Emotion API and POST and HTTP requests library

edited January 2017 in Library Questions

Hi all.

I have tried to resolve this to no avail. I just don't know what I'm doing wrong. I really hope someone out there can point me in the right direction. Apologies if my use of terminology is occasionally bogus below - network stuff is not my usual bag.

Basically, I'm trying to use the Microsoft Emotion API in Processing: https://dev.projectoxford.ai/docs/services/5639d931ca73072154c1ce89/operations/563b31ea778daf121cc3a5fa It requires API key authentication and HTTP headers as a POST request. I found the HTTP requests library (by Shiffman et al) which apparently takes the pain away (heh) and built a test example below:

import http.requests.*;
PostRequest post;

void setup() {
  size(400, 400);
  makeRequest();
  //println("Reponse Content: " + post.getContent());
  //println("Reponse Content-Length Header: " + post.getHeader("Content-Length"));
  JSONObject response = parseJSONObject(post.getContent());
  println(response);
}

void makeRequest() {  
  post = new PostRequest("https://" + "westus.api.cognitive.microsoft.com/emotion/v1.0/recognize");
  post.addHeader("Content-Type", "application/json");
  post.addHeader("Ocp-Apim-Subscription-Key", MyAPIkeyGoesHere);
  post.addData("url", "http://" + "www.boro.gr/contentfiles_2016/psyxologia/thymos/axaaamm.jpg");
  post.send();
}

What I should get back is a JSON file that looks like this:

  {
    "faceRectangle": {
      "height": 216,
      "left": 225,
      "top": 90,
      "width": 216
    },
    "scores": {
      "anger": 9.38430444E-11,
      "contempt": 3.36862873E-12,
      "disgust": 4.649468E-11,
      "fear": 1.913897E-11,
      "happiness": 1.0,
      "neutral": 7.306441E-11,
      "sadness": 1.65613755E-11,
      "surprise": 2.97461256E-09
    }
  }

... but what I get is this:

{"error": {
  "code": "BadBody",
  "message": "JSON parsing error."
}}

Anybody know what's going on? Also, if I was wanting to upload an image locally, how would I do that? Apologies for lameness, but am very grateful for any help. Thanks.

Kind regards, Paul.

Answers

  • post.addData("url", "http://" + "www.boro.gr/contentfiles_2016/psyxologia/thymos/axaaamm.jpg");

    the docs say that the request body should be json, but this is just adding a posted variable (using, probably, as a multipart form).

    if you call post.getContent() (before the send) you should see this.

  • edited January 2017 Answer ✓

    those docs in full:

    Request body: application/json
    { "url": "http://example.com/picture.jpg" }

    if you use this file:

    https://github.com/acdean/HTTP-Requests-for-Processing/blob/master/src/http/requests/PostRequest.java

    saved as PostRequest.java in you sketch directory, instead of the Http-Requests library, then that adds an addJson(String json); method whic will do what you need. but you'll need to create a json string with your data in it first (just "{\"url\": \"" + url + "\"}" should do it).

  • Hi koogs. Thanks for getting back so quickly. So I've created a .java file from the GIThub source and dropped it into the same directory as my Processing .pde file. So there is no need to include the other library now?

  • you might need to leave the import in place so it can find the new class, but it should find the local one before the library one. i can't quite remember - it's my class, i haven't used it other than to test it for someone else 8)

  • Hah! Excellent. It responds as it should now. Thank you so much. I'm not entirely sure why it works now but I'll look into it. Final question - if I wanted to upload a local image to the API instead of pointing to a URL, how would I do this?

  • i don't think you can with that library (or mine) - docs say to just post the binary data as the body, but i don't think you can, the library always needs a name which will make it an invalid request.

    application/octet-stream [binary image data]

    i'm struggling to get my own library to work this end, can't work out the imports 8)

  • (ok, got it now 8)

  • edited January 2017

    Cool. I notice that I have to trim the square brackets form the raw response before converting it to a JSON object, and I'm not sure why:

        String s = post.getContent();
        s = s.substring( 1, s.length()-1 );
        JSONObject response = parseJSONObject(s);
    

    If it's not possible to upload a binary file then I may have to resolve some image uploader routine before sending the URL in the POST query. Seems awfully heavy-handed. Let me know if you have any insight into this - I'd really appreciate it.

  • you could modify that class to do it for you... add an addData(byte[]); method. it would need to setEntity() to that data, and set the correct content-type header (httpPost.addHeader("content-type", "application/octet-stream");), probably 10-20 lines of code. (and an example).

    the square brackets probably means it gets treated as an array, an array containing 1 thing

  • I'm not confident I could manage that class update to be honest. A workaround for me is to use Flickr to upload, get the URL and feed that to this. If you were to be able to find some time to update the class then I'm sure it would be very useful not only to me but to other lamers like me! So if you do, please report back to this thread if possible. Thanks a lot for all your help. Really appreciated.

  • Answer ✓

    i have changed that file. it now does binary data

    https://github.com/acdean/HTTP-Requests-for-Processing

    addData(byte[] data);  
    addData(String contentType, byte[] data);
    addDataFromFile(String fullPathname);
    addDataFromFile(String contentType, String fullPathname);
    

    and also method(String put); to allow you to make PUT requests as well as just POSTs. (and DELETE for GetRequest).

    it's getting a bit messy because it's an extension of the original. would be neater to redo it from the beginning, as a Builder perhaps.

    if you check it out, change the build.properties file and then build it with ant it'll all work, honest.

  • Fantastic - works great. Thanks!

  • I came across this post when looking for a solution for Azure. I just added the HTTPClient library in the code folder (so need to use the modified HTTP-Requests library. I've put an example online to show how to post and process a picture with the Azure Face API (gives more data then the Emotion API).

    https://www.kasperkamperman.com/blog/using-azure-cognitive-services-with-processing/

  • I've just seen this response. Fantastic! Thanks kasperkamperman

  • The point of the processing library is, as usual, to simplify things, so that you don't have to call the massive, complicated HTTPClient library directly... But if there's functionality you need to use and you're comfortable doing it then that's fine.

    For instance, the above uses the following classes directly in the code, the processing library is (probably) capable of doing the same thing with one class.

    • URIBuilder
    • HttpPost
    • FileEntity
    • HttpClient
    • HttpResponse
    • HttpEntity
    • EntityUtils

    (But the more things people want, the more complicated it's getting, to the point where the original design might need a rethink)

Sign In or Register to comment.