社内ハッカソンで Azure FaceAPI, Emotion API を使用した API を作成する機会がありましたので、簡単な利用の流れをサンプルソースとともに記述します。 ※サンプルソースは取りあえずのものなので、モダンとか書き方なんかは全然こだわっていません。。。

【環境】 Windows10 + VirtualBox 5.1.6 + Ubuntu 14.04 LTS Apache/2.4.7 + PHP 7.0.8

【 FaceAPI, Emotion API を使って作ったもの】 顔画像を送信すると、 Face API で個人を識別、 Emotion API でその顔から感情を読み取り、ポジティブな感情か、ネガティブな感情かで得点を加減していくような仕組み。 ポジティブ人間ランキングみたいなものを出してみたりする。

0.事前準備

Microsoft Azure に登録し、 Cognitive Services APIs の Face API と Emotion API を 登録します。(無料試用版があります) → https://azure.microsoft.com/ja-jp/free/

1.Face List の登録

Face API を使う前に、 Face List を登録しておく必要があります。 顔画像を入れていく箱を用意するような感じです。

https://westus.api.cognitive.microsoft.com/face/v1.0/facelists/{faceListId}/

faceListId は任意の ID を入れてください。 Curl で良いので先に実行しておきます。

2.顔情報を取得( Face API )

まずは FaceAPI で顔画像を解析し、未登録の顔であれば新しく faceList に追加するクラスを作成します。 (顔画像は URL で渡す必要があるので、事前にどこかのサーバーにアップロードされている必要があります)

<?php
require_once 'HTTP/Request2.php';

class Face {
  private $headers;
  private $img_url;
  private $face_list_id = (登録した faceListId);
  private $subscription_key = (サブスクリプションキー);

  function __construct($img_url)
  {
    $this->headers = array(
      'Content-Type' => 'application/json',
      'Ocp-Apim-Subscription-Key' => $this->subscription_key
    );
    $this->img_url = $img_url;
  }

  // 既存の顔か、新規の顔かチェック
  function checkFace()
  {
    $request = $this->getRequestObject('https://api.projectoxford.ai/face/v1.0/findsimilars');

    $face_data = $this->getFaceData();

    if(!$face_data) {
      return null;
    }

    $req['faceId'] = $face_data['face_id'];
    $req['faceListId'] = $this->face_list_id;
    $req['maxNumOfCandidatesReturned'] = 10;
    $req['mode'] = 'matchPerson';
    $json = json_encode($req);

    $request->setBody($json);
    $response = $request->send();
    $ret = json_decode($response->getBody());

    if($ret) {
      $persistedFaceId = $ret[0]->persistedFaceId;

      // echo '一致した Face ID : ' . $persistedFaceId . "<br>\n";
      // echo '一致率: ' . $ret[0]->confidence * 100 . "%<br>\n";
    }
    else {
      $persistedFaceId = $this->addFace();

      // echo '一致しませんでした。' . "<br>\n";
      // echo '新しい Face ID : ' . $persistedFaceId;
    }

    $result['person_id'] = $persistedFaceId;
    $result['age'] = $face_data['age'];
    $result['gender'] = $face_data['gender'];

    return $result;
  }

  // 顔の情報を取得
  private function getFaceData()
  {
    $request = $this->getRequestObject('https://api.projectoxford.ai/face/v1.0/detect');

    $query_params = array(
      'returnFaceAttributes' => 'age,gender'
    );

    $url = $request->getUrl();
    $url->setQueryVariables($query_params);

    $req['url'] = $this->img_url;
    $json = json_encode($req);
    $request->setBody($json);

    $response = $request->send();
    $ret = json_decode($response->getBody());

    if(!$ret) {
      return null;
    }

    $result['face_id'] = $ret[0]->faceId;
    $result['age'] = $ret[0]->faceAttributes->age;
    $result['gender'] = $ret[0]->faceAttributes->gender;

    return $result;
  }

  // 顔を登録
  private function addFace() {
    $request = $this->getRequestObject('https://api.projectoxford.ai/face/v1.0/facelists/' . $this->face_list_id . '/persistedFaces');

    $req['url'] = $this->img_url;
    $json = json_encode($req);
    $request->setBody($json);

    $response = $request->send();
    $ret = json_decode($response->getBody());

    return $ret->persistedFaceId;
  }

  private function getRequestObject($api_url)
  {
    $request = new Http_Request2($api_url);
    $request->setConfig(array('ssl_verify_peer' => false));
    $request->setMethod(HTTP_Request2::METHOD_POST);
    $request->setHeader($this->headers);

    return $request;
  }
}

3.表情から感情を取得( Emotion API )

画像 URL を Emotion API に渡し、表情から感情を解析します。 Emotion API からは表情のスコアは下記のような感じで返ってきます。

"scores": {
  "anger": 0.00300731952,
  "contempt": 5.14648448E-08,
  "disgust": 9.180124E-06,
  "fear": 0.0001912825,
  "happiness": 0.9875571,
  "neutral": 0.0009861537,
  "sadness": 1.889955E-05,
  "surprise": 0.008229999
}

一番スコアの高い感情を取得して返すクラスを作成します。

<?php
require_once 'HTTP/Request2.php';

class Emotion {
  private $headers;
  private $img_url;
  private $subscription_key = (サブスクリプションキー);

  function __construct($img_url)
  {
    $this->headers = array(
      'Content-Type' => 'application/json',
      'Ocp-Apim-Subscription-Key' => $this->subscription_key
    );
    $this->img_url = $img_url;
  }

  // 感情を解析
  function getEmotion()
  {
    $request = new Http_Request2('https://api.projectoxford.ai/emotion/v1.0/recognize');
    $request->setConfig(array('ssl_verify_peer' => false,));
    $request->setMethod(HTTP_Request2::METHOD_POST);
    $request->setHeader($this->headers);

    $req['url'] = $this->img_url;
    $json = json_encode($req);
    $request->setBody($json);

    $response = $request->send();
    $ret = json_decode($response->getBody());

    if(!$ret) {
      return null;
    }

    $scores = $ret[0]->scores;
    $emotions = array(
      'anger' => $scores->anger,
      'contempt' => $scores->contempt,
      'disgust' => $scores->disgust,
      'fear' => $scores->fear,
      'happiness' => $scores->happiness,
      'neutral' => $scores->neutral,
      'sadness' => $scores->sadness,
      'surprise' => $scores->surprise,
    );

    // 戻り値の中から一番顕著な感情を取得する。
    $max_point = max($emotions);
    $hit_emotions = array_keys($emotions, $max_point);
    $array_num = array_rand($hit_emotions, 1); // 同点対応
    $emotion = $hit_emotions[$array_num];

    $result['emotion'] = $emotion;
    $result['point'] = $emotions[$emotion];

    return $result;
  }
}

4.取得した感情に、感情係数を加算したりする

あとはこんな感じで適当に、よりポジティブな感情であればプラス得点、よりネガティブな感情であればマイナス得点となるようにポイントを設定しておいて、取得した感情ごとにポイントを加算していけば、ポジティブ人間ランキングのできあがりです。

array(
  'anger' => -3500,
  'contempt' => -1000,
  'disgust' => -2000,
  'fear' => -500,
  'happiness' => 3500,
  'neutral' => -30,
  'sadness' => -1000,
  'surprise' => -500,
);

まとめ

顔解析や感情解析など、少し前にはとても難しいイメージのものでしたが、今はこんなに簡単に実装することができます。 Cognitive Services APIs には他にも面白い機能がありますので、ぜひ色々試してみてください。