2017.06.30

Mobile Vision APIを使って簡単なARアプリを作ってみた


はじめに


こんにちは。次世代システム研究室のT.D.Qです。
前回はGoogleの「Cloud Vision API」を試しました。今回はGoogleのMobile Vision APIというライブラリを用いて簡単なARアプリを作ってみたいと思います。

Mobile Vision API

GoogleがGoogle Playサービス7.8から「Mobile Vision API」という新しい API を発表しました。
Mobile Vision APIは、画像や動画で人物の顔を認識する機能を提供するAPIで、処理が高速で精度が高く、口や鼻などの顔のパーツを個別に識別することや笑顔や目の開いている状態を識別することができます。Androidだけではなく、iOSもサポートしています。APIの詳細はこちらです。

簡単なARアプリ

今回の記事ではこのMobile Vision APIを使って以下のことを実現します。
1.スマホ(今回はAndroid)のカメラの映像から顔を認識し、トラッキングする
2.目の部分に2D画像(メガネ)を表示する

実現方法

face-tracker-pipeline
Google Mobile Vision APIの顔認識パイプライン図

アプリが起動されると、カメラが画像をパイプラインに連続して送信します。 CameraSourceコンポーネントは、これらの画像の受信を管理し、上記で指定された最大30フレーム/秒で画像をFaceDetectorに渡します。FaceDetectorで認識した人間の顔をGraphicTrackerに渡して、顔をトラッキングします。同時に、目や口などもトラッキングされるので、目の位置と顔のサイズを合わせて2D画像(メガネ)を表示することで今回のアプリを実現します。

Mobile Vision APIのライブラリ導入

Face APIを使用するためにbuild.gradleに次のコードを追加します。
dependencies {
    compile 'com.google.android.gms:play-services-vision:7.8.0'
}

AndroidManifest.xmlのmanifestタグの間に以下を記載。
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />
AndroidManifest.xmlのapplicationタグの間に下記追加。
<meta-data
            android:name="com.google.android.gms.vision.DEPENDENCIES"
            android:value="face" />

カメラの設定


アプリのメインアクティビティにてカメラソースを設定します。端末の裏・表のカメラを指定できます。
Context context = getApplicationContext();
FaceDetector detector = new FaceDetector.Builder(context)
       .setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
        .build();

detector.setProcessor(
        new MultiProcessor.Builder<>(new GraphicFaceTrackerFactory())
            .build());

mCameraSource = new CameraSource.Builder()
        .setRequestedPreviewSize(640, 480)
        .setFacing(CameraSource.CAMERA_FACING_BACK)
        .setRequestedFps(30.0f)
        .build(getApplicationContext(), detector);

※※上記は重要な箇所の抜粋です。詳細はこちらをご確認ください。

カメラの映像から顔を認識

GraphicFaceTrackerが人間の顔を認識できると、FaceGraphicにFace(人間の顔情報)を渡します。なので、今回FaceGraphicクラスで認識した顔からLandmark情報(目、口、鼻などの情報)を取得して、そのLandmark情報を基づいて2D画像の追加表示を実装します。

まず、認識した顔から情報を抽出して表示する。
// トラッキングしている顔の中央点に丸いマークを描く
float x = translateX(face.getPosition().x + face.getWidth() / 2);
float y = translateY(face.getPosition().y + face.getHeight() / 2);
canvas.drawCircle(x, y, FACE_POSITION_RADIUS, mFacePositionPaint);
canvas.drawText("id: " + mFaceId, x + ID_X_OFFSET, y + ID_Y_OFFSET, mIdPaint);
canvas.drawText("幸せ度: " + String.format("%.2f", face.getIsSmilingProbability()), x - ID_X_OFFSET, y - ID_Y_OFFSET, mIdPaint);
        
// トラッキングしている顔の範囲を可視化するため、四角形を描く
float xOffset = scaleX(face.getWidth() / 2.0f);
float yOffset = scaleY(face.getHeight() / 2.0f);
float left = x - xOffset;
float top = y - yOffset;
float right = x + xOffset;
float bottom = y + yOffset;
canvas.drawRect(left, top, right, bottom, mBoxPaint);

// トラッキングしている顔のLandmarkを可視化する
for (Landmark landmark : face.getLandmarks()) {
    float cx = translateX(landmark.getPosition().x);
    float cy = translateY(landmark.getPosition().y);
    canvas.drawCircle(cx, cy, FACE_POSITION_RADIUS, mFacePositionPaint);
}

結果は以下の画像の通りです。

ar_vision-1


画像ソース:男性の顔(University Regensburg, Germany)


カメラの映像にオブジェクトを追加する

FaceGraphicクラスにて以下のソースコードで、顔のサイズと目の位置と合わせてメガネ画像が表示されます。

if (landmark.getType() == 10) {
        float cx = translateX(landmark.getPosition().x);
        float cy = translateY(landmark.getPosition().y);
        canvas.drawCircle(cx, cy, FACE_POSITION_RADIUS, mFacePositionPaint);
        RectF dsc = new RectF(left, cy - yOffset/4, right, cy + yOffset/4);
        canvas.drawBitmap(sunglassesBitmap, null, dsc, null);
    }
}

アプリをビルドして動作確認

アプリをビルドして以下の結果になります。ちゃんとメガネが表示されています。頭が動いているときメガネも同時に動きます。Facebook messengerのAR機能みたいですね。
ar_vision-2



所感


今回、Mobile Vision APIを使ってカメラの映像から認識した顔の部分(目)に好きなオブジェクト(メガネ)を追加することで簡単なARアプリを作ってみました。AR用のSDKを使わないので、やはりオブジェクトの位置やサイズが自分でいろいろ計算しないといけないですが、機械学習がこれからも進化していくので、いろいろなオブジェクトを認識できるようになり、ARアプリも簡単に作れるようになってくると思います。

次世代システム研究室では、アプリケーション開発や設計を行うアーキテクトを募集しています。アプリケーション開発者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。