Webカメラの映像をface++に送信する【JavaScript】
概要
前回の記事で、Webカメラの映像の画像を取得する方法を書きました。
famirror.hateblo.jp
API解説
face++は中国のWebサービスで、顔認証だけでなく、顔の判別や検索など、様々な機能を持つ無料APIです。
www.faceplusplus.com
「face++」の基本的な使い方に関しては以前の記事をご覧ください。
famirror.hateblo.jp
前回同様、顔認識機能「/detection/detect」を試してみます。
Webカメラの映像を取得する
Webカメラの映像を「video」領域に流し、ボタンが押された時にそれを「canvas」にコピーします。
詳しい解説は前回の記事をご覧ください。
famirror.hateblo.jp
以下のソースで「submit」ボタンを押すと「canvas」領域にWebカメラの映像がコピーされます。
HTML(index.html)
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="style.css"> <title>Webカメラの映像をface++に送信</title> </head> <body> <h2>Video</h2> <video id="camera" autoplay></video> <button id="submit">submit</button> <h2>Canvas</h2> <canvas id="canvas"></canvas> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script type="text/javascript" src="./script.js"></script> </body> </html>
@charset "UTF-8"; #camera { width: 400px; height: 300px; }
JavaScript(script.js)
$(function() { //videoタグを取得 var video = document.getElementById('camera'); //カメラが起動できたかのフラグ var localMediaStream = null; //カメラ使えるかチェック var hasGetUserMedia = function() { return (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); }; //エラー var onFailSoHard = function(e) { console.log('エラー!', e); }; if(!hasGetUserMedia()) { alert("未対応ブラウザです。"); } else { window.URL = window.URL || window.webkitURL; navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; navigator.getUserMedia({video: true}, function(stream) { video.src = window.URL.createObjectURL(stream); localMediaStream = stream; }, onFailSoHard); } $("#submit").click(function() { if (localMediaStream) { var canvas = document.getElementById('canvas'); //canvasの描画モードを2sに var ctx = canvas.getContext('2d'); var img = document.getElementById('img'); //videoの縦幅横幅を取得 var w = video.offsetWidth; var h = video.offsetHeight; //同じサイズをcanvasに指定 canvas.setAttribute("width", w); canvas.setAttribute("height", h); //canvasにコピー ctx.drawImage(video, 0, 0, w, h); } }); });
canvasを以下のように非表示にしても問題ありません。
#canvas { display: none; }
画像をバイナリ化
このままの状態では送信できたいので、画像データをバイナリ化します。
JavaScriptの44行目「ctx.drawImage(video, 0, 0, w, h);」の後に以下のコードを追加してください。
JavaScprit(script.js)追加
//ここから画像のバイナリ化 var can = canvas.toDataURL(); // Data URLからBase64のデータ部分のみを取得 var base64Data = can.split(',')[1]; // base64形式の文字列をデコード var data = window.atob(base64Data); var buff = new ArrayBuffer(data.length); var arr = new Uint8Array(buff); // blobの生成 for(var i = 0, dataLen = data.length; i < dataLen; i++){ arr[i] = data.charCodeAt(i); } var blob = new Blob([arr], {type: 'image/png'});
これで画像のバイナリデータがblobに入りました。
face++に送信する
続いてそのデータを送信します。
今回はajaxを使って非同期通信でPOST送信を行います。
先ほど追加したソースに、さらに以下のソースを続けてください。
JavaScript(script.js)追加
//ここから画像データ送信 //urlを設定 var api_key = 'b81fd92a7779b24eddf6b556ccb9baa9'; var api_secret = 'Pq9T3A_pboK4ANRSAnK7ea9XQZdTbVpH'; var url = 'https://apicn.faceplusplus.com/detection/detect' + '?api_key=' + api_key + '&api_secret=' + api_secret; //データをセット var formData = new FormData(); formData.append('img', blob); //非同期通信開始 $.ajax({ url: url, type: 'POST', data: formData, contentType: false, processData: false, success: function(data, dataType) { console.log(data); }, error: function(XMLHttpRequest, textStatus, errorThrown) { console.log('Error : ' + errorThrown); } });
<API Key>と<API Secret>はご自身のものをお使いください。
コンソールを確認すると、情報が得られているのがわかると思います。
結果を表示する
ついでに結果を表示しましょう。
表形式で一部の情報だけ表示します。
HTMLの「canvas」タグの下に以下のソースを追加します。
HTML(index.html)追加
<h2>Result</h2> <div id="result"></div>
JavaScriptの方は、resultという関数を作成し、ajaxの成功時に呼び出します。
先ほど「console.log(data)」となっていたところを以下のように変更してください。
JavaScript(script.js)変更
result(data);
また、以下の関数を宣言してください。
JavaScript(script.js)追加
var result = function(data) { var i, face; $('#result').html(''); for(i = 0; i < data['face'].length; i++) { face = data['face'][i]['attribute']; $('#result').append('<h3>' + (i + 1) + '人目</h3>'); $('#result').append('<table><tr><th>名前</th><th>データ</th></tr>'); $('#result').append('<tr><td>年齢</td><td>' + face['age']['value'] + '±' + face['age']['range'] + '歳</td></tr>'); $('#result').append('<tr><td>性別</td><td>' + face['gender']['value'] + '(' + face['gender']['confidence'] + '%)' + '</td></tr>'); $('#result').append('<tr><td>人種</td><td>' + face['race']['value'] + '(' + face['race']['confidence'] + '%)' + '</td></tr>'); $('#result').append('<tr><td>笑顔度</td><td>' + face['smiling']['value'] + '%</td></tr></table>'); } if(i == 0) $('#result').html('顔が検出されませんでした。'); }
ボタンを押してしばらくすると表が表示されるようになったと思います。
ちなみに、私の結果はこんな感じでした。
実年齢よりちょっと若目に出ていますね。
コード
HTML(index.html)
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="style.css"> <title>Webカメラの映像をface++に送信</title> </head> <body> <h2>Video</h2> <video id="camera" autoplay></video> <button id="submit">submit</button> <h2>Canvas</h2> <canvas id="canvas"></canvas> <h2>Result</h2> <div id="result"></div> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script type="text/javascript" src="./script.js"></script> </body> </html>
@charset "UTF-8"; #camera { width: 400px; height: 300px; }
JavaScript(script.js)
$(function() { //videoタグを取得 var video = document.getElementById('camera'); //カメラが起動できたかのフラグ var localMediaStream = null; //カメラ使えるかチェック var hasGetUserMedia = function() { return (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); }; //エラー var onFailSoHard = function(e) { console.log('エラー!', e); }; var result = function(data) { var i, face; $('#result').html(''); for(i = 0; i < data['face'].length; i++) { face = data['face'][i]['attribute']; $('#result').append('<h3>' + (i + 1) + '人目</h3>'); $('#result').append('<table><tr><th>名前</th><th>データ</th></tr>'); $('#result').append('<tr><td>年齢</td><td>' + face['age']['value'] + '±' + face['age']['range'] + '歳</td></tr>'); $('#result').append('<tr><td>性別</td><td>' + face['gender']['value'] + '(' + face['gender']['confidence'] + '%)' + '</td></tr>'); $('#result').append('<tr><td>人種</td><td>' + face['race']['value'] + '(' + face['race']['confidence'] + '%)' + '</td></tr>'); $('#result').append('<tr><td>笑顔度</td><td>' + face['smiling']['value'] + '%</td></tr></table>'); } if(i == 0) $('#result').html('顔が検出されませんでした。'); } if(!hasGetUserMedia()) { alert("未対応ブラウザです。"); } else { window.URL = window.URL || window.webkitURL; navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; navigator.getUserMedia({video: true}, function(stream) { video.src = window.URL.createObjectURL(stream); localMediaStream = stream; }, onFailSoHard); } $("#submit").click(function() { if (localMediaStream) { var canvas = document.getElementById('canvas'); //canvasの描画モードを2sに var ctx = canvas.getContext('2d'); var img = document.getElementById('img'); //videoの縦幅横幅を取得 var w = video.offsetWidth; var h = video.offsetHeight; //同じサイズをcanvasに指定 canvas.setAttribute("width", w); canvas.setAttribute("height", h); //canvasにコピー ctx.drawImage(video, 0, 0, w, h); //ここから画像のバイナリ化 var can = canvas.toDataURL(); // Data URLからBase64のデータ部分のみを取得 var base64Data = can.split(',')[1]; // base64形式の文字列をデコード var data = window.atob(base64Data); var buff = new ArrayBuffer(data.length); var arr = new Uint8Array(buff); // blobの生成 for(var i = 0, dataLen = data.length; i < dataLen; i++){ arr[i] = data.charCodeAt(i); } var blob = new Blob([arr], {type: 'image/png'}); //ここから画像データ送信 //urlを設定 var api_key = '<API KEY>'; var api_secret = '<API SECRET>'; var url = 'https://apicn.faceplusplus.com/detection/detect' + '?api_key=' + api_key + '&api_secret=' + api_secret; //データをセット var formData = new FormData(); formData.append('img', blob); //非同期通信開始 $.ajax({ url: url, type: 'POST', data: formData, contentType: false, processData: false, success: function(data, dataType) { result(data); }, error: function(XMLHttpRequest, textStatus, errorThrown) { console.log('Error : ' + errorThrown); } }); } }); });