Microsoft Azure Face APIを触ってみた&Pepperで動かしてみた


イサナドットネットのブログからの転載です。

【引用元】
http://blog.isana.net/2017/02/microsoft-azure-face-apipepper.html

はじめに

Microsoft Azureでは、クラウドベースで動作する強力な認知API群であるCognitive Service APIが提供されています。

このAPIの1つ、Face APIは、写真中の顔を検出、分析することができるAPIで、静岡県の特別養護老人ホーム「まごころタウン」で行われたPepperの実証実験において、Pepperアプリ内に組み込む形で使われました。
今回は、実際にFace APIを使って顔画像を分析する手順を紹介します。

※記載情報は全て2017年1月現在のものです。

Face APIを実際に使ってみる

Cognitive Servicesアカウントの作成

まず、AzureポータルでAzureアカウントを作成、ログインします。
次に、ポータル左上の「新規」をクリックし、「Marketplaceを検索」の欄に「Cognitive services APIs」と入れて検索してみます。

検索結果の「Cognitive Services APIs(プレビュー)をクリックし、ブレードに概要が表示されるので、「作成」をクリックします。

  • Account name: Cognitive Services用の名前を入力(重複不可)
  • サブスクリプション: 任意
  • API Type: Face APIを選択
  • 場所:米国西部のみ(2017年1月現在)
  • 価格レベル: Free/F0(無料)とStanderd/S0(有料)プランがある。Cognitive ServicesのF0プランは1サブスクリプション内に1つのみ作成可能。機能の違いはAPIコール回数に制限がある程度
  • Resource group: 別途作成したものがある場合「既存のものを使用」を選択することができる。新規作成したい場合は「新規作成」を選択し、一意な名前を付ける 規約に同意して"I have read and agree~"のチェックボックスをオンにする

全ての項目を選択後、「作成」をクリックすると、Cognitive Services用のアカウントが作成されます。

作成後、「すべてのリソース」から作成したアカウントを選択すると、アカウントの詳細が表示されます。

左側の「Keys」をクリックし、表示されたKEY 1をコピーしてどこかに保存しておいてください。

実際に使ってみる

まず、ここのページの「Open API Testing Console」をクリックして、Face APIの機能をブラウザで試してみます。

Query parametersでは、APIコール時に取得できる顔写真の情報を設定します。

  • returnFaceId: 画像左上からの顔の位置(top, left, width, height)を返す
    • 値: true / false
  • returnFaceLandmarks: returnFaceLandmarks: 詳細な顔パーツの位置を返す
    • 値: true / false
  • returnFaceAttributes: 顔の特徴を返す
    • 値: age(年齢)/ gender(性別)/ headPose(顔の角度)/ smile(笑顔度)/ facialHair(ひげ度合い)/ glasses(メガネの種類) カンマ区切りで複数指定可能

Headersでは、リクエストのヘッダ情報を設定します。

  • Content-Type: 戻り値の形式
    • 値: application/json(JSON形式)/ application/octet-stream(バイナリ形式)
    • 画像URLを送る場合はJSON、ローカルデータを送る場合はバイナリ形式
  • Ocp-Apim-Subscription-Key: Cognitive Serviceアカウント作成後に、AzureポータルでコピーしたKEY 1を入力

Request bodyでは、実際にAPIに送る画像情報を入力します。
HeadersでJSON形式を選択した場合は画像URLをキー"url"に設定し、バイナリ形式を選択した場合は、画像を文字列に変換したものをフィールドに入力します。

今回は、JSON形式で結果を取ってみます。
画像は、ブログ右上のこの写真にしましょう。

リクエスト用URLとHTTPリクエスト本体の完成です。

「Send」をクリックして、URLをPOSTします。

返ってきたJSONはこちらです。

