LoginSignup
4
0

More than 5 years have passed since last update.

AndroidからEmotion APIを使ってみる

Posted at

以前ブログの方に書いた記事ですが、誰もこないようなブログなのでQiitaの方がいいかなぁと思い改めて掲載

7/28から7/30に開催された石巻ハッカソンに参加してきました。

そこでAndroidからMicrosoft Cognitive Services のEmotion APIを使うことがあったので、その時のメモとして書いておこうと思います。

実装にあたって以下のサイトを参考にしました。
http://qiita.com/kosfuji/items/575408ae17113d7b58e9
http://qiita.com/a_nishimura/items/19cf3f60ad1dd3f66a84

公式の実装サンプルにjavaのコードはあったのですが、Android6.0からApache HTTP Clientのサポートが切られているため、HttpUrlConnectionを使う必要がありました。

準備

APIの利用にはSubscription Keyが必要になるため、ここからMicrosoftアカウントでログインしてSubscription Keyを取得します。

HTTP通信を行うので、INTERNETパーミッションを追加しておきます。

<uses-permission android:name="android.permission.INTERNET" />

実装例

 まず、通信用のスレッドを立てるためにAsyncTaskを継承したクラスを作成します。

public class ConnectToEmotionAPI extends AsyncTask<Void, Void, JSONObject> {
    @Override
    protected void onPreExecute() {
    }
    @Override
    protected JSONObject doInBackground(Void... params) {
    }
    @Override
    protected void onPostExecute(JSONObject result) {
    }
}

Emotion APIから画像を分析した結果がJSONで返ってくるので、doInBackgroundの戻り値はJSONObjectにします。

次に、doInBackground内に通信処理を書いていきます。

HttpURLConnection con = null;
URL url = null;
String urlStr = "https://westus.api.cognitive.microsoft.com/emotion/v1.0/recognize";
String key = "{Your Key}";                  //Subscription Key
DataOutputStream os = null;
BufferedReader reader;
JSONObject json = null;

try {
            url = new URL(urlStr);
            con = (HttpURLConnection)url.openConnection();
            con.setReadTimeout(10000);
            con.setConnectTimeout(20000);
            con.setRequestMethod("POST");
            con.setDoInput(true);
            con.setDoOutput(true);
            //リクエストヘッダーの設定
            con.setRequestProperty("Content-Type", "application/octet-stream");
            con.setRequestProperty("Ocp-Apim-Subscription-Key", key);

            // リクエストボディの作成
            Resources r = main_.getResources();
            Bitmap bmp = BitmapFactory.decodeResource(r, R.drawable.face_small);

            // 画像をバイナリデータに変換
            byte[] byteArray;
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, bos);
            byteArray = bos.toByteArray();

            os = new DataOutputStream(con.getOutputStream());
            for(int i =  0 ; i < byteArray.length;i++){
                   os.writeByte(byteArray[i]);
            }

            // APIに接続
            con.connect();
            os.close();

            int status = con.getResponseCode();

            switch (status) {
                case HttpURLConnection.HTTP_OK:
                    InputStream in = con.getInputStream();
                    reader = new BufferedReader(new InputStreamReader(in));
                    String line;
                    String readStr = new String();

                    while (null != (line = reader.readLine())){
                        readStr += line;
                    }
                    Log.d("EmotionAPI","read string: " + readStr);

                    in.close();

                    json = new JSONArray(readStr).getJSONObject(0);
                    break;

                case HttpURLConnection.HTTP_UNAUTHORIZED:
                    break;
                default:
                    break;
            }

} catch (MalformedURLException e){
            e.printStackTrace();
} catch (JSONException e){
            e.printStackTrace();
} catch (IOException e){
            e.printStackTrace();
}

return json;

画像を送信するにあたり、バイナリデータで送信するため、ByteArrayOutputStreamを使用します。

返ってくるJSONは配列形式なのでJSONArrayを使ってJSONをパースします。

最後にonPostExecuteで取得したJSONをオブジェクト名ごとにパースしています。

    @Override
    protected void onPostExecute(JSONObject result) {
        super.onPostExecute(result);

        JSONObject jsonData;
        String[] str = new String[2];
        try {
            jsonData = result.getJSONObject("scores");
            str[0] = jsonData.getString("happiness");
            str[1] = jsonData.getString("anger");
        } catch (Exception e){
            e.printStackTrace();
        }

        if (isSmile(str[0])) {
            Log.d("EmotionAPI","素敵な笑顔です!");
        } else if (isAnger(str[1])) {
            Log.d("EmotionAPI","そんなに怒らないでくださいよ~");
        } else {
            Log.d("EmotionAPI","つまんないです。何かリアクションしてください");
        }
    }

    public boolean isSmile(String strValue){

        double value = Double.parseDouble(strValue);
        if (value > 0.5) return true;
        else return false;
    }

    public boolean isAnger(String strValue){

        double value = Double.parseDouble(strValue);
        if (value > 0.5) return true;
        else return false;
    }

ハッカソンで実装したコードの方はGitHubに公開しているので、全体の実装の方はそちらをご覧ください。
Github EmotionAPI Sample

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0