目次

学習内容

このチュートリアルでやることは、以下のとおりです。

  • AKB48のメンバーの画像を、顔認識のAPIに送信
  • 顔認識のAPIがAKBメンバーの画像を学習
  • 画像を送信すると、一番似ているAKBメンバーを抽出して教えてくれる

といったものになっています。 CSVからAKBの画像データを取得して、データをMicrosoft Cognitive Face APIに送信します。 送信すると、Microsoft Face APIが顔と名前を一致して学習してくれるので、次に任意の女性の画像を送信すると、それに似たAKBのメンバーを教えてくれるといったものになります。

受講における必須条件

以下の理解があることが望ましいです。

  1. Windows / MacなどのPCが利用できる方
  2. Google Chromeをインストールできる方
  3. Pythonの環境構築が分かる方
  4. Pythonの基礎的な文法がわかる方
  5. Web APIの基礎的な文法が分かる方

事前に、以下のチュートリアルを完了しておくことをおすすめします。

Progate | Pythonコース
プログラミングの基礎を、環境構築なしで学べる、日本最大級のプログラミング学習サイト。まず、基礎を学ぶならここでやってみましょう。
Pythonで環境構築をしてみよう
Google Drive上で簡単に環境構築ができる、Google Colaboratoryを利用して、環境構築を行います。10分ほどで簡単に環境構築することができるので、初学者の方におすすめです。
Web APIを利用して、画像の自動収集をしてみよう
Pythonを利用して、画像の自動収集をAPI経由で行います。AKBのメンバー全員の画像を自動収集してみましょう。

このチュートリアルの流れ

以下の手順で学習を進めていきます。

  • Microsoft Cognitive Face APIとは?
  • PythonでAKBの画像データのCSVをインポート
  • それぞれの顔認識の画像に対して、一人ひとり学習を進めるコードを書く
  • 画像URLを指定すると、それに似た画像を返してくれるようなコードを書く

Microsoft Cognitive Face APIとは?

今回使う、Microsoft Cognitive Face APIについて解説します。公式はこちらのページをご覧ください。公式サイトはこちらです。

Face APIを利用するためには、Microsoftのアカウントを作成する必要があります。アカウントを作成する方法はこちらの記事が詳しいので、ぜひ参考にしてみてください。

さて、アカウントが作成されてから学習するまでの流れはこちらのブログにまとめていますので、ぜひ参照してみてください。

さて、晴れて登録できたら、今度はFace APIを利用するためのサブスクリプションキーを発行します。 発行するとここの上のところからサブスクリプションキーを取得することができます。ここのキーをメモしておきます。 こちらの

  • Endpoint
  • サブスクリプションID

をメモしておいてください。

Face APIの仕組み

Face APIの仕組み

  • Person Group:学習させる人の集合(今回だったらAKBメンバー全体)
  • Person:人一人(鳳かなめ、あおいそら等)
  • Person Face: Personに紐づく画像(複数)

流れとしては

  1. Person Groupの作成
  2. Person Groupに、Personを追加
  3. Personに、Person Faceを追加
  4. Person Groupの学習

となります。

Person Groupの作成

さて、最初にPerson Groupを作成します。APIリファレンスを読んでみましょう。

以下のように書いてあります。

指定したpersonGroupId、name、およびuser-provided userDataを持つ新しい個人グループを作成します。 userGroupは、顔画像および顔認識機能を含む、アップロードされた人物データのコンテナです。 作成後、PersonGroup Person – Createを使用してPersonをグループに追加し、PersonGroup – Trainを呼び出してこのグループをFace-Identifyの準備が整うようにします。 personGroup Person – DeleteまたはPersonGroup – Deleteが呼び出されるまで、personのface、image、userDataはサーバーに保存されます。

リクエストURL

リクエストURLは以下のとおりです。

https://[location].api.cognitive.microsoft.com/face/v1.0/persongroups/{personGroupId}

HTTPメソッド

