APIキーを取得したら、早速、Face++にリクエストを送って、顔認証のデータを取得してみましょう!! 言語はPHPを使用するので、PHPが稼働する環境を用意して下さい。
サンプルプログラム
URLを組み立てて、リクエストをするまでのプログラムは下記の通りです。リクエストが成功すると、$json
に、返り値のJSONデータが代入されます。
PHP
<?php
// 設定項目
$params = array(
'api_key' => '' , // APIキー
'api_secret' => '' , // APIシークレット
'url' => get_current_dir() . 'women.jpg' , // 画像のURLアドレス
'attribute' => 'glass,pose,gender,age,race,smiling' , // 取得要素
) ;
// リクエストURL
$request_url = 'https://apius.faceplusplus.com/v2/detection/detect' . '?' . http_build_query( $params ) ;
//cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl , CURLOPT_URL , $request_url ) ;
curl_setopt( $curl , CURLOPT_HEADER, 1 ) ;
curl_setopt( $curl , CURLOPT_SSL_VERIFYPEER , false ) ;
curl_setopt( $curl , CURLOPT_RETURNTRANSFER , true ) ;
curl_setopt( $curl , CURLOPT_TIMEOUT , 15 ) ;
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;
// 取得したデータを整理
$json = substr( $res1, $res2['header_size'] ) ;
$header = substr( $res1, 0, $res2['header_size'] ) ; // レスポンスヘッダー (検証に利用したい場合にどうぞ)
// HTML用
$html = '' ;
// リクエストしたデータ
$html .= '<h2>リクエストした画像</h2>' ;
$html .= '<p><img class="_img" src="' . $params['url'] . '"></p>' ;
// 取得したデータ
$html .= '<h2>取得したデータ</h2>' ;
$html .= '<p>リクエストの結果、下記のデータを取得できました。</p>' ;
$html .= '<h3>JSON</h3>' ;
$html .= '<p><textarea rows="8">' . $json . '</textarea></p>' ;
$html .= '<h3>レスポンスヘッダー</h3>' ;
$html .= '<p><textarea rows="8">' . $header . '</textarea></p>' ;
// 現在のディレクトリを[http]から取得する関数
function get_current_dir()
{
$ary = explode( '/' , $_SERVER['REQUEST_URI'] ) ;
$filename = $ary[ ( count( $ary ) - 1 ) ] ;
return str_replace( $filename , '' , ( !isset($_SERVER['HTTPS']) || empty($_SERVER['HTTPS']) ? 'http://' : 'https://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ) ;
}
?>
<?php
// ブラウザに[$html]を出力 (HTMLのヘッダーとフッターを付けましょう)
echo $html ;
?>
このコードの動作を確認する
取得できるJSON
冒頭のサンプルで使った写真のJSONデータは次の通りです。face
プロパティに人数分のデータが配列で格納されています。また、それぞれのデータには、年齢や性別などを含むattribute
と、顔、目、口などの位置情報を含むposition
プロパティで構成されています。face_id
は、その顔情報のIDです。Face++では72時間、顔画像が保存されていて、このIDを利用して再度呼び出したりすることができます。72時間経過後、このIDは意味を持たなくなります。
JSON
{"face":[{"attribute":{"age":{"range":10,"value":37},"gender":{"confidence":63.7538,"value":"Male"},"glass":{"confidence":99.4947,"value":"None"},"pose":{"pitch_angle":{"value":0.000171},"roll_angle":{"value":-6.7773},"yaw_angle":{"value":-0.001961}},"race":{"confidence":95.5922,"value":"White"},"smiling":{"value":85.687}},"face_id":"43b66e30688f865c7493ce2802077f18","position":{"center":{"x":19.166667,"y":55.137845},"eye_left":{"x":14.3913,"y":49.976942},"eye_right":{"x":23.315,"y":48.382206},"height":29.072682,"mouth_left":{"x":14.9816,"y":63.088471},"mouth_right":{"x":24.0275,"y":62.025313},"nose":{"x":19.235167,"y":54.676441},"width":19.333333},"tag":""},{"attribute":{"age":{"range":5,"value":12},"gender":{"confidence":99.6509,"value":"Female"},"glass":{"confidence":99.9069,"value":"None"},"pose":{"pitch_angle":{"value":0.001542},"roll_angle":{"value":-9.98795},"yaw_angle":{"value":27.922053}},"race":{"confidence":99.2528,"value":"White"},"smiling":{"value":86.6312}},"face_id":"3ed5e97937f0a5a6ce09e62fbde61504","position":{"center":{"x":46.75,"y":52.255639},"eye_left":{"x":41.967,"y":49.105764},"eye_right":{"x":48.270833,"y":47.436341},"height":21.804511,"mouth_left":{"x":43.258,"y":58.50401},"mouth_right":{"x":49.699333,"y":57.172682},"nose":{"x":47.685333,"y":51.54787},"width":14.5},"tag":""}],"img_height":533,"img_id":"92f5f4fdb1d7cfc96df188130a495eed","img_width":800,"session_id":"d2445038c8984840b582b992b521ca05","url":"http:\/\/syncer.jp\/images\/DHFgXv5Rfe4d1Lej1lnQfuffZtzsj\/post\/api\/face-detect-01.jpg"}
スタイルシートで枠線を重ねる
取得したJSONを活用するには、PHP以外に、スタイルシートやJavaScriptの知識が必要になってくるでしょう。
position
スタイルシートのposition
を利用することで、APIを通して取得した位置情報を元に、枠線などを画像に重ね合わせることが可能になります。これ以降の解説は、スタイルシートのposition
を正確に理解していることが前提です。これなしには、画像に枠線を重ねる仕組みを把握する努力は空回りしてしまいます。ええ、本当に。
ピクセルの実数値を求める計算式
position
を利用するには、まずは顔の中心位置のX座標、Y座標と、顔の横幅、縦幅のピクセル実数値が必要ですね。APIで取得した、位置や大きさを示す値は、全て、画像の大きさに対するパーセンテージとなっています。例えば、画像のサイズが500x250
だったとします。xが20%
で、yが50%
だった場合、顔の中心位置は、左側から100px
、上部から125px
だけ離れた位置にあるということになります。
つまり、画像サイズ * (値 / 100)
の計算式で、X座標、Y座標の実数となるピクセル値を算出できることが分かると思います。さらに、レスポンシブデザインなどの場合、画像の大きさは本来よりも狭めて表示させている場合があるので、そのパーセンテージ(スケーリング)の値も考慮する必要がありますね。例えば、本来の半分のサイズでブラウザに表示させているなら、0.5を掛けないといけません。総合すると、次の通りです。
( 画像サイズ * (値 / 100) ) * スケーリング値
重ね合わせの例
画像の大きさ、顔の中心座標、横幅、高さ、それぞれのピクセル値が分かれば、後は、スタイルシートとJavaScriptを使って、画像に枠となるdiv要素を重ね合わせるだけですね。例えば下記は、APIで取得した位置情報のデータを元に、それぞれの顔全体に、div
要素を重ね合わせたものです。
画像に枠を重ねる場合、position
のtop
値に顔の中心位置のX座標、left
値に顔の中心位置のY座標を重ねるだけでは右下方向にズレてしまいます。何故なら、このままだと、ちょうど枠の左上部分が顔の中心となっているからです。top
値、left
値からは、それぞれ、枠要素(顔の大きさ)の半分のサイズをマイナスさせる必要がある点にご注意下さいね。
枠要素(顔の大きさ)が300x200
の場合、例えば、顔の中心位置のX座標が500pxだったら、「500-(300/2)」で、350
がtop値に指定するべき値です。Y座標が600pxだったら、「600-(200/2)」で、500
がleft値に指定するべき値ですね。
そして、最後に何故、JavaScriptが必要なのかを説明しましょう。…それは、デスクトップ環境の人は、このウィンドウを狭めてみれば分かります。画像のサイズがレスポンシブデザインによって縮小されるため、枠の位置がズレてしまうんですね。要するに、ウィンドウの幅(画像の幅)に合わせて、動的に、top値やleft値などの値を指定する必要があるわけです。スマホ全盛は、色々な手間を運んでくれています。
Face++のAPIでは、顔の中心位置と大きさだけでなく、それぞれの目の位置、口の位置、そして鼻の位置も取得することができます。これらの情報を使えば、写真を自動でデコレーションするウェブサービスなどの実現も可能です。
サンプルプログラム
Face++のAPIで取得したJSONを引数に指定することで、顔写真に枠線を付けるJavaScript(syncerFaceDetect()
)の関数を作成してみました。よろしければ、色々な顔写真を指定して試してみて下さいね。
JavaScript
function syncerFaceDetect( obj )
{
// ID
var id = 'syncer-face-detect' ;
// 枠線の色
var color = '#D36015' ;
// 画像の大きさ
var img = {
top: $( '#' + id ).offset().top - $( '#' + id ).parent().offset().top ,
left: $( '#' + id ).offset().left - $( '#' + id ).parent().offset().left ,
width: $( '#' + id ).width() ,
height: $( '#' + id ).height() ,
} ;
// 変数の定義
var data = obj.face , face = [] , attr_id , attr_class_1 = id + '-' , attr_class_2 = id + '-parts-' , position ;
// 処理
for( var i in data )
{
// エイリアス
position = data[i].position ;
// 顔のデータをまとめる
face = {
width: img.width * ( position.width / 100 ) ,
height: img.height * ( position.height / 100 ) ,
center: {
x: img.width * ( position.center.x / 100 ) ,
y: img.height * ( position.center.y / 100 ) ,
} ,
eye: {
left: {
x: img.width * ( position.eye_left.x / 100 ) ,
y: img.height * ( position.eye_left.y / 100 ) ,
},
right: {
x: img.width * ( position.eye_right.x / 100 ) ,
y: img.height * ( position.eye_right.y / 100 ) ,
}
},
mouth: {
left: {
x: img.width * ( position.mouth_left.x / 100 ) ,
y: img.height * ( position.mouth_left.y / 100 ) ,
},
right: {
x: img.width * ( position.mouth_right.x / 100 ) ,
y: img.height * ( position.mouth_right.y / 100 ) ,
}
},
nose: {
x: img.width * ( position.nose.x / 100 ) ,
y: img.height * ( position.nose.y / 100 ) ,
},
} ;
// 各パーツの値をセット
var parts = [ face.eye.left , face.eye.right , face.mouth.left , face.mouth.right , face.nose ] ;
// 顔のIDを定義
attr_id = attr_class_1 + i ;
// 顔全体に枠線のHTMLを付ける
$( '#' + id ).after( '<div id="' + attr_id + '"><b>' + ( Number( i ) + 1 ) + '人目</b></div>' ) ;
// スタイルシートを適用
$( '#' + attr_id ).css( {
position: 'absolute' ,
width: face.width ,
height: face.height ,
top: img.top + face.center.y - ( face.height / 2 ) ,
left: img.left + face.center.x - ( face.width / 2 ) ,
background: 'rgba( 255,255,255 , .2 )' ,
border: '3px solid ' + color ,
color: '#030303' ,
} ) ;
// 各パーツの枠線を配置していく
for( var ii=0 , ll=parts.length ; ll > ii ; ii++ )
{
// IDの決定
attr_id = attr_class_2 + i + '-' + ii ;
// 枠線のHTMLを追加する
$( '#' + id ).after( '<div id="' + attr_id + '"></div>' ) ;
// HTMLにスタイルシートを適用
$( '#' + attr_id ).css( {
position: 'absolute' ,
width: 10 ,
height: 10 ,
top: img.top + parts[ ii ].y - 5 ,
left: img.left + parts[ ii ].x - 5 ,
background: color ,
} ) ;
}
}
}
次のように、ID属性値(デフォルトではsyncer-face-detect
)を付け、width
とheight
を指定したimg
要素を配置して下さい。親要素には、position:relative
を指定する必要があります。
HTML
<div style="position:relative; top:0; left:0; overflow:hidden;">
<img src="" id="syncer-face-detect" width="" height="">
</div>
このコードの動作を確認する