HTML5 videoでリアルタイム顔認識
以前、、ビデオのリアルタイムなヒストグラム表示を作ってみたが、思ったより高速だったので、もっと処理の重いものをやったらどうだろうと思い、JavaScriptで書かれた顔認識ソフトを利用して、ビデオに対してどのくらい可能なのかを試してみた。
JavaScriptによる顔認識ソフトは以下のものを利用。
中身を見ると、canvasにdrawImage()した画像をgetImageData()でピクセル情報を取得している。その際、モノクロ画像に変換してから認識している。また、動的にcanvasオブジェクトを生成してオリジナルの部分的な領域を抽出している。その先はちょっとブラックボックス。
で、ビデオのヒストグラム表示でやったときと同じように、ビデオを一旦canvasに縮小してdrawImageしてそのイメージに対して顔認識ソフトを適用してみた。
結果、非常い重い。1秒に2〜3コマ処理できる程度。β版と書かれているが、WebWorkerを利用したモードもあるので、それも試してみたが逆に重くなる。ヒストグラム表示のときもWebWorker版を作ったが、そのときもビデオの再生がカクカクしてしまうなど逆に遅くなった。ビデオとWebWorkerの組み合わせはどうも問題があるようだ。
そこで、JavaScriptのコードを改良することにした。顔認識の原理を知らないので、単純に機械的なコードの書き換えしかできないが、まず、以下を実行した。
1. 一時変数への代入
なぜか、以下のようなパターンが多い
x = foo[i].bar[j].func1(); y = foo[i].bar[j].func2(); z = foo[i].bar[j].func3();
これを
v = foo[i].bar[j]; x = v.func1(); y = v.func2(); z = v.func3();
とした
2. applyよりcall
なぜか、引数の数が固定なのに、わざわざ配列にしてapplyを実行している。配列を生成するのはムダだ。
fucn.apply(obj, [ arg1, arg2, arg3 ]);
これを以下のようにした。
func.call(obj, arg1, arg2, arg3);
3. for文の条件
一時変数への代入と同様であるが、以下のようなパターンが目立つ。
for (i = 0; i < foo[j].bar[k]; i++)
以下のようにした。
for (i = 0, n = foo[j].bar[k]; i < n; i++)
これらをやっても、それほどの効果はないだろうが、このようなコードを見るとつい直したくなる性分なので変更したというのが正直なところ。また、効果のなかったWebWorkerのコードをバッサリ削除し、自分好みに整形した。
結果は確かにあまり変わらない。そりゃそうだと思う。コードを単純に変更しただけはあまり効果はないので、もうちょっと効果のありそうな方法を次に試した。
4. canvasへdrawImage()するとき、もっと小さな画像にする
例えば 160x90 くらいにすると、かなり高速になる。でも、逆に認識率が低下してしまう。大きくもなく、小さくもなく、という適当な大きさにすればよさそうなので、ちょっと試してみて320x180に落ち着いた。
5. モノクロへの変換をやめてみる
情報量的にはカラーのままにした方が認識しやすいはずであるが、なぜかモノクロに変換しているので、カラーのまま実行したらどうなるかやってみた。結果、認識率にあまり変化はなさそうだった。なぜモノクロにしているのかわからない。
6. canvasオブジェクトの再利用
実行中にcreateElement()でcanvasオブジェクト複数生成している。DOM treeに結合しているわけではなく、drawImage()してイメージを部分的に切り出すために使っているようだ。これをビデオの再生中に毎回実行していたら遅いのは当たり前なので、生成したcanvasを再利用するようにした。ちなみに、canvasオブジェクトが37個生成されている。
以上の結果、画期的に高速になった。 ……と言いたいところだったが、多少高速になった程度。
人物の顔が映っていて著作権上問題のないビデオが見つからなかったので、結果だけを載せる。YouTubeをザッピングしていたら、顔認識のテストにまさにちょうどいい動画があった。AKB48の「頑張ろう、日本!!」の動画である。前回作った対話コマンドを使って最後のシーン付近で最も認識に成功しているものをコマ送りして選んだもの。実際に動作するところを載せたいが、canvasのgetImageData()を使っているのでドメインが異なるとセキュリティ例外が発生するし、そもそも著作権上できないだろう。顔認識に適した自由に使える動画はないだろうか?
実際の動作はこちらから確認できる。動画は前回と同じBig Buck BunnyとSintel。BBBは顔認識できないが、Sintelの方はちょっとだけ認識できるシーンがある。
高速になるだろうと期待して書き換えたソースはこちら。
今回はあまり有益な結果は得られなかったが、それでも十分楽しめた。
AKBのメンバーの顔と名前もちょっとは覚えたし...