APIキーを取得したら、早速、Face++にリクエストを送って、顔認証のデータを取得してみましょう!! 言語はPHPを使用するので、PHPが稼働する環境を用意して下さい。
サンプルプログラム
URLを組み立てて、リクエストをするまでのプログラムは下記の通りです。リクエストが成功すると、$json
に、返り値のJSONデータが代入されます。
PHP
<?php
$params = array(
'api_key' => '' ,
'api_secret' => '' ,
'url' => get_current_dir() . 'women.jpg' ,
'attribute' => 'glass,pose,gender,age,race,smiling' ,
) ;
$request_url = 'https://apius.faceplusplus.com/v2/detection/detect' . '?' . http_build_query( $params ) ;
$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 .= '<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>' ;
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
echo $html ;
?>
すべて見る
このコードの動作を確認する
取得できるJSON
冒頭のサンプルで使った写真のJSONデータは次の通りです。face
プロパティに人数分のデータが配列で格納されています。また、それぞれのデータには、年齢や性別などを含むattribute
と、顔、目、口などの位置情報を含むposition
プロパティで構成されています。face_id
は、その顔情報のIDです。Face++では72時間、顔画像が保存されていて、このIDを利用して再度呼び出したりすることができます。72時間経過後、このIDは意味を持たなくなります。
JSON
{
+
"face": [ … +
{ … +
"attribute": { … +
"age": { … },+
"gender": { … - "confidence": 63.7538,
- "value": "Male"
},+
"glass": { … - "confidence": 99.4947,
- "value": "None"
},+
"pose": { … +
"pitch_angle": { … },+
"roll_angle": { … },+
"yaw_angle": { … }
},+
"race": { … - "confidence": 95.5922,
- "value": "White"
},+
"smiling": { … }
},- "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": { … },+
"gender": { … - "confidence": 99.6509,
- "value": "Female"
},+
"glass": { … - "confidence": 99.9069,
- "value": "None"
},+
"pose": { … +
"pitch_angle": { … },+
"roll_angle": { … },+
"yaw_angle": { … }
},+
"race": { … - "confidence": 99.2528,
- "value": "White"
},+
"smiling": { … }
},- "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
要素を重ね合わせたものです。

2人目
1人目
画像に枠を重ねる場合、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 )
{
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 ] ;
attr_id = attr_class_1 + i ;
$( '#' + 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++ )
{
attr_id = attr_class_2 + i + '-' + ii ;
$( '#' + id ).after( '<div id="' + attr_id + '"></div>' ) ;
$( '#' + 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>
このコードの動作を確認する