Googleが提供しているMobile Vision APIの内、顔認識用のAPI "Face"を試してみました。
今回は、静止画を対象にした顔認識のみとなります(次回、カメラ動画で試してみたいと思います)。

環境設定

Mobile Visionを使用できるようにするには、"com.google.android.gms:play-services-vision"を依存関係として追加します。
最新のバージョンはここを見る限り、2017.08.29現在は"11.2.0"だったのですが、取得できなかったので、"11.0.0"を使用しました。

app/build.gradle
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.google.android.gms:play-services-vision:11.0.0'    // ★追加
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:recyclerview-v7:25.3.1'
}
これを設定することで、Mobile Vision APIが使用可能となります。

実装

静止画に対して、顔認識を行うのは比較的簡単な実装で行えます。
大まかな流れは以下のようになります。
  1. FaceDetector.Builderインスタンスを生成し、それから顔認識条件が設定されたFaceDetectorインスタンスを生成
  2. Frame.Builderインスタンスを生成し、それから静止画像が設定されたFrameインスタンスを生成
  3. FaceDetectorインスタンスにFrameインスタンスを設定して、顔認識を実施
顔認識を実施すると、その静止画から認識できた顔の情報を保存した、Faceインスタンスのリストが取得できます。
また、Faceインスタンスの中に、顔のパーツ(目、鼻、口、ほほなど)の位置を保存したLandmarkインスタンスのリストが格納されています。
これを駆使することで、静止画中の顔の位置と、顔のパーツの位置を知ることができます。

FaceDetector.Builderインスタンスを生成し、それから顔認識条件が設定されたFaceDetectorインスタンスを生成

app/src/main/java/jp/eq_inc/testmobilevision/fragment/FaceDetectFromPhotoFragment.java - FaceDetectTask.onPreExecute
  FaceDetector.Builder builder = new FaceDetector.Builder(activity);

  // classification
  SwitchCompat tempSwitch = (SwitchCompat) activity.findViewById(R.id.scClassification);
  if (tempSwitch.isChecked()) {
      builder.setClassificationType(FaceDetector.ALL_CLASSIFICATIONS);
  } else {
      builder.setClassificationType(FaceDetector.NO_CLASSIFICATIONS);
  }

  // landmark
  tempSwitch = (SwitchCompat) activity.findViewById(R.id.scLandmark);
  if (tempSwitch.isChecked()) {
      builder.setLandmarkType(FaceDetector.ALL_LANDMARKS);
  } else {
      builder.setLandmarkType(FaceDetector.NO_LANDMARKS);
  }

  // mode
  tempSwitch = (SwitchCompat) activity.findViewById(R.id.scDetectMode);
  if (tempSwitch.isChecked()) {
      builder.setMode(FaceDetector.FAST_MODE);
  } else {
      builder.setMode(FaceDetector.ACCURATE_MODE);
  }

  // prominent face only
  tempSwitch = (SwitchCompat) activity.findViewById(R.id.scProminentFaceOnly);
  builder.setProminentFaceOnly(tempSwitch.isChecked());

  mFaceDetector = builder.build();
設定できる条件としては、以下のものがあります。
設定名称設定名称概要設定値
classificationType目が空いているとかスマイルなどの状態を取得可否
概要
NO_CLASSIFICATIONS
デフォルト
目の開きやスマイル判定なし
ALL_CLASSIFICATIONS目の開きやスマイル判定あり
landmarkType目や鼻などの顔のパーツの取得可否
概要
NO_LANDMARKS
デフォルト
目や鼻など顔のパーツの場所特定なし
ALL_LANDMARKS目や鼻など顔のパーツの場所特定あり
proportionalMinFaceSize認識する顔の最小サイズ。小さい値を入れるほど認識率は上がるが、速度が劣化する 値は解析する画像幅を1としたときの割合。
デフォルト値はprominentFaceOnlyの指定により異なる。
prominentFaceOnly OFF: 0.1
prominentFaceOnly ON: 0.35
mode顔認識時の動作として精度を上げるか速度を上げるかのモード選択
概要
FAST_MODE
デフォルト
顔認識の速度重視
ACCURATE_MODE顔認識の正確さ重視
prominentFaceOnly一番目立つ顔のみ取得するか否か
概要
true一番目立つ顔のみ取得
false
デフォルト
認識した全ての顔情報を取得
trackingEnabled認識した顔を以後追い続けるか否か
概要
true認識した顔を追い続ける
false
デフォルト
追わない

