前回はブラウザにカメラ映像を映し出すだけでした。
今回は少しステップアップして、avascriptで実装された顔認識ライブラリのccv.jsと
組み合わせでリアルタイムの笑い男変換を実装したいと思います。
face.jsで顔認識〜という記事も見かけますが、実際の画像処理のコアはccv.jsに記述されています。
ccvとはC-based Computer Vision Libraryの略でその名の通り、OpenCVの処理を抜粋・簡略化して
javascript実装したものがccv.jsです。
言うなれば、
ccv.js = OpenCV本体
face.js = face用のカスケードファイル
といったところでしょうか。
ccv.jsは以下のgithubレポジトリからダウンロードしてください。
ccv.js
以前の記事でjava×OpenCVで画像の笑い男変換を実装しましたが、今回はそれのリアルタイム映像版です。
物体検知入門(2)サンプル:笑い男
さきにざくっと処理の流れをまとめておきますと、
1.wenRTCでカメラから映像を読み込む
2.1の映像の中からsetIntervalを利用して定期的にface.jsとccv.jsで顔を検出
3.映像のstreamに対して2で検出した座標に画像を描画したものをcanvasタグに書き出し
ライブラリ以外のソースコードは以下の通りです。
index.html
<!DOCTYPE html> <html> <head> <title>sample-Laughingman-</title> <script type="text/javascript" src="http://www.google.com/jsapi"></script><script type="text/javascript"> google.load('jquery', '1'); google.load('jqueryui', '1'); </script> <script type="text/javascript" src="./js/lib/ccv.js"></script> <script type="text/javascript" src="./js/lib/face.js"></script> <script type="text/javascript" src="./js/laughingman.js"></script> <script> jQuery(document).ready(function() { Laughingman.initialize(); Laughingman.execute(); }); </script> </head> <body> <h3>sample-Laughingman-</h3> <video id="input" height="400" width="800" controls autoplay style="display: none;"></video> <canvas id="output"></canvas> </body> </html>
laughingman.js
/* * To change this template, choose Tools | Templates * and open the template in the editor. * author potter0517 */ //笑い男描画オブジェクト var Laughingman = {}; /** * init関数 * フィールドに必要な要素を保持する * @returns {undefined} */ Laughingman.initialize = function() { //笑い男の顔画像を重ねるためのビデオタグ(これ自体はブラウザに映さない) Laughingman.video = jQuery("#input").get(0); //ビデオに笑い男の画像を描画して最終的に映し出すためのcanvasタグ Laughingman.canvas = jQuery("#output").get(0); //Laughingman.canvas = document.querySelector("#canvas"); Laughingman.ctx = Laughingman.canvas.getContext("2d"); //笑い男の画像 Laughingman.image = new Image(); Laughingman.image.src = "./img/laughingman.gif"; }; /** * 実行 * @returns {undefined} */ Laughingman.execute = function() { navigator.webkitGetUserMedia({video: true, audio: true}, Laughingman.successCallback, Laughingman.failCallback); } /** * 描画関数 * これをsetIntervalで定期実行させる * @returns {undefined} */ Laughingman.draw = function() { var width = Laughingman.video.videoWidth; var height = Laughingman.video.videoHeight; // var canvas = document.createElement('canvas'); Laughingman.canvas.width = width; Laughingman.canvas.height = height; Laughingman.ctx.drawImage(Laughingman.video, 0, 0, width, height); var faces = ccv.detect_objects({"canvas": Laughingman.canvas, "cascade": cascade, "interval": 5, "min_neighbors": 1}); for (var i = 0; i < faces.length; i++) { Laughingman.ctx.drawImage(Laughingman.image, faces[i].x - 30, faces[i].y - 30, faces[i].width + 60, faces[i].height + 60); } }; /** * webkitGetUserMediaの成功時コールバック関数 * @param {type} stream * @returns {undefined} */ Laughingman.successCallback = function(stream) { var videoStream = window.webkitURL ? window.webkitURL.createObjectURL(stream) : stream; Laughingman.video.src = videoStream; setInterval(Laughingman.draw, 500); }; /** * webkitGetUserMediaの失敗時コールバック関数 * @param {type} error * @returns {undefined} */ Laughingman.failCallback = function(error) { alert("error... code : " + error.code); };
videoタグはそのまま映像として映さずに元ソースとしてのみ利用し、
最終的な合成映像はcanvasタグで描画しています。
そのため映像がかくかくしてしまっています。ついでに言うとface.jsの顔検出精度も
そんなに高くありませんでした。。。
もっと良い実装がある気もするのですが,,,現在はこんな感じです。
参考になれば。