[  
  {  
   "faceId": "f9e95e85-2d58-4269-9354-5ed5e00a9bbb",  
   "faceRectangle": {  
    "top": 55,  
    "left": 163,  
    "width": 75,  
    "height": 75  
   },  
   "faceAttributes": {  
    "smile": 1.0,  
    "headPose": {  
     "pitch": 0.0,  
     "roll": -12.7,  
     "yaw": -35.0  
    },  
    "gender": "male",  
    "age": 29.3,  
    "facialHair": {  
     "moustache": 0.1,  
     "beard": 0.0,  
     "sideburns": 0.2  
    },  
    "glasses": "ReadingGlasses"  
   }  
  }  
 ]

"faceID"は、認識した顔に個別に割り振られるユニークなIDです。
"faceAttributes"を見ると、年齢や性別の他にも頭の角度、ひげやメガネの状態まで取ることができます。元の顔写真と比較しても、正確に取れているのではないのでしょうか。

応用:PepperでFace APIをコールする

Cognitive APIは、REST形式ですので、Pepperアプリ内から直接コールすることも可能です。

(※上記実証実験アプリでは、faceIDと利用者の名前を紐付けるため、PepperアプリからAzure Web Appを経由してFace APIをコールしています)

Face APIのリファレンス下部の「Code samples」欄に、各言語でAPIコールするためのテンプレートが用意されています。
Python用のテンプレートも用意されていますので、こちらを使います。
今回は、実際にPepperが撮影した顔写真を直接Face APIに送信してみます。

【Face Detectボックスの詳細】

  • 変数
    • Subscription-Key:Azureポータルでコピーしたサブスクリプションキー
    • FaceID:Testing Console上のreturnFaceId
    • FaceLandmarks:Testing Console上のreturnFaceLandmark

このボックスでは、PepperがTake Picturesボックスで撮影した写真のパスを受け取った後、写真をFace APIに投げて、その人の年齢と性別をログに出力しています。
顔の特徴も変数で指定できればよかったのですが、項目が多くなりそうだったので省略しました。
Testing Console上ではjson形式で写真のアドレスを投げていましたが、Pepperからは撮影した写真をバイナリ形式で送信します。

【Face DetectボックスのonInput_onStart部分を抜粋】

def onInput_onStart(self, p):
    import httplib
    import urllib
    import base64

    img_path = p
    #ヘッダー生成:写真のバイナリファイルを送るのでoctet-streamを指定する
    headers = {'Content-Type': 'application/octet-stream','Ocp-Apim-Subscription-Key': self.getParameter('Subscription-Key')}
    params = urllib.urlencode({
    # Request parameters
    'returnFaceId': self.getParameter('FaceId'),
    'returnFaceLandmarks': self.getParameter('FaceLandmarks'),
    'returnFaceAttributes': 'gender,age',
    })

    try:
        conn = httplib.HTTPSConnection('westus.api.cognitive.microsoft.com')
        conn.request("POST", "/face/v1.0/detect?%s" % params, open(img_path, 'rb'), headers)
        response = conn.getresponse()
        data = response.read()
        result = json.loads(data)
        if(result):
            self.logger.info("FaceAPI Age : " + str(result[0]['faceAttributes']['age']))
            self.logger.info("FaceAPI Gender : " + str(result[0]['faceAttributes']['gender']))
            conn.close()
            self.onStopped()

        except Exception as e:
            self.logger.warning(e)

アプリ再生後、Pepperの頭をタッチして顔写真を撮影し、ログを確認します。

[I] 1484881369.477206 3984 behavior.box: _Behavior__lastUploadedChoregrapheBehavior775395016:/Face Detect_8: FaceAPI Age : 24.4
[I] 1484881369.478232 3984 behavior.box: _Behavior__lastUploadedChoregrapheBehavior775395016:/Face Detect_8: FaceAPI Gender : female

性別と年齢が取れました!
ただ、Pepperの頭が動いてしまうことでうまく顔写真が取れないことも多いので、撮影時に頭の動きを止める工夫が必要です。

まとめ・所感

Pepperだけでも性別・年齢の判定はできますが、個人を判別することはできません。

Face APIを使うと顔別にfaceIDを発行することで、個人を識別することが可能です。

また、Azure Web Appなど、Azureが提供する他サービスと容易に連携できるので、アプリ自体の拡張性も高くなるかと思います。