Edited at

Cloud Vision APIをAndroidで使って感情検知する。

More than 1 year has passed since last update.

この記事はMonstar Lab, Inc. Advent Calendar 2016 12日目の記事です。

遅まきながらCloud Vision APIです。

Type=FACE_DETECTION(顔認識)でやってみます。


Google Cloud Vision API

公式

Google Cloud Vision APIを使ってみた


お値段

料金表

ユニット単位での請求となる。

1000ユニットまでなら無料で使える。

ユニットは画像の枚数のことではない。

1画像に対して"顔認識とラベル検知"としてAPI利用した場合、2ユニット利用となる。


APIキーの発行

実装前の準備です。

Google Developers Consoleに請求先情報を未登録の方はクレジットカードを握りしめて作業を開始してください。

※無料トライアルでも登録必須です。



  1. 公式からコンソールを開く

  2. 請求先情報などの入力を行う

  3. 新規にプロジェクトを作成


  4. Google Cloud API -> Vision APIを選択


  5. 有効にする -> 課金を求められるのでOK


  6. 認証情報 -> 認証情報を作成 -> APIキーを選択

  7. とりあえず制限なしでAPIキーを作成


実装

公式サンプルがあります。

Type=LABEL_DETECTION(物体の分類)になっているので、リファレンスを見ながら、必要なところを顔認識に書き換えます。

簡単に、1人だけ写ってる画像から表情(感情)を抽出する、という内容にします。


Feature typeの書き換え


before


MainActivity.java

annotateImageRequest.setFeatures(new ArrayList<Feature>() {{

Feature labelDetection = new Feature();
labelDetection.setType("LABEL_DETECTION");
labelDetection.setMaxResults(10);
add(labelDetection);
}});


after


MainActivity.java

annotateImageRequest.setFeatures(new ArrayList<Feature>() {{

Feature labelDetection = new Feature();
labelDetection.setType("FACE_DETECTION");
labelDetection.setMaxResults(1);
add(labelDetection);
}});

結果は1件だけ取得するようにします。


結果取得対象の書き換え


before


MainActivity.java

private String convertResponseToString(BatchAnnotateImagesResponse response) {

String message = "I found these things:\n\n";

List<EntityAnnotation> labels = response.getResponses().get(0).getLabelAnnotations();
if (labels != null) {
for (EntityAnnotation label : labels) {
message += String.format("%.3f: %s", label.getScore(), label.getDescription());
message += "\n";
}
} else {
message += "nothing";
}

return message;
}



after


MainActivity.java

private String convertResponseToString(BatchAnnotateImagesResponse response) {

String message = "I found these facial expressions:\n\n";
List<FaceAnnotation> labels = response.getResponses().get(0).getFaceAnnotations();
if (labels != null) {
for (FaceAnnotation label : labels) {
message += String.format("Joy:%s", label.getJoyLikelihood());
message += "\n";
message += String.format("Sorrow:%s", label.getSorrowLikelihood());
message += "\n";
message += String.format("Anger:%s", label.getAngerLikelihood());
message += "\n";
message += String.format("Surprise:%s", label.getSurpriseLikelihood());
}
} else {
message += "nothing";
}

return message;
}


(とても雑で申し訳ないです。。。)


結果

Likelihoodの言葉が示すとおり、「喜んでいる(楽しそうな)表情である可能性」という形で返ってきます。

値の意味はこちらにある通りです。

UNKNOWNを除いて5段階評価となっています。

なお、そもそも"人でない場合"は結果は0件となります。


精度(の感想)

そんなに細かく検証したわけではないので、感想レベルに留まります。


  • 正面向きでハッキリした表情なら"VERY_LIKELY"となる。

  • 帽子をかぶっていても大丈夫だが、目元が暗くなると判別できなくなる。

  • 横向きでもハッキリした笑顔なら大丈夫。

  • "くしゃっとした笑顔"はJoyとSorrowの両方が"LIKELY"や"POSSIBLE"となり、曖昧。

  • 真顔は全て"VERY_UNLIKELY"。

  • 笑顔は精度出るが、他は微妙な気がする。

  • モノクロ画像は結果が曖昧になる。


    • 元は結果の得られた画像も、モノクロにすると全て"VERY_UNLIKELY"になる、など。



  • 写実的なら絵でも銅像でも"顔"と判断される。


    • モナリザ:OK(無表情あつかい)

    • 阿修羅像:OK(無表情あつかい)

    • 三億円事件のモンタージュ写真:OK(機械には悲しんでる様に映るらしい)

    • 森気楼氏の絵:OK(感情も結構取れる!)

    • 西村キヌ氏の絵:NG

    • アニメのキャラクター:NG




まとめ

20年前から好きでしたが、改めて森気楼氏の絵は素晴らしいと思いました。

それが言いたかっただけです。