Frame.Builderインスタンスを生成し、それから静止画像が設定されたFrameインスタンスを生成

app/src/main/java/jp/eq_inc/testmobilevision/fragment/FaceDetectFromPhotoFragment.java - FaceDetectTask.doInBackground
  Frame fullImageFrame = new Frame.Builder().setBitmap(fullImage).setRotation(rotation).build();

FaceDetectorインスタンスにFrameインスタンスを設定して、顔認識を実施

app/src/main/java/jp/eq_inc/testmobilevision/fragment/FaceDetectFromPhotoFragment.java - FaceDetectTask.doInBackground
  SparseArray detectedFaceArray = mFaceDetector.detect(fullImageFrame);

顔認識結果

いくつかの画像で、どんな結果が得られるか試してみました。

口元を隠した写真

口元を隠した写真に対して顔認識できるか否かの確認になります。
使用した写真のモデル・コピーライトなどは、以下のものとなります。
提供元ぱくたそ
モデル大川竜弥
コピーライトすしぱく
結果:
顔認識成功

怒り顔

怒り顔が写った写真に対して顔認識できるか否かの確認になります。
使用した写真のモデル・コピーライトなどは、以下のものとなります。
提供元ぱくたそ
モデル大川竜弥
コピーライトすしぱく
結果:
mode: accurateでも、顔認識できず。

横顔

横顔が写った写真に対して顔認識できるか否かの確認になります。
使用した写真のモデル・コピーライトなどは、以下のものとなります。
提供元ぱくたそ
モデル千歳
コピーライトすしぱく
結果:
顔認識成功。また、顔のパーツについても写っているものについては認識成功(写真の緑色に塗られている部分が認識している箇所になります)

目元が隠れている写真

目元が隠れている写真に対して顔認識できるか否かの確認になります。
使用した写真のモデル・コピーライトなどは、以下のものとなります。
提供元ぱくたそ
モデルゆうせい
コピーライトすしぱく
結果:
mode: accurateでも、顔認識できず。

イラスト

イラストに対して顔認識できるか否かの確認になります。
使用したイラストは、以下のものとなります。
提供元いらすとや
いらすと集合している人たちのイラスト
結果:
mode: accurateにおいて、4人だけ顔認識に成功。

mode: fastにすると、2人だけしか顔認識に成功しませんでした。

mode: accurate且つprominent face onlyを有効にすると、顔は認識されませんでした。
多分、顔認識はされているけども、どれを該当の顔としてよいか判断出来なかったと思われます。

おまけ

写真によっては、顔以外のものも顔として認識されることがあるようです。それも、mode: accurateの場合に。
使用した写真のモデル・コピーライトなどは、以下のものとなります。
提供元ぱくたそ
モデル河村友歌
コピーライトすしぱく
結果:
mode: fastの場合は認識されていないが、mode: accurateの場合のみ、ダッシュボード付近に顔として認識されるものが存在する。
mode: accurate mode: fast
さすがに、顔のパーツは認識されていませんが、こういったものはアプリで除去する必要がありそうです。

サンプルアプリ

ここにサンプルアプリを置きました。 試してみる場合は、以下の手順で確認してみてください。
  1. ここから環境をクローン
  2. タグ"v0.1.0"をチェックアウト
  3. ビルドしてAPKをインストール
  4. "Face Detect from Photo"を選択
  5. デバイスに格納されている写真が表示されるので、顔認識したい写真をタッチ

参考サイト

Detect Facial Features in Photos
Get Started with the Mobile Vision API
Set Up Google Play Services

コメントの投稿