顔検出・顔認識をJavaScriptで実行する[CCV.js]
JavaScriptで画像から顔を検出する「顔検出」を実行するサンプルです。顔検出はオープンソースのCCV.jsというライブラリを使用します。顔を検出した後には各自で顔を認識するコードを追加します。
顔検出
画像から顔を検出すると赤い枠で顔を囲みます。
ccv.jsのダウンロード
https://github.com/liuliu/ccv (GitHub)
の「js」フォルダにある「ccv.js」と「face.js」のファイルをダウンロードします。
このccv.jsは「OpenCV」というインテルが開発したオープンソースの画像処理ライブラリから派生しています。
サンプルコード
ファイル選択ダイアログで画像を開くと、自動的に画像から顔を検出します。
顔検出の処理時間をブラウザのコンソールに出力しますので、ブラウザ上でF12キーを押して開発者ツールを起動しておいてください。※IEで開発者ツールを起動してスクリプトを実行すると動作が遅くなります。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src ="face.js"></script> <script src ="ccv.js"></script> <script> // キャンバス var src_canvas; var src_ctx; // イメージ var image; window.onload = function(){ src_canvas = document.getElementById("SrcCanvas"); src_ctx = src_canvas.getContext("2d"); image = document.getElementById("image_source"); } // ドラッグオーバー function onDragOver(event){ event.preventDefault(); } // ドロップ function onDrop(event){ onAddFile(event); event.preventDefault(); } // ユーザーによりファイルが追加された function onAddFile(event) { var files; var reader = new FileReader(); if(event.target.files){ files = event.target.files; }else{ files = event.dataTransfer.files; } // ファイルが読み込まれた reader.onload = function (event) { // イメージが読み込まれた image.onload = function (){ src_canvas.width = image.width; src_canvas.height = image.height; src_ctx.drawImage(image, 0, 0); console.time('処理'); // 顔検出 var comp = ccv.detect_objects({ "canvas" : ccv.grayscale(ccv.pre(image)), "cascade" : cascade, "interval" : 5, "min_neighbors" : 1 }); // 結果の表示 src_ctx.drawImage(image, 0, 0); src_ctx.lineWidth = 2; src_ctx.strokeStyle = "#ff0000"; for (var i=0;i<comp.length;i++) { src_ctx.strokeRect(comp[i].x,comp[i].y,comp[i].width,comp[i].height); } if(comp.length === 0){ console.log('顔を検出できませんでした。'); } console.timeEnd('処理'); }; // イメージが読み込めない image.onerror = function (){ alert('このファイルは読み込めません。'); }; image.src = reader.result; }; if (files[0]){ reader.readAsDataURL(files[0]); } } </script> </head> <body ondrop="onDrop(event);" ondragover="onDragOver(event);"> <img id="image_source" > <p></p> <input type="file" id="inputfile" accept="image/jpeg,image/png,image/gif,image/bmp" onchange="onAddFile(event);"> <p></p> <canvas id="SrcCanvas"></canvas> </body> </html>
画像から顔が検出されない場合は、コンソールに「顔を検出できませんでした。」と出力されます。
解説
57行目から62行目で顔検出を実行しています。
65行目から71行目で検出した結果を表示しています。
[顔検出の引数 - ccv.detect_objects()]
引数 | 意味 |
---|---|
canvas | 画像をグレースケールに変換した後のcanvasを指定します。 |
cascade | 常にface.jsにある配列を指定します。 |
interval | 間隔。値を小さくすると認識率が下がり、大きくすると認識率が向上します。処理速度は値に比例して増加します。(デフォルト:5) |
min_neighbors | 隣人?。(デフォルト:1) ※公式サンプルは1。 |
[戻り値 - ccv.detect_objects()]
プロパティ | 意味 |
---|---|
x | 検出した顔のX座標 |
y | 検出した顔のY座標 |
width | 検出した顔の幅 |
height | 検出した顔の高さ |
confidence | 信頼性? ※詳細不明 |
neighbors | 隣人? ※詳細不明 |
戻り値の「x/y/width/height」を使用して枠を描画しています。本家のOpenCVはその他に輪郭、眉毛、目、鼻、口などのプロパティがあると思われます。
顔検出の速度
1280 x 707の画像で速度のテストをしました。
※元のコードを改造してマルチスレッドで実行しています。
ブラウザ | 処理時間 |
---|---|
Chrome | 約750ms |
FireFox | 約570ms |
IE11 | 約2100ms |
環境はWindows 7(64bit)のCorei5-3470 CPU @3.20GHz (4CPUs)、Memory 4GB、GeForce GTX 550 Tiです。3-5年ぐらい前のゲームマシンです。
マルチスレッドで実行中にプログレスバーを表示すれば耐えられる速度だと思います。もちろん、元のソースコードを高速化することも可能だと思います。
顔検出の精度
基本的に正面を向いている画像のみに対応しているようです。
Googleで「集合写真」で検索して表示される集合写真を、この顔検出で確認してみるとわかりますが、認識率は「6-7割」ぐらいかと思われます。お遊び程度のWebアプリなら作れそうです。
また、画像を任意の領域で拡大、縮小を行うと精度が向上する場合があります。その他に画像のヒストグラムを平均化、引き伸ばしたり、尖鋭化、2値化、明るさ強調、暗さ強調、コントラスト改善など色々試すと認識率が上がるかもしれないです。
特許について
ccv.jsで使用されている顔検出にはSIFT/SURFという特許が含まれている可能性があります。商用利用ではライセンス契約をする必要があるようです。
Webサイトに広告を貼るだけでも商用利用になる可能性がありますので注意してください。この特許やライセンスに関しては各自で調査して各自の責任において使用してください。
特許関連リンク(外部)
SURFの特許についての議論
OpenCVとVisual C++による画像処理と認識 (ページ内を特許で検索)
OpenCV3でAKAZE特徴量を検出する (ページ内を特許で検索)
顔検出のWebAPI
顔検出を行ってくれるWebAPIです。
detectFace(); (無料)
Google Cloud Vision API (1000件/月まで無料)
Microsoft Cognitive Services (5000件/月まで無料)
※detectFace();はクライアント側のAjaxからは顔検出ができないようです。サーバー側からなら可能です。
関連記事
前の記事: | JavaScriptでタイマーを使用する[setTimeout/setInterval] |
次の記事: | 文字列をUTF8からShift-JISに変換する際の「円記号/バックスラッシュ」に対応する[encoding.js] |