LINE BOT APIが公開されたので、興味本位で作ってみました。Webプログラミングは趣味レベルですが、
とりあえず形になったので備忘録として残しておきます。
#とりあえず作ったもの
写真を送ると、顔のアップと、年齢・性別の推定結果を返してくれます。
1枚の画像から複数人同時に認識もでき(最大人数は不明)、複数人認識した場合は連続で推定結果を返してくれます。
実運用は想定していませんので下記記事で言う「多くの人がやっちゃう間違い」アーキテクチャです。
大量メッセージが来ても安心なLINE BOTサーバのアーキテクチャ - Qiita
興味本位で作ったBOTなので、trialが外れたら本BOTのサービスを停止する可能性が高いです。
#構成
分類 | 環境 |
---|---|
PaaS | IBM bluemix |
顔認識 | Microsoft Face API |
言語 | PHP |
タダが大前提だったんですが、herokuではなくbluemixを選んだのは、Qiitaのまとめの記事(後述)を読んだからです。顔認識もIBMにはWatsonさんがいるのですが、精度があまり良くないとの記事を読んだので、MSのFace APIにしました。PHPは適当にチョイスしました。
なお、Face APIは、無料版だと3万回/月、20回/分の呼び出しが可能とのことです。
30,000 transactions per month, 20 per minute.
#参考
リファレンスには目を通しておいたほうがいいです。
実際の作業については、既に親切な方々がまとめてくれています。
- LINE BOT API Trialでできる全ての事を試してみた - Qiita
- LINE BOT をとりあえずタダで Heroku で動かす - Qiita
- Herokuでbotを運用する時代は終わった。これからはIBM Bluemixを使って無料で運用する - Qiita
Line BOTでオウム返しができるようにするには、上記記事などが大変参考になりますので、
以降にはBluemixとFaceAPIに要点を絞って記述します。
#Bluemix
BluemixではCFアプリケーションを選択しました。
gitリポジトリも用意されているのですが、何故かcloneできなかったためCloud Foundryを使用しました。
ローカルでコーディングを行って、cfコマンドでpushします。
Bluemixでは、デプロイのたびにipが変わるので、Server IP Whitelistへの登録は毎回行いました(コンテナだと固定IP使えるそうです)。
#Face API
Face APIでは、画像のURLの他にもバイナリデータを送信することができます。
LINE BOT APIから画像データを取得する
<messageId>を取得したのち、再度問い合せを行うことで画像データを取得することができます。
Getting previews of message content
// 画像データを取得する
function api_get_message_content_request($message_id) {
$url = "https://trialbot-api.line.me/v1/bot/message/{$message_id}/content";
$headers = array(
"X-Line-ChannelID: {$GLOBALS['CHANNEL_ID']}",
"X-Line-ChannelSecret: {$GLOBALS['CHANNEL_SECRET']}",
"X-Line-Trusted-User-With-ACL: {$GLOBALS['MID']}"
);
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
$header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);
error_log("res header::".$header);
error_log("res body::".$body);
return array( "header"=>$header, "body"=>$body);
}
画像データを送って顔認証を行う
取得した画像データを使ってFace APIを呼び出します。
// (メンバ関数)バイナリデータから顔認証を行う
public function analyze_from_binary($img_binary) {
$headers = array(
"Content-Type" => "application/octet-stream"
);
$request = new Http_Request2("https://api.projectoxford.ai/face/v0/detections");
$request->setConfig(array(
"ssl_verify_peer" => false,
));
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setHeader($headers);
$url = $request->getUrl();
$url->setQueryVariables($this->query_params);
if( empty($img_binary)){
return false;
}
$request->setBody($img_binary);
try
{
$response = $request->send();
$status = $response->getStatus();
$body_json = json_decode($response->getBody());
error_log( "resp status::".$response->getStatus() );
error_log( "resp body::".$response->getBody() );
if($status != 200){
if( $status == 400 || $status == 408 || $status == 415 ){
return array (
"result" => false,
"code" => $body_json->{"code"},
"message" => $body_json->{"message"}
) ;
}
else if( $status == 401 || $status == 403 || $status == 429 ){
return array (
"result" => false,
"code" => $body_json->{"statusCode"},
"message" => $body_json->{"message"}
) ;
}else{
return array (
"result" => false,
"code" => "unknown",
"message" => "unknown error"
) ;
}
}
return array (
"result" => true,
"faces" => $body_json
) ;
}
catch (HttpException $ex)
{
throw $ex;
}
}
※aplication/octet-streamにすることを忘れずに。
あとは、取得したデータから顔をクリップして年齢と性別を送ってあげれば、完了です。
-
githubリポジトリ
※ただしこれだけでは動かないので、パーツとしてご利用ください。