VOYAGE GROUP エンジニアブログ

voyagegroup_techのブログ
VOYAGE GROUPエンジニアブログです。

2013年02月

Apple信者ならFlash使わずPHP拡張face_detectで顔認証するよね !

こんにちは、VOYAGE GROUPのエンジニア、ガイアです。今は、ECナビのスマホサイトの開発運用をしています。

僕はECナビのスマホサイトを8ヶ月利用して5万ポイント貯めました。

貯めたポイントをWebマネーに変えて、音楽でも買おうと思います。まあ、ステマはこのぐらいにして本題に入ります。(5万ポイントは本当です、信じてください)

現在、Webで配信されるコンテンツはテキストに始まり、画像、音声、映像ときて、今はインタラクションのあるコンテンツもごく当たり前に配信されてます。javascript、HTML5、Unityなど色々と技術はありますが、やはりWebとの親和性や、普及度などなど・・・結局、色々物議を醸し出していますが、Flashで作られたコンテンツが多いのが現状です。ただ、Apple信者としてはiPhoneやiPadに対応したコンテンツにしたいところ、Flashを使ったコンテンツは少しばかり抵抗があります。Apple曰く「アプリでやればいいじゃない」というツンデレっぷりです。

そんな事を考えている時、Webで顔認識をやりたいという願いが降り落ちて来ました。最善はFlashだろうと思ったのですが、このご時世iPhoneは外せない。という訳で他の方法を模索するに至りました。顔認識についてはOpenCVというオープンソースのコンピュータビジョン用のライブラリを利用するのが一番楽だと信じているので、それをWebのインターフェイスから利用しようと妄想を走らせ、Google先生にお伺いを立ててみると、PHPからOpenCVを使う方法があるみたいです。Sounds great!
PHPのExtensionにface_detectという拡張機能があり、それを使います。

さあ、前置きはこのぐらいにして実際の作業に入りましょう。
詳しくはXarg.orgに情報があります。

環境設定 
Scientific Liunux 5を利用しています。OSはなんでもいいでしょう。

インストールするもの
  • httpd
  • php5.3
  • php-devel
  • php-gd
  • OpenCV2.3
  • php face_detect extension 

php-gdあたりまでは楽に揃えられると思います。パッケージ管理ツールで揃えてしまいましょう。php-gdをインストールしたら、phpinfo のページを作って GD が有効になっていることを確認します。

gd


画像表示
次に、PHPで画像を表示させてみましょう。phpanualからPHPの画像表示のコードを拝借します。
imagecreatefromjpeg :新しい画像をファイルあるいは URL から作成する


lena

OpenCVのインストール
画像は表示されましたか?では、次にOpenCVをインストールします。OpenCVは2.3が推奨です。
OpenCVはリポジトリに無いことが多いので、ここを参考にさせて頂きました。
mk-mode BLOG * Scientific Linux - OpenCV をソースからインストール
ソースからOpenCVをインストールするときにcmakeを利用するのですが、リポジトリからcmakeをインストールすると2.6系が入り、このページの通りに進めていくとエラーが出てしまいます。ソースパッケージからcmakeの2.8系をインストールすれば解決します。その他、gc++が必要だったりしますが、エラーが出たら、適宜インストールして下さい。


facedetect extension
OpenCVをインストールしたら、facedetect extensionをインストールします。
Xarg.orgにインストール方法が書いてあります。


 Install OpenCV (OpenCV 2.3.1)
 Download facedetect source package
 Unpack facedetect source package
 Go to facedetect folder and type "phpize && ./configure && make && make install"
 Make sure you have extension=facedetect.so in your php.ini


コマンドだとこんな感じです。簡単ですね。(権限で怒られたら、適宜権限を追加するなり、コマンドを一つづつ実行するなりして下さい。)
  • git clone https://github.com/infusion/PHP-Facedetect.git
  • cd PHP-Facedetect
  • phpize && ./configure && make && make install
インストールが終わったらphp.iniに extension=facedetect.so を追記して、facedetectを有効化します。その後 phpinfo のページでfacedetectが有効化されていることを確認します。これで準備は万端です。
facedetect

因みに、facedetect extensionをインストールすると2つの関数が使えるようになります。
  • face_count('party.jpeg', 'cascade.xml') 顔の数を返す
  • face_detect('party.jpeg', 'cascade.xml') 顔の場所の配列を返す
第一引数は、画像ファイル、第2引数はOpenCVでオブジェクト検出に利用される分類器です。この分類器に関してはOpenCVに学習済みのサンプルがあります。OpenCVインストール時に解凍したディレクトリ OpenCV-2.3.0/data/haarcascades/ 以下にあるxmlがそのデータです。

ついに顔認識!!
さあ、環境設定も終わり、あとはコードを書くだけです、先ほどの画像表示のコードを変更します。
lena_face

