Azure Face APIで顔を識別する手順をcurlで追う


会社のテックWebマガジン コピペテック で、micro:bitと組み合わせた入室管理アプリケーションの記事を公開予定です。
紹介しているのは、人感センサー(焦電赤外線センサー)でオフィスの入出を検知してmicro:bitからiPhoneにコマンドを送って写真を撮り、IFTTT経由でWebhookを叩いて、Microsoft AzureのFace APIで誰が来たか識別し、Slackにお知らせするというシステムです。

このシステムでは、人の検出と、新しく来た人の登録するところでAzure Face APIを利用していますが、この手順について調べた内容についてせっかくなのでまとめて置きたいと思います。

手元の画像でFace APIについてちょろっと試すには、サイトのトップページでも試すことができます。まずは、ここで遊んで精度を確認してみるのも良いかもしれません。

AzureにFace APIリソースを追加

Face APIを利用するには、Azureポータルで「Face API」リソースを作成して、APIキーを取得します。

Azure ポータルにサインインして、画面の左のメニューから、[すべてのサービス] > [AI + MACHINE LEARNING]から[Cognitive Service]を選択します。

Cognitive Servicesのページに切り替わるので、左上の[追加]ボタンまたは[Congnitive Serviesの作成]ボタンをクリックします。

AI + Machine Learningのページで、Cognitive Servicesの[さらに表示]をクリックします。


右に開いたAPI一覧から[Face]を選択し、[作成]をクリックします。

作成フォームが開きます。
[Name]には適当な名前を入れ、サブスクリプションは「Azure Free Trial」を選択します。
[場所]は「東日本」(japaneast)を選択し、価格レベルは「F0」、[Resource Group]は適当に作成したものを選択して[作成]をクリックします。

リソースの作成が完了すると以下のポップアップが表示されるので、ダッシュボードに登録しておきます。(登録しなくてもOKです)

ダッシュボードから、作成した[HelloFaceDetection]を選択

左から[Keys]を選択します。

[KEY 1]は、APIの認証に使います。
コピーして控えておきます。

顔検出APIで疎通確認

まずはAzureに追加したリソースから取得したキーでAPIにアクセスできるか確認してみます。
クイック スタート: REST API と cURL を使って画像の中にある顔を検出する – Azure Cognitive Services | Microsoft Docs」を参考に顔検出をしてみます。

顔検出はhttps://<リージョン>.api.cognitive.microsoft.com/face/v1.0/detectに画像のURLか画像のバイナリをPOSTすると結果が返ってきます。
上記のクイックスタートでは、URLに指定した画像の検出をしていますが、ここでは手元の画像をPOSTしてみます。

以下、curlを使って、検出する属性faceAttributesageemotionを指定し、カレントディレクトリにある写真photo.jpgをPOSTする例です。
HTTPヘッダOcp-Apim-Subscription-Keyに、作成したリソースの[KEY 1]の値をセットします。
リージョンは「東日本」なのでPOST先のURLにjapaneastを指定しています。

curl -X POST \
  -H "Ocp-Apim-Subscription-Key: <Subscription Key>" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @photo.jpg \
  "https://japaneast.api.cognitive.microsoft.com/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,emotion"

この応答は以下、1歳のときの子供が笑っている写真を検出してみたところ、そのとおりの結果が取得出来ました。

[
    {
        "faceId": "f99ce335-03ef-44c7-b5e8-b68249ac3800",
        "faceRectangle": {
            "top": 855,
            "left": 2875,
            "width": 741,
            "height": 741
        },
        "faceAttributes": {
            "age": 1.0,
            "emotion": {
                "anger": 0.001,
                "contempt": 0.0,
                "disgust": 0.0,
                "fear": 0.0,
                "happiness": 0.997,
                "neutral": 0.001,
                "sadness": 0.001,
                "surprise": 0.0
            }
        }
    }
]

写真の顔を識別して名前を取得

さて本題の、写真に写っているのは誰かを識別する手順を確認してみます。

参考にしたドキュメントは、「例: 画像内の顔を識別する – Face API – Azure Cognitive Services | Microsoft Docs」です。

確認に使う画像は、上記ドキュメントに記載されているCognitive-Face-Windows/Data at master · Microsoft/Cognitive-Face-Windowsからダウンロードした画像を使用しました。

ざっくりした流れは以下のとおりです。

  1. PersonGroupを作成します。PersonGroupは、識別したい人をグルーピングするコレクションです。例としては、会社であれば社員を登録するなどでしょうか。
  2. PersonGroupに人物(Person)を登録します。
  3. 人物に、写真(Face)を登録します。複数人含まれている写真を登録する場合は、写真の検出を行いFaceを取得し検出された顔をそれぞれPersonに追加することもできます。
  4. 人物と写真の追加が終わったらPersonGroupの学習をします。
  5. 以上で、PersonGroupに対して写真の中の人物を識別できるようになります。

