Face Detectを使用して動画中の顔を認識させたいと思います。
が、しかし、残念なことにカメラからの入力映像以外はサポートしていないので、動画をデコードしてフレームを抽出し、それを静止画として解析することにします。

動画のデコード

動画のデコードはAndroidでも出来ますが、残念なことにフレームを取得できないので、JCodecを使用します。
JCodecはgradleに対応しているので、以下の設定をapp/build.gradleに設定することで使用することが可能になります。
app/build.gradle
android {
            : 省略
    configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.2'  // ★1
    }
}

dependencies {
            : 省略
    compile 'org.jcodec:jcodec:0.2.0'  // ★2
    compile 'org.jcodec:jcodec-android:0.2.0'  // ★3
}
★1: 「com.google.code.findbugs:jsr305」がJCodecと「com.android.support.test.espresso:espresso-core」の両方から引き込まれているけど、バージョンが異なるためにエラーになります。それを解消するために使用するバージョンを「3.0.2」に固定するために宣言が必要となります。
★2、3: JCodecを利用するために引き込むライブラリ

デコード処理の流れとしては以下のようになります。
  1. 動画ファイルからFrameGrabインスタンスを生成
  2. FrameGrabインスタンスからデコードしたい位置(フレームまたは時間: 秒)を指定して、Pictureインスタンスを生成
  3. Androidで処理できるようにPictureインスタンスをBitmapインスタンスへ変換
コードで記載すると以下のようになります。
  • 特定の位置(秒指定)のフレームを取得したい場合:
  • FrameGrabインスタンスにseekToSecondSloppy / seekToSecondPreciseでデコードを開始する位置を指定した後に、getNativeFrameで取得します。
    seekToSecondSloppyとseekToSecondPreciseの違いはseekToSecondPreciseは厳密に指定されたフレームを取得するために処理が遅く、
    seekToSecondSloppyは正確なseekは行わないけどの、処理速度が早いといったメリットがあります。
    // movieFilePath: スキームなしの動画ファイルのパス
    FrameGrab grab = FrameGrab.createFrameGrab(NIOUtils.readableChannel(movieFilePath));
    Picture picture = grab.seekToSecondSloppy(second).getNativeFrame();
    Bitmap frameBitmap = AndroidUtil.toBitmap(picture);
                            :
    
    秒で指定するのではなく、フレーム位置で指定したい場合は、seekToFrameSloppy / seekToFramePreciseを使用します。

  • 全てのフレームを取得したい場合:
  • seekせずに先頭から順次読み込んでいきます。
    // movieFilePath: スキームなしの動画ファイルのパス
    FrameGrab grab = FrameGrab.createFrameGrab(NIOUtils.readableChannel(movieFilePath));
    Picture picture = null;
    while((picture = grab.getNativeFrame()) != null){
        Bitmap frameBitmap = AndroidUtil.toBitmap(picture);
                            :
    }
    

サンプルアプリ

ここにサンプルアプリを置きました。 試してみる場合は、以下の手順で確認してみてください。
※ ストレージにある動画ファイルの一覧を表示後、それを選択することで、1秒間隔のフレームに分割します。フレームを選択すると顔認識が動作するようになっています。
  1. ここから環境をクローン
  2. タグ"v0.2.0"をチェックアウト
  3. ビルドしてAPKをインストール
  4. "Face Detect from Movie"を選択
  5. デバイスに格納されている動画が表示されるので、顔認識したい動画をタッチ
  6. タッチすると、動画を1秒間隔のフレームに分割して表示するので、顔認識したいフレームをタッチ

コメントの投稿