HTTPメソッドはPUT(更新)になります。

リクエストパラメーター

必須のリクエストパラメーターは以下の通りです。

  • personGroupId: ユーザー指定のpersonGroupIdを文字列として返します。有効な文字には、数字、英字(小文字)、 ‘ – ‘、 ‘_’が含まれます。 personGroupIdの最大長は64です。

リクエストヘッダー

必須のリクエストヘッダーは以下の通りです。

  • Ocp-Apim-Subscription-Key:このAPIへのアクセスを提供するサブスクリプションキー。あなたのCognitive サービスアカウントにあります。

リクエストボディ

必須のリクエストボディは以下の通りです。

  • name: Person group の表示名.最大文字数は128字です.

コーディング

のちほどコードの解説はしますが、以下のように実装することになります。こちらはのちほど変わるコードなので、「こういう構造になるんだ~」くらいで理解しておいてください。

def makeGroup():
  end_point = BASE_URL + "persongroups/" + GROUP_NAME
  payload = { # ここがリクエストボディになります。
      "name": GROUP_NAME
  }
  headers = { # ここがヘッダーになります
      "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY 
  }
  r = requests.put(
      end_point, # URL 
      headers = headers, # ヘッダー
      json = payload # リクエスト墓碑
  )
  print (r.text)

Person Groupに、Personを追加

次に、Personを追加します。リファレンスはこちらになります。

さきほどと同じようにリファレンスを読んでいきましょう。

リクエストURL

リクエストURLは以下のとおりです。

https://[location].api.cognitive.microsoft.com/face/v1.0/persongroups/{personGroupId}/persons

リクエストパラメーター

必須のリクエストパラメーターは以下の通りです。

  • personGroupId: 先ほど指定したperronGroupIdを指定します

リクエストヘッダー

必須のリクエストヘッダーは以下の通りです。

  • Ocp-Apim-Subscription-Key:このAPIへのアクセスを提供するサブスクリプションキー。あなたのCognitive サービスアカウントにあります。

リクエストボディ

必須のリクエストボディは以下の通りです。

  • name:人間の名前です。今後AKBの各女優に名前を付けていく場合はここになります。

コーディング

のちほどコードの解説はしますが、以下のように実装することになります。こちらはのちほど変わるコードなので、「こういう構造になるんだ~」くらいで理解しておいてください。

def makePerson(personName):
 """
 makeGroupで作成したgroupにpersonを追加することができます。
 """
 end_point = BASE_URL + "persongroups/" + GROUP_NAME + "/persons"
 headers = {
     "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
 }
 payload = {
     "name": name
 }
 r = requests.post(
     end_point,
     headers = headers,
     json = payload
 )
 try:
     personId = r.json()["personId"]
 except Exception as e:
     personId = None
     print(r.json()["error"])
 return personId

Person Face: Personに紐づく画像を追加

次に Person Groupの中のPersonの中に、取得した顔の画像を紐づけます。 また同じようにリファレンスを見ていきましょう。こちらがリファレンスになります。

HTTPメソッド

HTTPメソッドは以下のようになります。

  • POST

リクエストURL

リクエストURLは以下の通りです。

https://[location].api.cognitive.microsoft.com/face/v1.0/persongroups/{personGroupId}/persons/{personId}/persistedFaces[?userData][&targetFace]

リクエストパラメーター

必須のリクエストパラメーターは、以下の通りです。

  • personGroupId:さきほど説明したpersonGroupIdを指定します。
  • personId:personGroupIdの中のpersonの値を指定します。

リクエストヘッダー

ヘッダーも先ほどと同じで、以下の値になります。

  • Ocp-Apim-Subscription-Key:このAPIへのアクセスを提供するサブスクリプションキー。あなたのCognitive サービスアカウントにあります。

リクエストボディ

リクエストボディは以下のようになります。

  • url:画像のURLです。1KBから6MBでが許容範囲です。複数の顔がある画像は使えません