では、以下curlでこの手順を追ってみます。

1. PersonGroup を作成する

PersonGroup – Create APIでPersonGroupを作成します。
リクエストボディには、nameフィールドのみ含むJSONをPOSTしています。

$ curl -v -X PUT \
  -H 'Content-Type:application/json' \
  -H 'Ocp-Apim-Subscription-Key:<Subscription Key>' \
  -d '{"name":"My Co-worker"}' \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/persongroups/mycoworker

成功するとレスポンス200が返ってきます。応答ボディは空(Content-Length: 0)です。

PersonGroup – Getで、作成したPersonGroupを確認してみます。

$ curl -H 'Ocp-Apim-Subscription-Key:<Subscription Key>' \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/persongroups/mycoworker
{"personGroupId":"mycoworker","name":"My Co-worker","userData":null}

2. PersonGroupに人物を追加する

作成したPersonGroupに、PersonGroup Person – Create APIで人物 Personを追加します。

$ curl -v -X POST \
  -H 'Content-Type:application/json' \
  -H 'Ocp-Apim-Subscription-Key:<Subscription Key>' \
  -d "{'name': 'bill'}" \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/persongroups/mycoworker/persons
...
{"personId":"5723e747-932d-4472-925f-fbf9c8cc767e"}

「bill」に続いて「clare」も追加してみます。

$ curl -v -X POST \
  -H 'Content-Type:application/json' \
  -H 'Ocp-Apim-Subscription-Key:<Subscription Key>' \
  -d "{'name': 'clare'}" \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/persongroups/mycoworker/persons
...
{"personId":"b3fecf88-cac2-489b-9c6d-3c1b1d070f93"}

3. 人物に顔(Face)を追加

人物に顔(Face)つまり写真を追加していきます。

PersonGroup Person – Add Face APIで人物に顔を追加します。

「bill」に写真を追加します。
「bill」のpersionId「5723e747-932d-4472-925f-fbf9c8cc767e」をURLに指定します。

curl -v -X POST \
  -H 'Content-Type:application/octet-stream' \
  -H "Ocp-Apim-Subscription-Key:<Subscription Key>" \
  --data-binary @/path/to/Cognitive-Face-Windows-master/Data/PersonGroup/Family1-Dad/Family1-Dad1.jpg \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/persongroups/mycoworker/persons/5723e747-932d-4472-925f-fbf9c8cc767e/persistedFaces
...
{"persistedFaceId":"495c20ef-cb56-41d1-901c-2c0fe91a3670"}

「clare」も同様にファイルを追加していきます。
「clare」のpersionIdは「b3fecf88-cac2-489b-9c6d-3c1b1d070f93」を指定します。

curl -v -X POST \
  -H 'Content-Type:application/octet-stream' \
  -H "Ocp-Apim-Subscription-Key:<Subscription Key>" \
  --data-binary @/path/to/Cognitive-Face-Windows-master/Data/PersonGroup/Family1-Mom/Family1-Mom1.jpg \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/persongroups/mycoworker/persons/b3fecf88-cac2-489b-9c6d-3c1b1d070f93/persistedFaces
...
{"persistedFaceId":"495c20ef-cb56-41d1-901c-2c0fe91a3670"}

PersonGroup Person – Add Faceは、1人づつの登録する必要があるため、1枚の写真に複数の人物が写っている場合は、Face Detectを実行した結果から検出された位置をtargetFaceに渡して人数分Add Face APIを呼ぶ必要があります。
サンプルデータは1枚に一人づつしか写ってないのでこの手順は省略しました。

4. PersonGroup のトレーニング

一通り写真を登録したら、PersonGroup – Train APIを実行して学習します。

curl -v -X POST \
  -H "Ocp-Apim-Subscription-Key:<Subscription Key>" \
  -d "" \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/persongroups/mycoworker/train

レスポンスコード202が返ってくると学習が開始されます。

学習学習は非同期に実行されます。学習のステータスチェックは[PersonGroup – Get Training Status](PersonGroup – Get Training Status) APIで確認できます。

curl -v -X GET \
  -H "Ocp-Apim-Subscription-Key:<Subscription Key>" \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/persongroups/mycoworker/training
...
{"status":"succeeded","createdDateTime":"2018-10-22T07:36:00.9574792Z","lastActionDateTime":"2018-10-22T07:36:01.1301022Z","message":null}

