Amazon Rekognitionを使って集合写真からメンバーの判別をする

Amazon RekognitionはAWS上の画像認識サービスです。

今回は顔の比較機能を使ってみたいと思います。顔の比較、と言われると分かりづらいかもしれませんが、ソースイメージで与えられた顔をターゲットイメージから探すという機能です。

GUIで顔比較をする

AWSのアカウントを持っていればマネジメントコンソールからGUIを使って試すことができます。

ソースイメージ、ターゲットイメージともに2つずつサンプルイメージが用意されており、それぞれどちらのイメージを使用するかを選択するだけで分析が始まります。

ターゲットイメージに複数の顔がある場合は、ソースイメージ内の顔とターゲットイメージ内の最大100までの顔を比較してそれぞれに対して類似度を出してくれます。

もし、ソースイメージに複数の顔があった場合はその中で一番大きく写っている顔を使って比較を行います。

サンプルイメージではなく、自前で画像を用意して比較したい場合は、参照顔、比較顔と書いてある欄に写真をドラッグアンドドロップするか下の方にあるURL入力欄にURLを入力してアップロードすればよいです。(写真は5MB未満のJPGかPNG形式にする必要があります)

AWS CLIで顔比較をする

以下のコマンドで顔の比較機能を使うことができます。

画像をS3から読み込む場合

aws rekognition compare-faces --source-image "S3Objec
t={Bucket=SourceBucketName,Name=SourceImageName}" --target-image "S3Object
={Bucket=TargetBucketName,Name=TargetImageName}"

画像をローカルから読み込む場合

aws rekognition compare-faces --source-image-bytes fi
leb://SourceImageName --target-image-bytes fileb://TargetImageName

レスポンスは以下のようになります。(aws cliの設定時に出力形式としてjsonを選んだ場合)

{
    "SourceImageFace": {
        "BoundingBox": {
            "Width": 0.46666666865348816,
            "Height": 0.699999988079071,
            "Left": 0.5024999976158142,
            "Top": 0.10249999910593033
        },
        "Confidence": 99.7334976196289
    },
    "FaceMatches": [
        {
            "Similarity": 98.0,
            "Face": {
                "BoundingBox": {
                    "Width": 0.24500000476837158,
                    "Height": 0.3675000071525574,
                    "Left": 0.43166667222976685,
                    "Top": 0.16875000298023224
                },
                "Confidence": 99.94893646240234,
                "Landmarks": [
                    {
                        "Type": "eyeLeft",
                        "X": 0.5521777272224426,
                        "Y": 0.32683613896369934
                    },
                    {
                        "Type": "eyeRight",
                        "X": 0.6080317497253418,
                        "Y": 0.35208362340927124
                    },
                    {
                        "Type": "nose",
                        "X": 0.5935028791427612,
                        "Y": 0.42228659987449646
                    },
                    {
                        "Type": "mouthLeft",
                        "X": 0.5184009671211243,
                        "Y": 0.43238815665245056
                    },
                    {
                        "Type": "mouthRight",
                        "X": 0.5623704791069031,
                        "Y": 0.45827361941337585
                    }
                ],
                "Pose": {
                    "Roll": 12.113231658935547,
                    "Yaw": 53.51523971557617,
                    "Pitch": -10.478560447692871
                },
                "Quality": {
                    "Brightness": 48.997554779052734,
                    "Sharpness": 99.98487854003906
                }
            }
        }
    ],
    "UnmatchedFaces": [
        {
            "BoundingBox": {
                "Width": 0.22750000655651093,
                "Height": 0.3412500023841858,
                "Left": 0.2524999976158142,
                "Top": 0.12250000238418579
            },
            "Confidence": 99.99396514892578,
            "Landmarks": [
                {
                    "Type": "eyeLeft",
                    "X": 0.3527677059173584,
                    "Y": 0.2771225571632385
                },
                {
                    "Type": "eyeRight",
                    "X": 0.3976413309574127,
                    "Y": 0.28078728914260864
                },
                {
                    "Type": "nose",
                    "X": 0.38970983028411865,
                    "Y": 0.35649099946022034
                },
                {
                    "Type": "mouthLeft",
                    "X": 0.33361324667930603,
                    "Y": 0.38035106658935547
                },
                {
                    "Type": "mouthRight",
                    "X": 0.36442211270332336,
                    "Y": 0.3911028206348419
                }
            ],
            "Pose": {
                "Roll": -2.283367156982422,
                "Yaw": 59.26860046386719,
                "Pitch": -16.994068145751953
            },
            "Quality": {
                "Brightness": 49.882808685302734,
                "Sharpness": 99.97486114501953
            }
        },
        ...
    ]
}