コーディング

これらの値を利用してコーディングを行うと、以下のようになります。

def addFaceToPerson(personId, imageUrl):
  end_point = BASE_URL + "persongroups/" + GROUP_NAME + "/persons/" + personId  + "/persistedFaces"
  print(end_point)
  headers = {
      "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
  }
  payload = {
      "url": imageUrl
  }
  r = requests.post(
      end_point,
      headers = headers,
      json = payload
  )
  print(r.text)

実装編

さて、APIリファレンスを軽くさらったところで、さっそく試していきましょう。

ライブラリのインポート

まずは必要なライブラリをインポートします。

  • requests: HTTPの通信を行うためのライブラリ
  • json:データをjson形式で使うためのライブラリ
  • pandas: CSVデータを使うためのライブラリ
# ライブラリのインポート
import requests
import json
import pandas as pd

APIのエンドポイントのルートURLと、サブスクリプションキーの設定

APIのエンドポイントのルートURLと、サブスクリプションキーの設定を行います。

# ライブラリのインポート
import requests
import json
import pandas as pd

BASE_URL = "https://japaneast.api.cognitive.microsoft.com/face/v1.0/" # Base URLの指定
SUBSCRIPTION_KEY  = "jacb0d5c5g6b47aab43cad251d157b0e" # API KEYの指定

グループ名の追加

さて、Person Groupの名前を付けます。ここでは、GROUP_NAMEという変数に名前を定義しておきましょう。

# ライブラリのインポート
import requests
import json
import pandas as pd

BASE_URL = "https://japaneast.api.cognitive.microsoft.com/face/v1.0/" # Base URLの指定
SUBSCRIPTION_KEY  = "jacb0d5c5g6b47aab43cad251d157b0e" # API KEYの指定
GROUP_NAME = "akb48" # グループ名を設定

Person Groupを作る関数の作成

≫Person Groupの作成 で確認した、API リファレンスをもとに、関数を作成します。

# グループの作成
def make_group():
  end_point = BASE_URL + "persongroups/" + GROUP_NAME # エンドポイント
  payload = {
      "name": GROUP_NAME # グループ名の指定
  }
  headers = {
      "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
  }
  r = requests.put(
      end_point,
      headers = headers,
      json = payload
  )
  return r.json()

Person Groupの作成

作成したPerson Groupの関数を実行します。エラーなく実行できると、Person Groupが作成できていると思います。

# グループの作成
make_group()

Person GroupにPersonを追加する関数の実装

今度は、作成したPerson GroupにPersonを追加する関数を実装します。

# Personの追加
def make_person(name):
  end_point = BASE_URL + "persongroups/" + GROUP_NAME + "/persons"
  headers = {
      "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
  }
  payload = {
      "name": name
  }
  r = requests.post(
      end_point,
      headers = headers,
      json = payload
  )
  return r.json()

make_person関数の実行

make_person関数を実行します。

# Personの追加
make_person("浦島太郎")

そうすると、以下のような結果が取得可能です。

{'personId': 'b8f2516a-63b1-49ab-bf9c-fc64f320a796'}

このように、個別のPersonには個別のpersonIdが付与されます。個別のpersonIdを指定して、今度はこのpersonIdにFaceを追加していくことになります。 また、今後このpersonIdを関数の引数に入れて、顔を追加する必要がでてきますので、JSON形式のデータを取得する方法を確認します。以下のようにコードを実行すると

make_person("浦島太郎")["personId"]

以下のような結果が返ってきます。

{'personId': 'b8f2516a-63b1-49ab-bf9c-fc64f320a796'}

このように取得することができるのを覚えておいてください。

PersonにFaceを追加する関数を追加

今度は、PersonにFaceを追加する関数を追加します。引数には、以下の値を入れます。

  • person_id : さきほどmake_personで実行したときに、付与されたpersonId
  • image_url: Personに紐づけたい画像URL

では、実装していきましょう。