5. PersonGroup に対して顔を識別する

学習済みのPersonGroupに対して、新しい写真を識別するには、Face – Identify APIを使います。

Face Identify APIには、Face Idの配列faceIdsを渡す必要があるので、まずは識別する画像を検出します。

curl -v -X POST \
  -H 'Content-Type:application/octet-stream' \
  -H "Ocp-Apim-Subscription-Key:<Subscription Key>" \
  --data-binary @/path/to/Cognitive-Face-Windows-master/Data/identification1.jpg \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/detect
...
[
    {
        "faceId": "54850407-215c-46fd-9e26-b283c4baeaf5",
        "faceRectangle": {
            "top": 202,
            "left": 302,
            "width": 113,
            "height": 113
        }
    },
    {
        "faceId": "a9925edb-8d68-42c1-9928-9551f0c5d4fc",
        "faceRectangle": {
            "top": 238,
            "left": 398,
            "width": 91,
            "height": 91
        }
    },
    {
        "faceId": "ef1e4933-3550-435f-baac-af134c6656fc",
        "faceRectangle": {
            "top": 238,
            "left": 495,
            "width": 82,
            "height": 82
        }
    },
    {
        "faceId": "f1bf034b-21e7-4d24-8ea4-7bd038b45b31",
        "faceRectangle": {
            "top": 162,
            "left": 211,
            "width": 81,
            "height": 81
        }
    }
]

「Data/identification1.jpg」は4人の人物が移っているので、4つのFaceが検出されています。
leftの値を見ると、1番目が「bill」で2番目が「clare」です。

curl -v -X POST \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key:<Subscription Key>" \
  -d '{"personGroupId":"mycoworker", "faceIds":["54850407-215c-46fd-9e26-b283c4baeaf5", "a9925edb-8d68-42c1-9928-9551f0c5d4fc", "ef1e4933-3550-435f-baac-af134c6656fc", "f1bf034b-21e7-4d24-8ea4-7bd038b45b31"]}' \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/identify
...
[
    {
        "faceId": "54850407-215c-46fd-9e26-b283c4baeaf5",
        "candidates": [
            {
                "personId": "5723e747-932d-4472-925f-fbf9c8cc767e",
                "confidence": 0.80474
            }
        ]
    },
    {
        "faceId": "a9925edb-8d68-42c1-9928-9551f0c5d4fc",
        "candidates": [
            {
                "personId": "b3fecf88-cac2-489b-9c6d-3c1b1d070f93",
                "confidence": 0.8912
            }
        ]
    },
    {
        "faceId": "ef1e4933-3550-435f-baac-af134c6656fc",
        "candidates": []
    },
    {
        "faceId": "f1bf034b-21e7-4d24-8ea4-7bd038b45b31",
        "candidates": []
    }
]

「bill」は80%、「clare」は89%の信頼度で識別できています。
サンプル画像とはいえ、画像3枚で良く識別できています。

最後に検出された人物の情報を取得して確認してみます。

curl -v -X GET \
  -H "Ocp-Apim-Subscription-Key:<Subscription Key>" \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/persongroups/mycoworker/persons/5723e747-932d-4472-925f-fbf9c8cc767e
...
{
    "personId": "5723e747-932d-4472-925f-fbf9c8cc767e",
    "persistedFaceIds": [
        "515a6182-c69d-459d-9400-5c40254237e5",
        "5619605c-701b-4402-a3fb-0462865bb548",
        "dab3c98a-9f6a-4499-8c5b-ed79a57b36af"
    ],
    "name": "bill",
    "userData": null
}
curl -v -X GET \
  -H "Ocp-Apim-Subscription-Key:<Subscription Key>" \
  https://japaneast.api.cognitive.microsoft.com/face/v1.0/persongroups/mycoworker/persons/b3fecf88-cac2-489b-9c6d-3c1b1d070f93
...
{
    "personId": "b3fecf88-cac2-489b-9c6d-3c1b1d070f93",
    "persistedFaceIds": [
        "11f26757-d971-4e32-b5ff-f9b84e8a422e",
        "ccade857-b221-46c9-b9b4-9b5a65d9f2ca",
        "f24f01de-c5b1-4f5c-9556-d9ceedf57fc5"
    ],
    "name": "clare",
    "userData": null
}

TIPS

APIから401が返される

はじめ401が返されたので確認したらURLに指定するリージョンが間違っていました。
以下のブログ記事が参考になりました。

HTTP 401 Access Denied (invalid subscription key) のエラーが発生した場合の切り分け方法 – Japan Cognitive Services Support Blog

, , ,