こんにちは、Michaelです。
今回は、Face APIの1機能であるFind Similar機能を使って2つの画像に共通する人物を探してみます。
Find Similar機能について
Find Similar機能は、その名の通り2つの画像に共通する似た顔を検出してスコアリングすることができる機能で、特定の人物を写真から見つけ出したいときに利用できます。
Face APIのリファレンスによると、Find Similar機能をPythonで利用する場合、以下のようなコードを使用します。リクエスト先のURLやパラメータが異なりますが、基本的にはPOSTリクエストのため、リファレンスに沿ってheader、body、parameterを記述してリクエストをすれば利用できます。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32  | 
						import httplib, urllib, base64 import json headers = {     # Request headers     'Content-Type': 'application/json',     'Ocp-Apim-Subscription-Key': '*********** {APIキー}', } body = {     # Request body     "faceId": "c5c24a82-6845-4031-9d5d-************",     "faceIds": [         "ca59c95b-d15a-4ae3-bf99-************",         "d96b1b94-696b-484a-bf6e-************",         "e3982e3e-d5b9-4779-91a9-************"     ],       "maxNumOfCandidatesReturned": 20,     "mode": "matchPerson" } params = urllib.urlencode({ }) try:     conn = httplib.HTTPSConnection('westus.api.cognitive.microsoft.com')     conn.request("POST", "/face/v1.0/findsimilars?%s" % params, json.dumps(body), headers)     response = conn.getresponse()     data = json.loads(response.read())     print(data)     conn.close() except Exception as e:     print("[Errno {0}] {1}".format(e.errno, e.strerror))  | 
					
Request bodyに”faceId”と”faceIds”というパラメータがあるようにFind Similarでは、特定したい1つの顔に対して複数の顔を一度に比較し、類似の顔を検出することができます。”faceId”と”faceIds”にはFace Detect(顔検出)機能で取得する顔のIDを設定することになるため、Face Detectとセットで使用することになります。
| 
					 1 2 3 4 5 6 7 8 9 10 11  | 
						body = {     # Request body     "faceId": "c5c24a82-6845-4031-9d5d-************",     "faceIds": [         "ca59c95b-d15a-4ae3-bf99-************",         "d96b1b94-696b-484a-bf6e-************",         "e3982e3e-d5b9-4779-91a9-************"     ],       "maxNumOfCandidatesReturned": 20,     "mode": "matchPerson" }  | 
					
また、”faceIds”のパラメータは、Face APIのFace Listという機能で置き換えることができ、下記のようにも記述をすることができます。
Face Detectで出力されるfaceIdは、24時間で無効になるという制約がありますが、 Face Listに保存されたfaceIdは、永続的に保持されるため、長期にわたり使用する場合にはこの機能を活用することで、トランザクションを減らすことができます。
| 
					 1 2 3 4 5 6 7  | 
						body = {     # Request body     "faceId":"c5c24a82-6845-4031-9d5d-978df9175426",     "faceListId":"sample_list",       "maxNumOfCandidatesReturned":10,     "mode": "matchPerson" }  | 
					
レスポンスには、特定したい対象と似ている顔のfaceIdとその信頼性(0~1の数値)が配列として返されます。
| 
					 1 2 3 4 5 6 7  | 
						[     {         "faceId" : "015839fb-fbd9-4f79-ace9-7675fc2f1dd9",             "confidence" : 0.82     },     ... ]  | 
					
もちろんFace APIのPython SDKでも利用でき、APIキーとRequest bodyの情報があれば、上記と同じ情報が得られます。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16  | 
						#!/usr/bin/env python #coding:utf-8 import cognitive_face as CF KEY = '*********** {APIキー}' CF.Key.set(KEY) faceId = "c5c24a82-6845-4031-9d5d-************", faceIds = [     "ca59c95b-d15a-4ae3-bf99-************",     "d96b1b94-696b-484a-bf6e-************",     "e3982e3e-d5b9-4779-91a9-************" ]  data = CF.face.find_similars(faceId, face_ids=faceIds, max_candidates_return=20, mode='matchPerson')  print(data)  | 
					
Find Similar機能を使った人物特定
ここからは実際にFind Similar機能を使って写真から特定人物の検出を試してみます。
今回は4人の集合写真と特定する対象の1人の写真を使って、集合写真から特定人物を検出してみます。
・集合写真

・特定対象の写真

特定人物の検出には下記のコードを使用しました。Find Similar機能は単体では使えないため、Face Detect機能を併用して検出を行います。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49  | 
						#!/usr/bin/env python #coding:utf-8 import cognitive_face as CF import json import sys def main():     # APIキーのセット     api_key = '************* {APIキー}'     CF.Key.set(api_key)     img_urls ={         'target': 'https://*********** {集合写真}',         'comparison': 'https:// *********** {特定対象の写真}'     }     face_Ids = {         'target': {},         'comparison': {}     }     #### 顔検出(Face Detect) ####     for key, img_url in img_urls.items():         # 顔検出のリクエスト         detect = CF.face.detect(img_url, face_id=True, landmarks=False)         # 検出した顔の記録         if len(detect) != 0:             for i, face in enumerate(detect):                 face_Ids[key].update({face['faceId']: face})         else:             print(key + '_image: No face detected.' )             sys.exit()     found = {comparisonId: {} for comparisonId in face_Ids['comparison'].keys()}     #### 顔比較(Face Similar) ####     for comparisonId, comparison in face_Ids['comparison'].items():         targetIds = face_Ids['target'].keys()         similar = CF.face.find_similars(comparison['faceId'], face_ids=targetIds, max_candidates_return=20, mode='matchPerson')         for face in similar:             found[comparisonId].update({face['faceId']: face['confidence']})      print(json.dumps(found, indent = 4)) if __name__ == '__main__':     main()  | 
					
上記コードを実行すると以下のような結果が出力されました。
Find Similar機能は類似性の高いfaceIdを出力しますが、結果には集合写真に含まれるfaceIdが出力されており、人物を特定できていることが分かります。

上記の情報だけでは集合写真のどの人物を似ていると判断しているかわからないため、Open CVを使い出力情報を画像上で可視化してみました。Face Detectで出力された”faceRectangle”の情報を基に、出力されたfaceIdの人物の顔に四角の枠を追加すると、確かに同一人物に枠が追加されており、人物特定ができていることがわかりました。

また、特定する人物を2人に増やして試してみました。
上記のコードでは、特定する人物ごとにFind Similar機能を使用するようになっているため、複数人でもそれぞれの人物を判定することができました。

これを応用すると、特定の人物以外の人物にモザイクをかけるといったこともできます。
ニュースなどでよくある、見知らぬ通行人にモザイクをかけるということも概ね自動でできてしまうのではないでしょうか。

今回は簡単ながらFind Similar機能を使って顔の比較を行いました。
Find Similar機能がどの程度まで類似の顔を検出できるかは、またの機会に検証してみます。
次回は、Face APIのFind Similarと似た機能であるVerify (顔認証)機能を検証していきます。
お楽しみに!