# Faceに画像を追加するURL

def add_face_to_person(person_id, image_url):
  end_point = BASE_URL + "persongroups/" + GROUP_NAME + "/persons/" + person_id  + "/persistedFaces"
  headers = {
      "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
  }
  payload = {
      "url": image_url
  }
  r = requests.post(
      end_point,
      headers = headers,
      json = payload
  )
  return r.json()

Faceの追加

それでは、実際にFaceを追加します。personIdでは、さきほど取得した浦島太郎の値をセット、image_urlには僕が適当にネットから拾ってきた、浦島太郎の画像をセットし、add_face_to_person関数を実行します。 img01_mm.png

# 'dca7eaee-f45c-4f27-9751-9ac26bcb6828' をperonId、適当な浦島太郎の画像URL(https://www.au.com/content/dam/au-com/pr/cm/3taro/sp/images/img01_mm.png)をセットする
person_id = "dca7eaee-f45c-4f27-9751-9ac26bcb6828"
image_url = "https://www.au.com/content/dam/au-com/pr/cm/3taro/sp/images/img01_mm.png"
add_face_to_person(person_id, image_url)

そうすると、以下のような結果が取得できます。

{'persistedFaceId': '6cc44175-36b7-45e6-9356-cc35b28f8cad'}

この結果が出ていれば、PersonにFaceを追加することに成功しました。

Person GroupにFaceを学習させる関数を実装

それでは、Person GroupにFaceを学習させていきましょう。現状、PersonにFaceが登録されているだけなので、このAPIのエンドポイントを利用すると、顔の学習を行うことができます。

# 顔を学習させる
def train_group(group_id):
  end_point = BASE_URL + "persongroups/" + GROUP_NAME + "/train"
  headers = {
      "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
  }
  r = requests.post(
      end_point,
      headers = headers
  )
  return r.text

Person GroupにFaceを学習させる関数を実行

以下のように実行してみてください。

train_group(GROUP_NAME)

特になにもレスポンスはありませんが、エラーが起こらなければ、顔の学習が完了します。

URLからFaceを検出する関数を実装する

URLからFaceを検出する関数を実装します。 引数には、以下の値を入れます。

  • image_url: 画像のURL。
# URLから画像を検出する

def detect_face(image_url):
  end_point = BASE_URL + "detect"
  headers = {
      "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
  }
  payload = {
      "url": image_url
  }
  r = requests.post(
      end_point,
      json = payload,
      headers = headers
  )
  return r.json()

URLからFaceを検出する関数を実行する

detect_face関数に、さきほど学習させた浦島太郎の画像を入れて、顔認識を行います。

image_url = "https://www.au.com/content/dam/au-com/pr/cm/3taro/sp/images/img01_mm.png"
detect_face(image_url)

実行すると、以下のような結果が返ってくるはずです。

[{'faceId': '844452b4-0913-49c6-b77e-3c5dc7cd8373',
 'faceRectangle': {'height': 93, 'left': 235, 'top': 148, 'width': 93}}]

このようなリスト形式で、顔だと判定された画像のfaceIdと、詳細なデータが返ってきます。このあとこのfaceIdを利用して、学習済みのモデルの中から、似ている顔画像を取得することができるようになります。

Faceから登録したPersonを特定する関数を実装する

では、次に学習した結果のPersonから、似ている人のIDを取得してみましょう。

# detectFaceから抽出したfaceIdから、学習済みモデルのfaceIdを取得
def identify(face_id):
  end_point = BASE_URL + "identify"
  headers = {
      "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
  }
  faceIds = [face_id]
  payload = {
      "faceIds" :faceIds,
      "personGroupId" :GROUP_NAME,
  }
  r = requests.post(
      end_point,
      json = payload,
      headers = headers
  )
  return r.json()

この関数を、さきほど入れた浦島太郎の画像のfaceIdから

# detectFaceから抽出したfaceIdから、学習済みモデルのfaceIdを取得
identify("08925fdb-311a-4730-85e5-a50fcad60a63")

