Android の Camera2 API と Mobile Vision API を使って 顔検出する


Android の Mobile Vision API を使って 顔検出する
の続きです。

概要

前回の記事では、画像ファイルから顔検出した。
今回の記事では、カメラからの連続画像から顔検出する。

公式サンプルコードでは、カメラの制御に
Mobile Vision API の CamearaSource を使っている。

この記事では、CamearaSource と同様の機能を持つ Cameara2Source を自作する。

reference: CameraSource

Android の Camera2 API を使って カメラのプレビュー画面を表示する
にて紹介し下記のコードを参考にした

Basic functionalities of both Camera1 API and Camera2 API with a Google Vision Face Detector added

カメラからの連続画像から顔検出する

画像ファイルから顔検出する場合は、Frame.Builder#setBitmap を使用した。

カメラからの連続画像から顔検出する場合は、Frame.Builder#setImageData を使用する。

reference: Frame.Builder#setImageData

画像は、NV21形式のバイト配列で指定する。

カメラからは YUV_420_888 形式で取得し、 NV21形式に変換する。

ImageReader

カメラからの連続画像をキャプチャーするための ImageReader を生成する。

ImageReader の使い方は、下記の記事を参考に。
Android の Camera2 API を使って 写真を撮る

// YUV_420_888 形式の画像の大きさを取得する
    StreamConfigurationMap map = characteristics.get(
        CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
    Size imagePreviewSize = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.YUV_420_888)), new CompareSizesByArea());

// YUV_420_888 形式のImageReader を生成する
    ImageReade imageReaderPreview = ImageReader.newInstance( imagePreviewSizegetWidth(), imagePreviewSize.getHeight(), ImageFormat.YUV_420_888, 4);

// リスナーを設定する
    imageReaderPreview.setOnImageAvailableListener(previewAvailableListener, mBackgroundHandler);

// リスナー
    ImageReader.OnImageAvailableListener previewAvailableListener = new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
    // 連続画像を FrameProcessor に渡す
            frameProcessor.setNextImage(reader.acquireNextImage());
        } 
    }; 

FrameProcessor

カメラからの連続画像を受け取り FaceDetector に渡すためのクラスです。
基底となるクラスはないので、スクラッチから自作する。

class Camera2FrameProcessor implements Runnable {

    public void setNextImage(Image image ) {
        // カメラからの連続画像を受け取る
    }

    @Override
    public void run() {
        // 連続画像を FaceDetector に渡す
        detector.receiveFrame(outputFrame);
    }
}

FaceTracker

FaceDetector から顔検出の結果を受け取るためのクラスです。
Tracker を継承して FaceTracker クラスを作成する。

reference: Tracker

onUpdate に結果が入る。

class FaceTracker extends Tracker<Face> {

        @Override
        public void onUpdate(FaceDetector.Detections<Face> detectionResults, Face face) {
            // 顔検出の結果の処理
        }
}

検出した顔の上にランドマークを表示する

下記の記事と同じような処理を行う。
Android の Camera2 API を使って 顔検出する

ViewGroup を継承した CameraSourcePreview を作成する。
CameraSourcePreview の子のビューとして、カメラのプレビュー画面を表示する TextureView とランドマークを表示するオーバーレイ用の View を作成する。

View の大きさに合うように、View と ImageReader の大きさの比率を求め、ランドマークの位置を調整する。

スクリーンショット

サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/Vision2