本人確認における Amazon Rekognition の使用のチュートリアルを Lambda でやってみた
Using Amazon Rekognition for Identity Verification - Amazon Rekognition
上記チュートリアルを Lambda でやってみました。
前提
- Lambda のランタイム: Python 3.13
- Lambda 実行ロールの権限: AdministratorAccess
- Lambda のタイムアウト: 10 秒
- Lambda の実行方法: コンソールからのテスト実行
- 使用する画像は S3 バケットに保存済み
- 画像比較用に異なる画像を 2 枚
- ただし映っている人物は 1 人
概要
- Rekognition のコレクション作成
- 検出した顔に関する情報を保存するコンテナ
- 画像から顔の検出
- 人物が一人であるかどうかをチェック
- 2 つの画像の人物を比較
- 画像の人物がコレクションに登録されているかをチェック
- コレクションに人物情報を登録
- コレクションの情報を DynamoDB に保存
- 今回は保存するだけで用途はなし
- 再度人物画像がコレクションに登録されているかをチェック
01. コレクションを作成する
-
collection-id-name
を任意の名称に置換- 今回は test
-
region-name
を使用リージョンコードに変換- 今回は ap-northeast-1
コード
import json
import boto3
collection_id = 'collection-id-name'
region = "region-name"
def lambda_handler(event, context):
create_collection(collection_id, region)
def create_collection(collection_id, region):
client = boto3.client('rekognition', region_name=region)
# Create a collection
print('Creating collection:' + collection_id)
response = client.create_collection(CollectionId=collection_id,
Tags={"SampleKey1":"SampleValue1"})
print('Collection ARN: ' + response['CollectionArn'])
print('Status code: ' + str(response['StatusCode']))
print('Done...')
実行後に以下のログが出力されます。
Creating collection:test
Collection ARN: aws:rekognition:ap-northeast-1:012345678901:collection/test
Status code: 200
Done...
02. DetectFaces オペレーションを呼び出す
-
photo-name
は S3 バケットに保存済みの画像ファイル名に置換 -
region-name
を使用リージョンコードに変換
チュートリアルではローカルファイルの画像を読み込んでいますが、Lambda で試したところ InvalidImageFormatException が発生しました。
そのため、S3 バケットから画像を読み取る処理に変更しています。
コード
import boto3
import json
photo = 'photo-name'
region = 'region-name'
def lambda_handler(event, context):
face_count=detect_faces(photo, region)
print("Faces detected: " + str(face_count))
if face_count == 1:
print("Image suitable for use in collection.")
else:
print("Please submit an image with only one face.")
def detect_faces(target_file, region):
client=boto3.client('rekognition', region_name=region)
response = client.detect_faces(
Image={
'S3Object': {
'Bucket': 'your-bucket-name',
'Name': target_file,
}
},
Attributes=['ALL'])
print('Detected faces for ' + photo)
for faceDetail in response['FaceDetails']:
print('The detected face is between ' + str(faceDetail['AgeRange']['Low'])
+ ' and ' + str(faceDetail['AgeRange']['High']) + ' years old')
print('Here are the other attributes:')
print(json.dumps(faceDetail, indent=4, sort_keys=True))
# Access predictions for individual face details and print them
print("Gender: " + str(faceDetail['Gender']))
print("Smile: " + str(faceDetail['Smile']))
print("Eyeglasses: " + str(faceDetail['Eyeglasses']))
print("Emotions: " + str(faceDetail['Emotions'][0]))
return len(response['FaceDetails'])
実行後に以下のログが出力されます。
※詳細なログも出力されますが割愛します。
Gender: {'Value': 'Male', 'Confidence': 99.70700073242188}
Smile: {'Value': True, 'Confidence': 64.96673583984375}
Eyeglasses: {'Value': True, 'Confidence': 99.91963958740234}
Emotions: {'Type': 'HAPPY', 'Confidence': 55.158203125}
Faces detected: 1
Image suitable for use in collection.
03. CompareFaces オペレーションを呼び出す
-
bucket-name
は画像を保存した S3 バケット名に置換 -
source-file-name
は S3 バケットに保存した画像ファイル名 -
target-file-name
は S3 バケットに保存したsource-file-name
とは異なる画像ファイル名 -
region-name
を使用リージョンコードに変換
コード
import boto3
bucket = 'bucket-name'
source_file = 'source-file-name'
target_file = 'target-file-name'
region = "region-name"
def lambda_handler(event, context):
face_matches = compare_faces(bucket, source_file, target_file, region)
print("Face matches: " + str(face_matches))
if str(face_matches) == "1":
print("Face match found.")
else:
print("No face match found.")
def compare_faces(bucket, sourceFile, targetFile, region):
client = boto3.client('rekognition', region_name=region)
response = client.compare_faces(SimilarityThreshold=99,
SourceImage={'S3Object':{'Bucket':bucket,'Name':sourceFile}},
TargetImage={'S3Object':{'Bucket':bucket,'Name':targetFile}})
for faceMatch in response['FaceMatches']:
position = faceMatch['Face']['BoundingBox']
similarity = str(faceMatch['Similarity'])
print('The face at ' +
str(position['Left']) + ' ' +
str(position['Top']) +
' matches with ' + similarity + '% confidence')
# imageTarget.close()
return len(response['FaceMatches'])
実行後に以下のログが出力されます。
The face at 0.381568044424057 0.02870430052280426 matches with 99.99736785888672% confidence
Face matches: 1
Face match found.
04. SearchFacesByImage オペレーションを呼び出す
-
collectionId
は 01 で作成済みのコレクション名 -
region-name
を使用リージョンコードに変換 -
photo-name
は S3 バケットに保存済みのいずれかの画像ファイル名に置換 -
bucket-name
は画像を保存した S3 バケット名に置換
コード
import boto3
collectionId = 'collection-id-name'
region = "region-name"
photo = 'photo-name'
threshold = 70
maxFaces = 1
bucket = 'bucket-name'
def lambda_handler(event, context):
client = boto3.client('rekognition', region_name=region)
response = client.search_faces_by_image(CollectionId=collectionId,
Image={'S3Object':{'Bucket':bucket,'Name':photo }},
FaceMatchThreshold=threshold, MaxFaces=maxFaces)
print(response)
faceMatches = response['FaceMatches']
print(faceMatches)
for match in faceMatches:
print('FaceId:' + match['Face']['FaceId'])
print('ImageId:' + match['Face']['ImageId'])
print('Similarity: ' + "{:.2f}".format(match['Similarity']) + "%")
print('Confidence: ' + str(match['Face']['Confidence']))
実行後に以下のログが出力されます。
この時点ではコレクションに画像が登録されていないのでレスポンスは空です。
[]
05. IndexFaces オペレーションを呼び出す
-
image
は S3 バケットに保存済みのいずれかの画像ファイル名に置換 -
collectionId
は 01 で作成済みのコレクション名 -
photo-name
は任意の名称に置換 (ファイル名など) -
region-name
を使用リージョンコードに変換 -
bucket-name
は画像を保存した S3 バケット名に置換
コード
import boto3
image = 'image-file-name'
collection_id = 'collection-id-name'
photo_name = 'desired-image-name'
region = "region-name"
bucket = 'bucket-name'
def lambda_handler(event, context):
indexed_faces_count = add_faces_to_collection(image, photo_name, collection_id, region)
print("Faces indexed count: " + str(indexed_faces_count))
def add_faces_to_collection(target_file, photo, collection_id, region):
client = boto3.client('rekognition', region_name=region)
response = client.index_faces(CollectionId=collection_id,
Image={'S3Object':{'Bucket':bucket,'Name':photo}},
ExternalImageId=photo,
MaxFaces=1,
QualityFilter="AUTO",
DetectionAttributes=['ALL'])
print(response)
print('Results for ' + photo)
print('Faces indexed:')
for faceRecord in response['FaceRecords']:
print(' Face ID: ' + faceRecord['Face']['FaceId'])
print(' Location: {}'.format(faceRecord['Face']['BoundingBox']))
print(' Image ID: {}'.format(faceRecord['Face']['ImageId']))
print(' External Image ID: {}'.format(faceRecord['Face']['ExternalImageId']))
print(' Confidence: {}'.format(faceRecord['Face']['Confidence']))
print('Faces not indexed:')
for unindexedFace in response['UnindexedFaces']:
print(' Location: {}'.format(unindexedFace['FaceDetail']['BoundingBox']))
print(' Reasons:')
for reason in unindexedFace['Reasons']:
print(' ' + reason)
return len(response['FaceRecords'])
実行後に以下のログが出力されます。
※詳細なログも出力されますが割愛します。
Results for DSC_0001.png
Faces indexed:
Face ID: bbf242f9-15b1-4ef6-a37d-bc5e6bd11507
Location: {'Width': 0.4596697688102722, 'Height': 0.5054149627685547, 'Left': 0.3576127886772156, 'Top': 0.3911670446395874}
Image ID: ec9532ed-9d7b-3396-b018-3d9dc4e1e328
External Image ID: DSC_0001.png
Confidence: 99.99915313720703
Faces not indexed:
Faces indexed count: 1
06. イメージと FaceID のデータを S3 と DynamoDB に保存する
S3 へのアップロード
S3 への画像のアップロードはコンソールから行いました。
保存済みの画像以外で同じ人物が一人だけ映っている画像をアップロードしました。
DynamoDB テーブルの作成
-
database_name
は任意の名称に置換 -
region-name
を使用リージョンコードに変換
コード
import boto3
region = "ap-northeast-1"
database_name = 'database-name'
def lambda_handler(event, context):
dynamodb_table = create_dynamodb_table(database_name, region)
print("Table status:", dynamodb_table)
def create_dynamodb_table(table_name, region):
dynamodb = boto3.client("dynamodb", region_name=region)
table = dynamodb.create_table(
TableName=table_name,
KeySchema=[{
'AttributeName': 'FaceID', 'KeyType': 'HASH' # Partition key
},],
AttributeDefinitions=[
{
'AttributeName': 'FaceID', 'AttributeType': 'S' }, ],
ProvisionedThroughput={
'ReadCapacityUnits': 10, 'WriteCapacityUnits': 10 }
)
print(table)
return table
DynamoDB テーブルへの保存
-
bucket-name
は画像を保存した S3 バケット名に置換 -
file-name
およびkey-name
はS3 バケットに保存済みのいずれかの画像ファイル名に置換 -
region-name
を使用リージョンコードに変換 -
FACE-ID-HERE
は 05 で取得した Face ID に置換 -
IMAGE-ID-HERE
は 05 で取得した Image ID に置換 -
confidence-here
は 05 で取得した Confidence に置換
コード
import boto3
from pprint import pprint
from decimal import Decimal
import json
bucket = "bucket-name"
file_name = "file-name"
key_name = "key-name"
region = "region-name"
# Get URL of file
file_url = "https://s3.amazonaws.com/{}/{}".format(bucket, key_name)
print(file_url)
def lambda_handler(event, context):
dynamodb_resp = AddDBEntry(file_name, file_url, "FACE-ID-HERE",
"IMAGE-ID-HERE", confidence-here)
print("Database entry successful.")
pprint(dynamodb_resp, sort_dicts=False)
def AddDBEntry(file_name, file_url, face_id, image_id, confidence):
dynamodb = boto3.resource('dynamodb', region_name=region)
table = dynamodb.Table('test')
response = table.put_item(
Item={
'ExternalImageID': file_name,
'ImageURL': file_url,
'FaceID': face_id,
'ImageID': image_id,
'Confidence': json.loads(json.dumps(confidence), parse_float=Decimal)
}
)
return response
実行後、DynamoDB テーブルに上記アイテムが保存されます。
07. SearchFacesByImage オペレーションを呼び出す
ここまでの手順でコレクションに画像を登録できているので、再度 04 のコードを実行します。
04 の時点ではレスポンスが空でしたが、コレクション登録後には以下のようなログが出力されます。
FaceId:bbf242f9-15b1-4ef6-a37d-bc5e6bd11507
ImageId:ec9532ed-9d7b-3396-b018-3d9dc4e1e328
Similarity: 100.00%
Confidence: 99.99919891357422
コレクションに登録された画像の人物と、比較用に使用した画像の人物が一致しているかどうかを確認できています。
ユースケース
Using Amazon Rekognition for Identity Verification - Amazon Rekognition
By making use of Amazon Rekognition’s face detection, face comparison, and collection management operations, you can create an application with an identity verification solution.
チュートリアルの説明通りですが、本人確認を顔認証で行う場合に使用できるソリューションです。
- アプリなどから撮影画像などをアップロード
- サーバー側でコレクションに登録されているか確認
- 登録されている: 認証済みとして処理
- 登録されていない: 未認証として処理
まとめ
今回は本人確認における Amazon Rekognition の使用のチュートリアルを Lambda でやってみました。
どなたかの参考になれば幸いです。
Discussion