MLKit for Firebase触ってみた(2) -顔認識編-

 MLKit for Firebase、2つ目は顔認識です!

  • 概要/事前準備編: Link
  • 文字認識編: Link
  • 顔認識編: この記事
  • バーコードスキャン編: 執筆中…
  • 物体認識編: 執筆中…

TL;DR

顔の位置、顔のパーツの位置、左右の目が閉じているor開いている、笑顔判定等ができます。
文字認識APIとの大きな違いとして、On-deviceのAPIのみ用意されていることが挙げられます。


実装

コードを書く前の準備

文字認識の時と同じく、ライブラリの追加とAndroidManifestのmeta-dataへの追記をします。

app.gradle

dependencies {
    ...
    implementation 'com.google.firebase:firebase-ml-vision:16.0.0'
    ...
}

AndroidManifest.xml

<application
    ...
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name">
    ...
    <!-- 追記 -->
    <meta-data
        android:name="com.google.firebase.ml.vision.DEPENDENCIES"
        android:value="face" />
    ...
</application>

コーディング

1.FirebaseVisionImageのオブジェクトを取得

FirebaseVisionImageをオブジェクトを取得します。文字認識の時と同じ手順のため、ここでは割愛します。

2.FirebaseVisionFaceDetectorのインスタンスを取得

val detector: FirebaseVisionFaceDetector = FirebaseVision.getInstance()
        .visionFaceDetector

この時、FirebaseVisionFaceDetectorOptionsクラスで設定した顔認識オプションをgetVisionFaceDetectorメソッドに渡すことができます。

val options: FirebaseVisionFaceDetectorOptions = FirebaseVisionFaceDetectorOptions.Builder()
            .setModeType(FirebaseVisionFaceDetectorOptions.ACCURATE_MODE)
            .setLandmarkType(FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS)
            .setClassificationType(FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS)
            .setMinFaceSize(0.1f)
            .setTrackingEnabled(false)
            .build()

設定可能なオプションを順に解説します。

setModeType
 速度を優先するか、認識精度を優先するかを指定します。

  • ACCURATE_MODE: 認識精度を優先する
  • FAST_MODE: 速度を優先する(default)

setLandmarkType
 顔のパーツの位置を取得するか指定します。ALL_LANDMARKを指定した場合、目・耳・口・頬・鼻の位置をそれぞれ取得できます。

  • ALL_LANDMARKS: 顔のパーツの位置を取得する
  • NO_LANDMARKS: 顔のパーツの位置を取得しない(default)

setClassificationType
 表情判定をするか指定します。ALL_CLASSIFICATIONを指定した場合、左右の目の開閉判定・笑顔判定ができます。

  • ALL_CLASSIFICATION: 表情判定をする
  • NO_CLASSIFICATION: 表情判定をしない(default)

setMinFaceSize
 認識可能な顔の最小サイズを指定します。サイズは「画像の幅に対する顔の幅の割合」で指定します。0.1Fとした場合、画像幅の10%以上の幅の顔を認識するようになります。
なお、この値は厳密なモノではなく、指定した幅を若干下回るような顔も認識するようです。

setTrackingEnabled
 同じ人物の顔を追跡するか指定します。動画で同じ人物の顔の追跡をしたい場合のみtrue、それ以外の場合はfalseを指定します(defaultはfalse)。
静止画での顔認識判別の際、このオプションをtrueにしてしまうと、複数枚の異なる画像を連続で認識させた時に最初の1枚しか正しい結果を得ることができないため、注意が必要です。

3.各種リスナーを追加

detectImage()メソッドに、手順1で取得したFirebaseVisionImageオブジェクトを渡し、顔認識成功時/失敗時のリスナーをセットします。

val result: Task<List<FirebaseVisionFace>> = detector.detectInImage(image)
        .addOnSuccessListener { firebaseVisionFaces: List<FirebaseVisionFace>
            // 成功時
        }
        .addOnFailureListener { e: Exception ->
            // 失敗時
        }
        .addOnCompleteListener { task: Task<List<FirebaseVisionFace>> ->
            
        }

4.認識結果の展開

顔認識に成功すると、その結果としてFirebaseVisionFaceオブジェクトがリストで返ってきます。このオブジェクトに顔の位置・顔の傾きの情報と、オプションで指定したパラメータに対応する各種の値が格納されているため、これを展開するコードを書きます。

val boundingBox: Rect = firebaseVisionFace.boundingBox // 顔の位置
val rotY: Float = firebaseVisionFace.headEulerAngleY // 顔の傾き(画像に対して縦方向の軸)
val rotZ: Float = firebaseVisionFace.headEulerAngleZ // 顔の傾き(画像を手前から奥に貫く方向の軸)

// ALL_LANDMARKSを指定した場合
val leftEye: FirebaseVisionFaceLandmark = firebaseVisionFace.getLandmark(FirebaseVisionFaceLandmark.LEFT_EYE)
val rightEye: FirebaseVisionFaceLandmark = firebaseVisionFace.getLandmark(FirebaseVisionFaceLandmark.RIGHT_EYE)

val leftEyePoint: FirebaseVisionPoint = leftEye.point // 左目の位置
val rightEyePoint: FirebaseVisionPoint = rightEye.point // 右目の位置

// ALL_CLASSIFICATIONを指定した場合
val smilingProbability: Float = firebaseVisionFace.smilingProbability // 笑顔判定(0.0〜1.0、1.0に近いほど笑顔)
val leftEyeOpenProbability: Float = firebaseVisionFace.leftEyeOpenProbability // 左目の開閉判定(0.0〜1.0、1.0に近いほど開いている)
val rightEyeOpenProbability: Float = firebaseVisionFace.rightEyeOpenProbability // 右目の開閉判定(0.0〜1.0、1.0に近いほど開いている)

// setTrackingEnabledにtrueを指定した場合
val trackingId: Int = firebaseVisionFace.trackingId

実装したサンプルアプリの動作

実装したサンプルアプリの動作と実際のコードは以下の通りです。

コードはこちら→MLKitTest on GIthub
メインのFragmentの実装はこちら→FaceDetectionFragment.kt

感想

 表情判定まで含めてかなりの速度で認識でき、かつオフラインで実行可能なためなかなか魅力的だと思いました。前準備も少なく、文字認識よりも更に簡単に導入できます。
 ただ、3DCGやアニメ絵等の認識精度はかなり低く、リアルの写真用のAPIという位置づけになっているようです。デレステ・ミリシタMVの笑顔判定装置とか作りたかった

 内カメで顔の動きをトラッキングして、表情や頭の動きでアプリの動作を操作する機能とか作れたらめっちゃ面白そうヽ(´エ`)ノ

参考リンク

Pocket

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です