SDKで顔比較をする

Amazon RekognitionはSDKを使って様々な言語を用いてAPIを扱うことができますが、今回はPythonを使いたいと思います。

画像をS3から読み込む場合

#!/usr/bin/python3

from boto3 import client

client = client("rekognition", region_name="ap-northeast-1", aws_access_key_id="****", aws_secret_access_key="****")
response = client.compare_faces(
    SourceImage={
        'S3Object': {
            'Bucket': SourceBucketName,
            'Name': SourceImageName
            }
    },
    TargetImage={
        'S3Object': {
            'Bucket': TargetBucketName,
            'Name': TargetImageName
        }
    }

)
print(response)

画像をローカルから読み込む場合

#!/usr/bin/python3

from boto3 import client

with open(SourceImageName,'rb') as f1:
    with open(TargetImageName,'rb') as f2:

        client = client("rekognition", region_name="ap-northeast-1", aws_access_key_id="****", aws_secret_access_key="****")
        source=f1.read()
        target=f2.read()
        response = client.compare_faces(
            SourceImage={
                'Bytes': source
            },
            TargetImage={
                'Bytes': target
            }

        )
print(response)

レスポンスはAWS CLIを使ったものとほぼ同じです。

自前の写真でやってみた

まあGUIは使いやすいけど、実際にサービスで使うにはやっぱりAWS CLIかSDKですよね……というわけで、ソースイメージとの類似度が一番高い顔をターゲットイメージから取り出して取得するスクリプトを書いてみました。今回はローカルから写真を取ってくるという場合のスクリプトをPythonで書いてみました。

#!/usr/bin/python3

from boto3 import client
from PIL import Image

with open(SourceImageName,'rb') as f1:
    with open(TargetImageName,'rb') as f2:

        client = client("rekognition", region_name="ap-northeast-1", aws_access_key_id="****", aws_secret_access_key="****")
        source = f1.read()
        target = f2.read()
        response = client.compare_faces(
            SourceImage={
                'Bytes': source
            },
            TargetImage={
                'Bytes': target
            },
            SimilarityThreshold=0
        )

source_face_boundingbox = response['SourceImageFace']['BoundingBox']
source_image = Image.open(SourceImageName)
source_height = source_image.height
source_width = source_image.width
source_image.crop((source_width*source_face_boundingbox['Left'],source_height*source_face_boundingbox['Top'],source_width*(source_face_boundingbox['Left']+source_face_boundingbox['Width'
]),source_height*(source_face_boundingbox['Top']+source_face_boundingbox['Height']))).save(SourceFaceImageName)

target_face_boundingbox = response['FaceMatches'][0]['Face']['BoundingBox']
target_image = Image.open(TargetImageName)
target_height = target_image.height
target_width = target_image.width                                                                                                                                       
target_image.crop((target_width*target_face_boundingbox['Left'],target_height*target_face_boundingbox['Top'],target_width*(target_face_boundingbox['Left']+target_face_boundingbox['Width'
]),target_height*(target_face_boundingbox['Top']+target_face_boundingbox['Height']))).save(TargetFaceImageName)

このスクリプトをもとに実行してみた結果は以下になります。

顔認識の例1

ソースイメージはこちら

ターゲットイメージはこちら

ソースイメージを基準に、ターゲットイメージを顔比較した結果が以下になります。

  

ソースイメージから認識された顔を基準に、ターゲットイメージに写っている顔の中で基準に最も類似しているとされた顔が抜き出されました。

顔認識の例2

ソースイメージはこちら

ターゲットイメージはこちら

顔比較した結果は以下になります。

  

ターゲットイメージの中では一番奥にいて、髪型も違うのに同一人物の認識をすることができました。

Amazon Rekognitionの他の機能についてはほかの記事もありますので、以下の関連記事欄からもぜひご覧ください。