SYSTEM_KDです。
Google Play services 7.8 がリリースされ、新しいAPIが追加されたので、試してみたいと思います。
新しく追加されたAPIは、次の2つになります。
・Mobile Vision API
・Nearby Messages API
両方試してみたい所ですが、今回は「Mobile Vision API」の方を試してみたいと思います。
Mobile Vision APIを試す
そもそも、このAPIで何ができるかですが、画像や映像からリアルタイムに「顔」を認識できるようです。
画像から顔認識できるAPIは以前からありましたが、これはより多くの情報を認識できるようになっているようです。
具体的には、「目」「鼻」「口」「顔の向き」「目の開き」「笑顔」の情報を取得できるようです。
(おー!凄いですね!)
ということで、さっそくサンプルを取得して見てみたいと思います。
(サンプルはこちらにあるみたいです)
サンプルをそのまま動かして試しても良いのですが、ソースを見るのも兼ねて、別でプロジェクトを作成して、作っていきます。
(といっても、結局コピーするようなものですが^^;
では、さっそくサンプルからー。と言いたいとこですが、まずは準備を整えたいと思います。
Android SDK Manager で最新を取得。
Update 分をインストールします。
インストールできたら、次は「Google Play Services 7.8」が利用できるように、「build.gradle」へ1行追加
dependencies {
・・・
compile 'com.google.android.gms:play-services:7.8.0'}
本題のコード部分に入ります。
とりあえず、簡単そうな画像から顔を認識するのを試したいと思います。
サンプルを見てみると、下記の流れになっているようです。
1.画像を読込。
2.顔検出
3.画像と検出結果を表示
静止画の顔検出を行うだけなら、かなり簡単そうです。
顔検出の準備
とりあえず、1の画像読込は割愛して、2の顔検出部分部分ですが、
FaceDetector detector = new FaceDetector.Builder(getApplicationContext()) .setTrackingEnabled(false) .setLandmarkType(FaceDetector.ALL_LANDMARKS) .build();
こんな感じらしいです。
静止画なので、trackingはOFFで、「目」や「鼻」「口」などを検出するために、「.setLandmarkType(FaceDetector.ALL_LANDMARKS)」と設定しているようです。
顔を検出する
検出の準備ができたら、実際の検出を行います。
Frame frame = new Frame.Builder().setBitmap(bitmap).build(); SparseArray<Face> faces = detector.detect(frame);
えーと、「1.」で読み込んだ画像から、Frameを作ってやって、それを先ほど準備した顔検出に渡してやると、検出した顔パーツの位置が返ってくるといったところかな。
サンプルでは、顔検出が利用可能化(端末のGoogle Play services対応したバージョンに更新されているか)をチェックする処理をはさんでいるようですので、ちょっと変更して追加。
if (!detector.isOperational()) { Toast.makeText(getApplicationContext(), "残念ながらライブラリが更新されていないため、まだ未対応です", Toast.LENGTH_SHORT).show(); finish(); }
ちなみに、「Face」「FaceDetector」「Frame」は、Google Play servicesのものを利用する必要があります。
com.google.android.gms.vision.Frame; com.google.android.gms.vision.face.Face; com.google.android.gms.vision.face.FaceDetector;
結果表示
最後に検出結果の表示を行います。
サンプルでは、独自Viewを作って表示するようにしています。
(※R.id.faceViewは後述)
FaceView overlay = (FaceView) findViewById(R.id.faceView); overlay.setContent(bitmap, faces); detector.release();
Viewの中身はこの様になっておりました。
public class FaceView extends View { private Bitmap mBitmap; private SparseArray<Face> mFaces; public FaceView(Context context, AttributeSet attrs) { super(context, attrs); } /** * 表示を行う情報の設定 */ void setContent(Bitmap bitmap, SparseArray<Face> faces) { mBitmap = bitmap; mFaces = faces; invalidate(); } /** * 描画部分 * 画像の表示と検出結果の表示を行う */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if ((mBitmap != null) && (mFaces != null)) { double scale = drawBitmap(canvas); drawFaceAnnotations(canvas, scale); } } /** * ベースの画像表示(デバイスのサイズにスケーリングを行う) */ private double drawBitmap(Canvas canvas) { double viewWidth = canvas.getWidth(); double viewHeight = canvas.getHeight(); double imageWidth = mBitmap.getWidth(); double imageHeight = mBitmap.getHeight(); double scale = Math.min(viewWidth / imageWidth, viewHeight / imageHeight); Rect destBounds = new Rect(0, 0, (int)(imageWidth * scale), (int)(imageHeight * scale)); canvas.drawBitmap(mBitmap, null, destBounds, null); return scale; } /** * 検出結果の表示 */ private void drawFaceAnnotations(Canvas canvas, double scale) { Paint paint = new Paint(); paint.setColor(Color.GREEN); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); for (int i = 0; i < mFaces.size(); ++i) { Face face = mFaces.valueAt(i); for (Landmark landmark : face.getLandmarks()) { int cx = (int) (landmark.getPosition().x * scale); int cy = (int) (landmark.getPosition().y * scale); canvas.drawCircle(cx, cy, 10, paint); } } } }
読み込んだ画像と、顔検出した結果が重ねて表示されるようになっています。
レイアウトで「R.id.faceView」にあたるものを用意しておけば、完成です。
<com.xxxx.xxxx.FaceView android:id="@+id/faceView" android:layout_width="match_parent" android:layout_height="match_parent" />
※FaceViewは、上記で用意した表示用のViewになります
実行結果
実行すると、検出した顔部分に緑の丸が描かれるようになっています。
実行する際の注意点ですが、エミュレータで実行される際は、通常の「System Image」ではなく、「Google APIs」のSystem Imageの方で実行する必要があります。
フリー素材の「ぱくたそ」から、モデルさんの顔写真を持ってきて試してみましたが、正面を向いている写真はちゃんと検出されました。
しかし、横向きや、斜めについては検出されませんでした。
(一度、正面で検出してトラッキングすれば、横とかが認識できるのかな??)
あと、複数人いる場合は、複数人検出されました。
まとめ
静止画像から、顔を認識するだけなら、かなり簡単にできるようです。
動画をトラッキングしながら、行うサンプルも見てみたい所ですが、難しそうなので、別の機会にみてみたいと思います^^;
あと、バーコードも認識できるようになったようなので、そのうち試してみたいと思います。
(そういえば、標準のバーコード認識機能っていままでなかったような・・)
0 件のコメント:
コメントを投稿