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 件のコメント:
コメントを投稿