カメラ映像で顔検出2016/08/04

前回の記事の通り、Androidアプリ「おかしな(ヵ_ォ)カメラ」では顔検出に Google Play Serivcesの FaceDetectorを使っています。

このAPIの基本的な使い方はチュートリアル等にありますが、今回はカメラの映像で顔検出をする場合の手順と、引っかかった所や気づいたところを解説してみます。

参考にするのは提供されているサンプル
その中(FaceTrackerの下じゃないけど)でも、カメラの映像を顔検出APIに送っているのは
あたりです。


◇手順
・Andoroidでのカメラ画像の表示
・FaceDetectorのプロジェクトへの組み込み
については省略します。

FaceDetectorの生成

FaceDetector detector = new FaceDetector.Builder(getApplicationContext()).build();

こんな感じで顔検出用のクラスを生成します。
このとき、いくつかのパラメータを設定することができますが、その中で使用してみて注意点があったものを挙げてみます。

・setMode(int)
 FAST_MODEで速度重視、ACCURATE_MODEで精度重視となります。
 顔の範囲やZ軸回転(首をかしげる)はどちらでも取得できますが、FAST_MODEではY軸回転(横を向く)が取れなくなりました(常に0が返る)。ちなみにX軸回転(うつむく、見上げる)は元々取得するメンバがありません。何故?

・setMinFaceSize(float)
 検出する顔の最小値(画面に対する比率)を設定します。
 ただこの関数で大きめの値を設定すると、Face.getWidth()や Face.getHeight()で得られる顔の大きさにズレが生じます(画面上の顔が小さくなるほど、実際の顔より大きめの値が返ってくる)。
 設定するとズレるというより設定する値が大きいとズレが顕著になっているようなのですが、残念ながら対処法はわかりません。

・setTrackingEnabled(boolean)
 リアルタイムの映像で検出を行う場合は trueに設定するのですが、ちょっと気を付けなければいけない点があります。それについては後述します。


カメラ映像の取得
このへんは顔検出特有の部分では無いので簡単に済ませます。

カメラ入力画像は、Camera.setPreviewCallbackWithBuffer(Camera.PreviewCallback)と Camera.addCallbackBuffer(byte[])でコールバックを設定して取得します。
CameraSourceでは createCamera()の最後の部分、そしてコールバック関数自体は CameraPreviewCallbackクラスの onPreviewFrame(byte[], Camera)です。
コールバック関数にデータが来る → 顔検出 の繰り返しとなります。

また、顔検出処理は時間がかかるので別スレッドで行います。
CameraSourceでは、FrameProcessingRunnableクラスでその処理を管理しています。


顔検出準備
取得した画像データから、Frameクラスを生成します。

Frame frame = new Frame.Builder().setImageData(data, width, height, ImageFormat.NV21).build();

YUV形式に対応していますのでカメラから取得したデータをそのまま使えます。

・画像の向き
 顔検出APIは、検出する顔と画像の上下が合っていることが前提となっています。
 カメラ画像は横向きなので、端末を縦に使う場合等は画像を回転する必要があります。

Frame frame = new Frame.Builder().setImageData(data, width, height, ImageFormat.NV21).setRotation(rotation).build();

 setRotation(int)によって回転角を指定します。
 引数は ROTATION_0 ~ ROTATION_270と、90°単位です。
 CameraSource(というよりFaceTracker)では、screenOrientationを fullSensorにして getDefaultDisplay().getRotation()から計算しています(大雑把に言うと)。

 さて前述の setTrackingEnabled(true)での注意点ですが、
 「おかしな(ヵ_ォ)カメラ」のようなリアルタイムで端末の向きを変えられるアプリの場合、setTrackingEnabled(true)としていると向きが変わったときにエラーが出て顔の検出ができなくなってしまいます。画像としては不連続になるからなんだとは思いますが。
 そのため端末の向きが変わったときは FaceDetectorを一旦 release()して生成し直す必要があります。


顔検出
 あとは FaceDetectorに Frameを放り込んで顔検出情報 Faceの配列を取得するだけです。

SparseArray <Face> faces = detector.detect(frame);

 CameraSourceは顔検出専用ではないので、汎用的にDetectorクラスの receiveFrame(Frame)を使っています。ご注意を。

 個々の検出情報は、valueAt(int)で取り出します。

for (int i = 0; i < faces.size(); i++) {
    Face face = faces.valueAt(i);

    // 顔で遊ぼう!
}

 Faceで得られる情報は、リファレンスからどうぞ。



「おかしなカメラ」再び2016/08/17

「おかしなカメラ・改」を通して、世の中を面白おかしく見てみよう!
カメラからの入力映像をリアルタイムに加工して表示する、面白カメラアプリです。


Androidアプリ「おかしなカメラ・改

おかしなカメラ・改


いろいろあるエフェクトの中から、いくつかご紹介します。

砂状 [じわじわ系]

砂人間

動きのあるものの描画をドット単位で遅らせて、砂でできているかのような表現をします。
これで君もサンシャインだ!


ゆらゆら(横)[ゆらゆら系]

ゆらゆら

いわゆるスリットスキャンで、ラインで描画フレームを遅らせることでゆらゆらした感じを出します。
一般的なスリットスキャンほどフレームが細かくなく、遅らせるフレームに限界があるのが残念ですが。


縮小 [変形・鏡系]

鍛えあげられた筋肉

画面中央が縮小するように画像を変形させます。
他に「拡大」「縦長」「横長」といった変形パターンがありますので、うまく使い分けてください。


ミニチュア風 [画像系]

ミニチュア風

簡易的なチルトシフトで、風景をミニチュアのように見せます。
高い所から下を見下ろすような場所で使用してください。





”改”とあるように、「おかしなカメラ」のバージョンアップ版です。
必要な Androidバージョンが上がったりエフェクトの見え方が変わったりしたので、単なるバージョンアップではなく別アプリとしました。

おかしなカメラ」を使っていて Android4.0.3以上の方は、ぜひこちらに差し替えてください。



まんがタイムスペシャル 10月号2016/08/24

ローカル女子の遠吠え
「富士宮焼きそば」ってのは富士宮市でしか食べられないものなんだろうか?
うなぎパイなんかは愛知県でも売ってるけど(たぶん本物)。

毎日がインドアライフ
朔君の胡散臭い言動とか、姉ちゃんの土に帰りたい発言とかサスペンスドラマの伏線みたいだな。

メェ~探偵フワロ
さて、今回は単なる漂流ネタなのか、ストーリーの重要な転換点なのか…
死を覚悟するところまでいってアーサーの心境にも変化がありそうだが、危険な目に合わせてしまったということで躊躇してしまいそうな感じもするし。


商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。お買い物される際には、必ず商品ページの情報を確認いただきますようお願いいたします。また商品ページが削除された場合は、「最新の情報が表示できませんでした」と表示されます。

光れ!メシスタント(1) [ 310 ]
価格:668円(税込、送料無料) (2016/8/24時点)