Android の Mobile Vision API を使って 顔検出する
の続きです。
概要
前回の記事では、画像ファイルから顔検出した。
今回の記事では、カメラからの連続画像から顔検出する。
公式サンプルコードでは、カメラの制御に
Mobile Vision API の CamearaSource を使っている。
この記事では、CamearaSource と同様の機能を持つ Cameara2Source を自作する。
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 クラスを作成する。
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