こんばんは。
先日、PHPの公式を見ていたら走る象さんが現れました。画面左上。
拡大するとこれ。必死に走っていました。
この象さんは64分の1の確率で現れてくれるらしいです。
よかったよかった。
SkyBiometry使ってみました
話は変わりますが、最近「SkyBiometry」という顔認識APIを使う機会があったので、忘れないうちに書いてみたいと思います。
これは何ぞって、「写真のURLとパラメータを送ると、その写真の中にある顔の座標や特徴量を返してくれる」APIになります。
さらに、UID(user id)と同一人物の複数の顔情報TID(tag id)を結び付けて学習させることで顔認識の精度を上げることができ、且つ類似度の算出が可能になるみたいです。
まずsign up nowしてみましょう。
マイページはこんな感じです。APIを叩いた回数がグラフ化されており、API keyやAPI secret、UIDを束ねるnamespaceの設定が行なえます。ちなみに無料版ですと5000回/1ヶ月、100回/1時間叩くことができます。
API keyとAPI secretが入手出来たらあとは簡単です。
下記の形式でURLを叩くだけで結果を取得することができます。
http://api.skybiometry.com/fc/{API method}.{response format}
?api_key={自分のアカウントページのAPI key}
&api_secret={自分のアカウントページのAPI secret}
&{other parameters}
上記のAPI methodやresponse format、other parametersに関してはドキュメントのページに書いてあります。
例えば、「faces/detect」という顔を発見するAPI methodを使いたい、「JSON形式」のレスポンスで受け取りたい、WikipediaでFaceと検索して出てきた「顔の画像URL」の「顔座標をすべて取得」したい、という要望には下記の記述で答えることができます。
http://api.skybiometry.com/fc/faces/detect.json
?api_key={自分のアカウントページのAPI key}
&api_secret={自分のアカウントページのAPI secret}
&urls=http://upload.wikimedia.org/wikipedia/commons/thumb/5/55
/Mona_Lisa_headcrop.jpg/640px-Mona_Lisa_headcrop.jpg
&detect_all_feature_points=true
下記がレスポンスのJSONです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
{ "operation_id": "b0678e98d8714d46a70b328d3bc*****", "photos": [ { "height": 798, "pid": "F@049131163a6cb9ed055c437a0b4f75d7_8d713d23*****", "tags": [ { "attributes": { "face": { //信用度83で顔を認識 "confidence": 83, "value": "true" } }, "center": { //顔の中心の座標 "x": 50.16, "y": 36.47 }, "confirmed": false, "eye_left": { //左目の座標 "confidence": 50, "id": 449, "x": 50.0, "y": 31.08 }, "eye_right": { //右目の座標 "confidence": 50, "id": 450, "x": 35.16, "y": 31.08 }, "height": 24.44, "label": null, "manual": false, "mouth_center": { //口の座標 "confidence": 50, "id": 615, "x": 40.31, "y": 45.61 }, "nose": { //鼻の座標 "confidence": 50, "id": 403, "x": 39.22, "y": 39.47 }, "pitch": 0, "points": [ //ここから顔の詳細座標 { "confidence": 50, "id": 768, "x": 31.09, "y": 31.33 }, { "confidence": 50, "id": 769, "x": 30.0, "y": 36.22 }, { "confidence": 50, "id": 770, "x": 32.03, "y": 41.1 }, //この間、約60の座標を省略 { "confidence": 50, "id": 834, "x": 40.31, "y": 45.61 }, { "confidence": 50, "id": 835, "x": 39.22, "y": 39.47 } ], "recognizable": true, "roll": 0, "similarities": null, "tid": "TEMP_F@049131163a6cb9ed055c437a01410123_8d713d23a73*****.16_36.4*****", //TIDはこの写真のこの顔TAGに結び付いたID "uids": [], "width": 30.47, "yaw": 45 } ], "url": "http://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Mona_Lisa_headcrop.jpg/640px-Mona_Lisa_headcrop.jpg", "width": 640 } ], "status": "success", //failureの際はエラーコードが付きます "usage": { "limit": 100, "remaining": 98, "reset_time": 1424692786, "reset_time_text": "Mon, 23 February 2015 11:59:46 +0000", "used": 2 } } |
顔の座標や特徴量が取れました。other parametersの設定(例えば「attributes=all」など)により、他の情報も取得できます。
GDで顔座標をプロット
PHPでAPIの返り値を使いたいので、curl関数を使います。curl関数の使い方はこのあたりを参考にさせていただきました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//自分のアカウントページのものを定数化しておきます define("FACE_API_KEY", "********************************"); define("FACE_API_SECRET", "********************************"); define("FACE_API_METHOD", "faces/detect"); define("FACE_API_RESPONSE", "json"); define("FACE_API_URL", "http://api.skybiometry.com/fc/".FACE_API_METHOD.".".FACE_API_RESPONSE); //顔認識したい画像URLはこちら $url = "http://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Mona_Lisa_headcrop.jpg/640px-Mona_Lisa_headcrop.jpg"; //APIたたく準備します $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, FACE_API_URL); curl_setopt($curl, CURLOPT_POST, TRUE); //GETで渡していたパラメータはPOSTで送ります $params = array( "api_key" => FACE_API_KEY, "api_secret" => FACE_API_SECRET, "urls" => $url, "detect_all_feature_points" => "true", "attributes" => "all" ); //APIたたきます curl_setopt($curl, CURLOPT_POSTFIELDS, $params); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $response = curl_exec($curl); $header = curl_getinfo($curl); |
ここまでで、APIのパラメータの設定をしてその結果を$responseに格納することができました。
ここから、簡単なエラーチェックを行ない顔の座標をプロットして行きます。ちなみに顔の座標情報は「$data[“photos”][0][“tags”][0][“points”]」の中にあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//もろもろのエラーチェック $code = $header["http_code"]; //APIのHTTPコードをチェック if($code >= 400) { header("HTTP", true, $code); echo "レスポンスエラーです:".$response; exit; } $data = json_decode($response, true); //APIの実行結果をJSONパーサでパースし$dataに格納します if(count($data["photos"][0]["tags"]) > 1){ echo "顔が複数あります"; exit; }elseif(count($data["photos"][0]["tags"]) == 0){ echo "顔がありません"; exit; } //GDを使い元の画像からイメージ生成します $original_image = imagecreatefromstring(file_get_contents($url)); //座標をプロットしたイメージを生成して上記と重ねて出力します $plot_image = generatePlotImage($data["photos"][0]["width"], $data["photos"][0]["height"], $data["photos"][0]["tags"][0]["points"], $original_image); imagecopy($original_image, $plot_image, 0, 0, 0, 0, $data["photos"][0]["width"], $data["photos"][0]["height"]); //重ね合わせる header('Content-Type: image/png'); //出力します imagepng($original_image); imagedestroy($original_image); imagedestroy($plot_image); exit; |
21行目のgeneratePlotImage関数では、元の画像の顔の上に顔の座標点をプロットするため、透過可能なpngイメージを生成しています。22行目のimagecopy関数で元のイメージと前述した関数によって生成されたイメージとを重ね合わせています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
function generatePlotImage($width, $height, $points_array){ //点を相対座標から絶対座標に変換 foreach($points_array as $key=>$value) { $point = array($value["x"]*($width/100), $value["y"]*($height/100)); $points[] = $point; } //Create image using GD $plot_image = imagecreatetruecolor($width, $height); $white = imagecolorallocatealpha($plot_image, 255, 255, 255, 127); $green = imagecolorallocate($plot_image, 50, 255, 0); imagefill($plot_image, 0, 0, $white); //顔の座標に点を打っていきます foreach($points_array as $key=>$value) { imagerectangle($plot_image, $value["x"]*($width/100)-1, $value["y"]*($height/100)-1, $value["x"]*($width/100)+1, $value["y"]*($height/100)+1, $green); } return $plot_image; } |
重ね合わせ生成された画像がこれです!
APIが認識した顔の座標点が緑色にプロットされていますね。
ではまた次回(゜-゜)