JSで顔認識(Face Detection)

  • 85
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

会社のAdvent calendarと同じ内容をあげようと試みたのですが、ダメでした。。orz
遅れてすみません...

最近顔認識(Face Detection)のイケてるサイト公開されてたのに影響されてちょっと調べてみました。

いくつかライブラリがあるようですね。

clmtrackr

jQuery FaceDetection

今回はサンプルも充実していたいのでclmtrackrを利用します。

clmtrackrでできること

Face Detectionでやりたいことは一通りできるようです。
目、鼻、口、輪郭、眉毛の認識から、それらの位置ベクトルの取得。画像、動画どちらも対応可能なようです。

解析の入力サイズは小さい方がパフォーマンスはでますが、MBPであれば、640x520とかでもサクサク動きます。
実際に動かしてみながら動作を確認していきます。exampleディレクトリ内のsample.htmlを元に紹介します。

下準備

HTMLを用意し、まずはjsを設定します。

<script src="../clmtrackr.js"></script>
<script src="../models/model_pca_20_svm.js"></script>

2つ目のmodel_pca_20_svm.jsはおそらく顔判定のデータです。
顔認識では判定データを元に解析します。この手のデータは最近はやりのDeepLearningなどで、改善しながら作成したりすると思います。0からFace Detectionを作る場合はOpenCVなどのデータを流用するのが良いと思います。

これでFace Detectionの準備ができました。

入力データを用意する

判定するための元となる入力データを準備します。これはVideo、画像、Webカムなど用途に応じて使い分けます。まずはVideoを使います。VideoタグをHTMLに書きます。JSでアクセスするのでidを設定します。

<video id="inputVideo" width="400" height="300" autoplay loop>
    <source src="動画のパス" type="video/ogg"/>
</video>

出力データを表示する

入力データから判定し、出力データを反映する場所を用意します。
判定した顔のアウトラインデータをcanvasに描画します。

<canvas id="canvas" width="400" height="300"></canvas>

HTMLの準備は最低限これでOKです。

clmtracker.jsを利用する

JSを記述します。最初に入力データとなるDOM要素を取得します。

var videoInput = document.getElementById('inputVideo');

次にclmtrackerインスタンスを作成し初期化します。初期化の引数にpModelを渡しますが、これはmodel_pca_20_svm.js内で定義されている変数です。

var tracker = new clm.tracker();
tracker.init(pModel); // ここで初期化、引数にpModelを渡す。

これを実行すると、videoの最初のフレーム画像を解析し判定します。
判定した結果はgetCurrentPosition()で取得できます。

// positions = [[x_0, y_0], [x_1,y_1], ... ] 配列が帰ります。
var positions = tracker.getCurrentPosition(); // 解析されて位置ベクトル情報

このpositonsで取得したデータにたいしてテクスチャーを貼り付けたり、各ベクトル情報を操作することで顔を動かすようなアニメーションを作ることができます。顔ぐにゃ〜っとさせたりするやつです。

Videoの動きに合わせて判定する

このままでは1フレーム目のみの判定になるので、毎フレーム判定するためにはtracker.start()を使います。

// 引数には入力用のDOM要素を渡します。2番目の引数で入力位置を設定できるようです。
tracker.start(videoInput);
var box = [0, 0, 400, 260];
tracker.start(videoInput, box);

結果を出力する

var canvasInput = document.getElementById('canvas');
var cc = canvasInput.getContext('2d');

function drawLoop() {
   requestAnimationFrame(drawLoop); // ここで毎フレームdrawLoopを呼び出すように設定します。
   cc.clearRect(0, 0, canvasInput.width, canvasInput.height); // 毎フレーム出力用のキャンバスをクリアします。これをしないと重ね書きのようになってしまいます。
   tracker.draw(canvasInput); // 判定結果をcanvasに描画します。
}
drawLoop();

これで結果が簡単にみれます。表現物を作る場合は、途中で取得したpositionsの値をうまく操作することでいろいろできると思います。

画像からの解析、webカムのバージョンはこちらのアドベントカレンダーで書いてきます。