【LINE Bot】 bluemixとFaceAPIを使った年齢性別推定Bot

  • 54
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

LINE BOT APIが公開されたので、興味本位で作ってみました。Webプログラミングは趣味レベルですが、
とりあえず形になったので備忘録として残しておきます。

とりあえず作ったもの

写真を送ると、顔のアップと、年齢・性別の推定結果を返してくれます。
IMG_2113.PNG
1枚の画像から複数人同時に認識もでき(最大人数は不明)、複数人認識した場合は連続で推定結果を返してくれます。

登録用のQRコードは下記になります。
uao3236v.png

実運用は想定していませんので下記記事で言う「多くの人がやっちゃう間違い」アーキテクチャです。
大量メッセージが来ても安心な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でオウム返しができるようにするには、上記記事などが大変参考になりますので、
以降にはBluemixとFaceAPIに要点を絞って記述します。

Bluemix

BluemixではCFアプリケーションを選択しました。
gitリポジトリも用意されているのですが、何故かcloneできなかったためCloud Foundryを使用しました。
blue02.png

ローカルでコーディングを行って、cfコマンドでpushします。
Bluemixでは、デプロイのたびにipが変わるので、Server IP Whitelistへの登録は毎回行いました(コンテナだと固定IP使えるそうです)。
linebo01.png

Face API

Face APIでは、画像のURLの他にもバイナリデータを送信することができます。

oct1.png

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リポジトリ
    ※ただしこれだけでは動かないので、パーツとしてご利用ください。