結果

[{'candidates': [{'confidence': 1.0,
   'personId': 'dca7eaee-f45c-4f27-9751-9ac26bcb6828'}],
 'faceId': '08925fdb-311a-4730-85e5-a50fcad60a63'}]

この、candidatesの中のデータですが、

  • confidence: 一致度で、0 ~ 1.0の割合で算出されます。今回1なのは、元のオリジナル画像と学習した画像が一緒なため、高くなっています。
  • personId:一致しているPersonのIDとなります。

今後はこのpersonIdから、データを取得することになります。

personIdから名前を取得する関数を実装する

では、identify関数を実行し、似ているPersonのIDを取得できたので、今度はPerson IDから、そのPersonの登録情報を取得する関数を実装します。 引数にはperson_idを指定します。

# Personを取得
def get_person(person_id):
  end_point = BASE_URL + "persongroups/" + GROUP_NAME + "/persons/" + person_id
  headers = {
      "Ocp-Apim-Subscription-Key" :SUBSCRIPTION_KEY
  }
  r = requests.get(
      end_point,
      headers = headers
  )
  return r.json()

personIdから名前を取得する関数を実行する

さっそく、作成したget_person関数に、引数にpersonIdを入れて実行してみましょう。

get_person("dca7eaee-f45c-4f27-9751-9ac26bcb6828")

実行結果は以下のようになります。

{'name': '浦島太郎',
'persistedFaceIds': ['15b62de9-d257-4da9-95eb-9d88feb61283',
'6cc44175-36b7-45e6-9356-cc35b28f8cad',
'8ea3dce7-8415-4dbb-97bf-a6f5279848a3',
'9463bf90-ff69-4979-803a-668cc02a21e6',
'd77d74b7-74f0-4588-8db4-056127452f00'],
'personId': 'dca7eaee-f45c-4f27-9751-9ac26bcb6828',
'userData': None}

中に入っているデータを確認します。

  • name: Personに紐づいている名前。最初にmakePerson関数で登録したユーザーと一致します。
  • pesistedFaceIds:顔を登録したデータ
  • personId:そのPersonのID

CSVから取得したデータで、大量に顔を学習させる

それでは、今度はAKB48の120名分の画像データをFace APIで学習させ、未知の画像を送信したときに似ているAKBメンバーが返ってくるようにしましょう。 AKBメンバーのCSVのデータ取得は、以前のチュートリアルで取得したCSVデータを利用します。こちらのチュートリアルから始めた方は、以下のGoogle Drive上のCSVデータをダウンロードしてください。 akb.csv

CSVをGoogle Colaboratoryにアップロードする

Google ColaboratoryでCSVを利用するための方法は、こちらのQiitaがわかりやすいと思います。

では、まずGoogle Colaboratory上でCSVを利用するために、以下のコマンドを実行します。

from google.colab import files
uploaded = files.upload()

実行すると、以下のような画面になると思います。 このように、≫ファイル選択 をクリックし、ダウンロードしたCSVファイルを選択すると、CSVをColaboratory上にアップロードすることができます。

ファイルがアップロードされたことを確認する

では、ファイルがアップロードされたことを確認します。現在のディレクトリにファイルが存在することを確認するために、lsコマンドを実行します。

!ls

実行すると、akb.csvが存在するはずです。

akb.csv  sample_data

ここにakb.csvが存在すれば、大丈夫です。lsコマンドについては、下記リンクがわかりやすいので確認してみてみてください。

PandasでCSVを読み込む

それでは、さっそくPandasでCSVを読み込んでみましょう。以下の記事を参考にしつつ

実行していきましょう。

import pandas as pd
import io
df = pd.read_csv(io.StringIO(uploaded['akb.csv'].decode('utf-8')), index_col=0)
df.head()

実行結果は、以下のようになります。 きちんとCSVが読み込まれていることが分かります。