よく見る出力結果になりましたね。PHPで顔認識をすることができました。みなさんも、PHPで顔認識を楽しんで下さい。

face_detect_murata


・・・

「いやいやいや、ちょっとまって、なんだよ、PHPで顔認識って、その処理、全部サーバでやる気かよ、そこはFlashだろjk」
っておみさんに言われそうな仕様です。
 
今回VirtualBoxを使っていたのですが、実行速度も・・・
これでは、ユーザの同時アクセスに耐えれそうにありません・・・
PHPで顔認識ってニーズあるんですかね。実現可能性が低いんでは・・・
そもそもOpenCVの顔認識って色々オプションあったよね、そんなのも設定できないんじゃ・・・


「まだだ、まだ終わらんよ」

こうなったら更にニッチなところへと足を踏み入れていく次第です。

次回
「サンプルコードでDeveloper!? OpenCVで学ぶ!自作 PHP Extension」




jQueryを用いた美しいajax処理

こんにちは、Research Panel Asia の関口(@takkyuuplayer)です。

jQueryを用いた非同期処理の待ち合わせについて書きたいと思います。 昨今WebにリッチなUIが求められていますが、その際によく遭遇するのが次のような処理です。

「処理A(非同期)が終わってからその結果を元に処理Bを行いたい。」

jQuery.getなんかでデータを取ってくる際には必須ですね。このような非同期処理の待ち合わせはjQuery.Deferredを使うと簡単に実現可能です。

jQuery.Deferred

ex1.html
 
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
</head>
<body>
<ul id="async_test">
<li>0</li>
</ul>
<script language="javascript">
var time_ms = 1000;
var ajax = function(arg) {
var deferred = $.Deferred();
setTimeout(function() {
deferred.resolve(arg+1);
}, time_ms);

return deferred.promise();
}

var tmpl = _.template('<li><%= count %> : <%= wait %>ms later</li>');
ajax(0).done(function(ret) {
$('ul#async_test').append(tmpl({count:ret, wait:time_ms}));
});

</script>
</body>
</html>

また、jQuery.whenを使って「処理Aと処理A’が両方終わってから、処理Bを行う」事もできます。

jQuery.when

ex2.html : ※下記にはex1.htmlとの変更部分のみ示してあります。
      var tmpl = _.template('<li><%= count1 %> / <%= count2 %> </li>');
$.when(ajax(0), ajax(100)).done(function(ret1, ret2) {
$('ul#async_test').append(tmpl({count1:ret1, count2:ret2}));
});

便利ですね。任意個数の待ち合わせを行うにはどうすればよいでしょうか?引数を配列にすることで、「処理A, A’, A’’, ....が終わってから処理Bを行う」事ができます。

複数処理の同時待ち合わせ

ex3.html : ※下記にはex1.htmlとの変更部分のみ示してあります。
      var deferreds = [];
for (var i=0; i<20; i++) {
deferreds.push(ajax(i*10));
}

var tmpl = _.template('<li><%= text %></li>');
$.when.apply(null, deferreds).done(function() {
var rets = Array.prototype.slice.call(arguments);
$('ul#async_test').append(tmpl({text:rets.join(' / ')}));
});

ただし、実際にex3.htmlのようなコードを書くことは稀でしょう。非同期処理はjQuery.getやjQuery.postといった、HTTPリクエストであることが多いと思います。ex3.htmlでは20ものHTTPリクエストを同時に発生させてしまいます。そこで求められるのは「処理Aが終わったら処理A’を行い、それが終わったら処理A’’を行い・・・最後に処理Bを行う」事です。私は悩んだ末以下のように再帰で解決しました。

順番に待ち合わせる

ex4.html : ※下記にはex1.htmlとの変更部分のみ示してあります。
      var deferreds = [];
var max = 20;
for (var i=0; i<max; i++) {
deferreds.push(function(arg) { return ajax(arg*10); });
}

var rets = [];
var do_next = function() {
if(deferreds.length == 0 ) {
var tmpl = _.template('<li>Finished</li>');
$('ul#async_test').append(tmpl({text:rets.join(' / ')}));

return;
}

var arg = max - deferreds.length;
var deferred = deferreds.shift();
deferred(arg).done(function(ret) {
rets.push(ret);
var tmpl = _.template('<li>Process : <%= text %></li>');
$('ul#async_test').append(tmpl({text:rets.join(' / ')}));
do_next();
});
};

do_next();

ajaxに渡す引数の処理がいけていませんが、deferredsの中に入れるのをnewしたオブジェクトにしておけば解決できるでしょう。

まとめ

jQueryで可能なのはDOM操作だけではありません。Deferredを始めいろいろ便利機能が揃っています。時間がある時に一度jQuery API ドキュメントを眺めてみてはいかがしょうか?
記事検索
QRコード
QRコード