本人確認における Amazon Rekognition の使用 - Amazon Rekognition

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

本人確認における Amazon Rekognition の使用

Amazon Rekognition には、本人確認のシステムを簡単に作成できるオペレーションが複数用意されています。Amazon Rekognition を使用すれば、ユーザーはイメージから顔を検出して、検出された顔と他の顔とでデータどうしを比較し、顔を比較できます。この顔データは「コレクション」と呼ばれるサーバー側のコンテナに保存されます。Amazon Rekognition の顔検出、顔比較、コレクション管理の各オペレーションを活用することで、本人確認の機能を備えたアプリケーションを作成できます。

このチュートリアルでは、本人確認が必要なアプリケーションを作成するための、一般的な 2 つのワークフローを紹介します。

1 つ目のワークフローは、新規ユーザーをコレクションに登録する作業を伴います。2 つ目のワークフローは、リピーターをログインさせるために既存のコレクションを検索する作業を伴います。

このチュートリアルでは AWS SDK for Python を使用します。その他の Python チュートリアルについては、 AWS Documentation SDK サンプル GitHub リポジトリも参照してください。

前提条件

このチュートリアルを開始する前に、Python をインストールし、Python AWS SDK のセットアップに必要な手順を完了する必要があります。これ以外にも、次のことを確認してください:

コレクションの作成

コレクションに新規ユーザーを登録する、またはコレクションでユーザーを検索する前に、作業を行うコレクションを作成しておく必要があります。Amazon Rekognition コレクションとはサーバー側のコンテナであり、検出した顔に関する情報はここに保存されます。

コレクションを作成する

最初に、自分のアプリケーションで使用するコレクションを作成するための、関数を作成します。Amazon Rekognition では、検出した顔に関する情報は、コレクションと呼ばれるサーバー側のコンテナに保存されます。既知の顔に関しては、コレクションに保存された顔情報を検索できます。顔情報を保存するには、まず、CreateCollection オペレーションを使ってコレクションを作成する必要があります。

  1. 作成するコレクションの名前を選択します。以下のコードで、collection_id の値を、作成するコレクションの名前に置き換え、region の値を、ユーザー認証情報で定義されているリージョンの名前に置き換えます。Tags 引数を使用すると、任意のタグをコレクションに適用できますが、必須ではありません。CreateCollection オペレーションは、コレクションの Arn など、作成したコレクションに関する情報を返します。コードを実行した後に受け取った Arn は、書き留めておきます。

    import boto3 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...') collection_id = 'collection-id-name' region = "region-name" create_collection(collection_id, region)
  2. コードを保存して実行します。コレクション Arn を書き留めておきます。

    Rekognition コレクションを作成できました。これで、顔の情報や ID をこのコレクションに保存できます。また、顔を、保存した情報と比較して検証することもできます。

新規ユーザー登録

次に、新規ユーザーをコレクションに登録し、その情報を追加します。新規ユーザーを登録するプロセスは、通常は以下のステップに従います。

DetectFaces オペレーションを呼び出す

DetectFaces オペレーションを使って顔イメージの画質をチェックするための、コードを記述します。DetectFaces オペレーションを使って、カメラで撮影したイメージが SearchFacesByImage オペレーションによる処理に適しているかどうかを判断します。イメージに映る顔は 1 つでなければなりません。DetectFaces オペレーションでローカルの入力イメージファイルを指定し、イメージ内で検出された顔の詳細を受け取ります。次のコード例では、DetectFaces で入力イメージを指定し、イメージ内で検出された顔が 1 つのみであるかどうかを確認します。

  1. 以下のコード例で、photo を、検出しようとしている顔のターゲットイメージの名前に置き換えます。また、region の値は、アカウントに関連付けられているリージョンの名前に置き換える必要があります。

    import boto3 import json def detect_faces(target_file, region): client=boto3.client('rekognition', region_name=region) imageTarget = open(target_file, 'rb') response = client.detect_faces(Image={'Bytes': imageTarget.read()}, 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']) photo = 'photo-name' region = 'region-name' 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.")
  2. 上のコードを保存して実行します。

CompareFaces オペレーションを呼び出す

アプリケーションでは、コレクションに新規ユーザーを登録し、リピーターが同一人物であることを確認できる必要があります。そのためには、最初に、新規ユーザーの登録に使用する関数を作成します。まず、CompareFaces オペレーションを使って、ユーザーのローカルの入力イメージ/ターゲットイメージと、ID/保存済みイメージを比較します。両方のイメージから検出された顔が一致している場合は、コレクション内を検索し、このユーザーが既に登録されているかどうかを確認できます。

まず、入力イメージを、Amazon S3 バケットに保存した ID イメージと比較する関数を作成します。以下のコード例では、入力イメージを自分で用意する必要があります。このイメージは、何らかの方法でライブネス検出を行った後に、撮影する必要があります。また、Amazon S3 バケットに保存されているイメージの名前も渡す必要があります。

  1. bucket の値を、ソースファイルが保存されている Amazon S3 バケットの名前に置き換えます。また、source_file の値は、使用しているソースイメージの名前に置き換える必要があります。target_file の値を、指定したターゲットファイルの名前に置き換えます。region の値を、ユーザー認証情報で定義されている region の名前に置き換えます。

    また、similarityThreshold 引数を使用して、レスポンスで返すマッチレベルの最小信頼度も指定します。検出された顔は、信頼度がこのしきい値を超えた場合にのみ、FaceMatches 配列に返されます。選択した similarityThreshold は、ユーザー固有のユースケースの性質を反映しているものでなければなりません。ユースケースが重大なセキュリティアプリケーションに関係する場合、選択するしきい値は 99 を使用します。

    import boto3 def compare_faces(bucket, sourceFile, targetFile, region): client = boto3.client('rekognition', region_name=region) imageTarget = open(targetFile, 'rb') response = client.compare_faces(SimilarityThreshold=99, SourceImage={'S3Object':{'Bucket':bucket,'Name':sourceFile}}, TargetImage={'Bytes': imageTarget.read()}) 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']) bucket = 'bucket-name' source_file = 'source-file-name' target_file = 'target-file-name' region = "region-name" 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.")
  2. 上のコードを保存して実行します。

    一致した顔と、信頼度に関する情報を含む、レスポンスオブジェクトが返されます。

SearchFacesByImage オペレーションを呼び出す

CompareFaces オペレーションの信頼度が、選択した SimilarityThreshold を上回った場合、入力イメージに一致する可能性のある顔をコレクション内で検索します。コレクションで一致する顔が見つかった場合、そのユーザーは既にコレクションに登録されている可能性が高いため、新規ユーザーとして登録する必要はありません。一致する顔が見つからなければ新規ユーザーとしてコレクションに登録できます。

  1. まず、SearchFacesByImage オペレーションを呼び出すコードを作成します。このオペレーションは、ローカルのイメージファイルを引数として受け取り、提供されたイメージの中で最も多く検出された顔と一致する顔を Collection で検索します。

    以下のコード例で、collectionId の値を、検索するコレクションに変更します。region の値を、アカウントに関連付けられたリージョンの名前に置き換えます。また、photo の値を、入力ファイルの名前に置き換える必要があります。さらに、threshold の値を、選択したパーセンタイルに置き換えて、類似度のしきい値を指定します。

    import boto3 collectionId = 'collection-id-name' region = "region-name" photo = 'photo-name' threshold = 99 maxFaces = 1 client = boto3.client('rekognition', region_name=region) # input image should be local file here, not s3 file with open(photo, 'rb') as image: response = client.search_faces_by_image(CollectionId=collectionId, Image={'Bytes': image.read()}, FaceMatchThreshold=threshold, MaxFaces=maxFaces) 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']))
  2. 上のコードを保存して実行します。一致する顔が見つかった場合、イメージで認識された人物は既にコレクションに含まれているため、次のステップに進む必要はありません。この場合は、ユーザーにアプリケーションへのアクセスを許可するだけで済みます。

IndexFaces オペレーションを呼び出す

検索したコレクションの中に一致する顔が見つからなければ、そのユーザーの顔をコレクションに追加する必要があります。顔を追加するには、IndexFaces オペレーションを呼び出します。IndexFaces を呼び出すと、入力イメージで識別された顔の特徴が Amazon Rekognition によって抽出され、そのデータが指定したコレクションに保存されます。

  1. まず、IndexFaces を呼び出すコードを作成します。image の値を、IndexFaces オペレーションの入力イメージとして使用するローカルファイルの名前に置き換えます。また、photo_name の値を、入力イメージの名前に置き換える必要があります。collection_id の値を、以前に作成したコレクションの ID に置き換えます。次に、region の値を、アカウントに関連付けられたリージョンの名前に置き換えます。また、MaxFaces 入力パラメータの値を指定します。このパラメータは、インデックスを作成する必要がある、イメージ内の顔の最大数を定義します。このパラメータのデフォルト値は 1 です。

    import boto3 def add_faces_to_collection(target_file, photo, collection_id, region): client = boto3.client('rekognition', region_name=region) imageTarget = open(target_file, 'rb') response = client.index_faces(CollectionId=collection_id, Image={'Bytes': imageTarget.read()}, 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']) image = 'image-file-name' collection_id = 'collection-id-name' photo_name = 'desired-image-name' region = "region-name" indexed_faces_count = add_faces_to_collection(image, photo_name, collection_id, region) print("Faces indexed count: " + str(indexed_faces_count))
  2. 上のコードを保存して実行します。イメージ内の人物に割り当てられた FaceID など、IndexFaces オペレーションによって返されるデータを保存するかどうかを決定します。このデータを保存する方法は、次のセクションで解説します。次に進む前に、返された FaceIdImageIdConfidence の値を書き留めておきます。

イメージと FaceID のデータを Amazon S3 と Amazon DynamoDB に保存する

入力イメージの Face ID を取得すると、イメージデータを Amazon S3 に保存し、顔データとイメージ URL を DynamoDB などのデータベースに入力できるようになります。

  1. 入力イメージを Amazon S3 データベースにアップロードするためのコードを作成します。以下のコード例で、bucket の値を、ファイルのアップロード先となるバケットの名前に置き換え、file_name の値を、Amazon S3 バケットに保存するローカルファイルの名前に置き換えます。key_name の値を、イメージファイルに付ける名前に置き換えることにより、Amazon S3 バケット内のファイルを識別するキー名を指定します。アップロードするファイルは、前にコード例で定義したファイルと同じファイルで、IndexFaces に使用した入力ファイルです。最後に、region の値を、アカウントに関連付けられたリージョンの名前に置き換えます。

    import boto3 import logging from botocore.exceptions import ClientError # store local file in S3 bucket bucket = "amzn-s3-demo-bucket" file_name = "file-name" key_name = "key-name" region = "region-name" s3 = boto3.client('s3', region_name=region) # Upload the file try: response = s3.upload_file(file_name, bucket, key_name) print("File upload successful!") except ClientError as e: logging.error(e)
  2. 上のコード例を保存して実行し、入力イメージを Amazon S3 にアップロードします。

  3. 返された Face ID もデータベースに保存します。保存するには、DynamoDB データベーステーブルを作成し、そのテーブルに Face ID をアップロードします。以下のコード例では、DynamoDB テーブルを作成します。テーブルを作成するコードを実行するのは 1 回のみですので、ご注意ください。以下のコードで、region の値を、アカウントに関連付けられたリージョンの値に置き換えます。また、database_name の値を、DynamoDB テーブルに付ける名前に置き換えます。

    import boto3 # Create DynamoDB database with image URL and face data, face ID 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 region = "region-name" database_name = 'database-name' dynamodb_table = create_dynamodb_table(database_name, region) print("Table status:", dynamodb_table)
  4. 上のコードを保存して実行し、テーブルを作成します。

  5. テーブルを作成すると、返された FaceID をそこにアップロードできます。アップロードするには、Table 関数を使用してテーブルへの接続を確立し、put_item 関数を使用してデータをアップロードします。

    以下のコード例で、bucket の値を、Amazon S3 にアップロードした入力イメージを含むバケットの名前に置き換えます。また、 file_name の値を、Amazon S3 バケットにアップロードした入力ファイルの名前に置き換え、key_name の値を、前に入力ファイルの識別に使用したキーに置き換えます。最後に、region の値を、アカウントに関連付けられたリージョンの名前に置き換えます。これらの値は、ステップ 1 で指定した値と一致している必要があります。

    AddDBEntry は、顔に割り当てられた FaceID、ImageId、Confidence の値をコレクションに保存します。前の IndexFaces セクションのステップ 2 で保存した値を、以下の関数に入力します。

    import boto3 from pprint import pprint from decimal import Decimal import json # The local file that was stored in S3 bucket bucket = "amzn-s3-demo-bucket" 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) # upload face-id, face info, and image url def AddDBEntry(file_name, file_url, face_id, image_id, confidence): dynamodb = boto3.resource('dynamodb', region_name=region) table = dynamodb.Table('FacesDB-4') 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 # Mock values for face ID, image ID, and confidence - replace them with actual values from your collection results 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)
  6. 上のコード例を保存して実行し、返された Face ID データをテーブルに保存します。

既存ユーザーのログイン

ユーザーは、一度コレクションに登録されると、SearchFacesByImage オペレーションを使って、再度利用する際に認証を受けることができます。そのためには、入力イメージを取得し、そのイメージの質を DetectFaces を使って確認する必要があります。そうすることで、SearchFacesbyImage オペレーションを実行する前に、適切なイメージが使用されているかどうかを判断します。

DetectFaces オペレーションを呼び出す

  1. DetectFaces オペレーションを使って、顔イメージの画質をチェックし、カメラで撮影したイメージが SearchFacesByImage オペレーションによる処理に適しているかどうかを判断します。入力イメージには顔を 1 つしか含むことができません。以下のコード例では、入力イメージを取得して DetectFaces オペレーションに使用します。

    以下のコード例では、photo の値を、ローカルのターゲットイメージの名前に置き換え、region の値を、アカウントに関連付けられたリージョンの名前に置き換えます。

    import boto3 import json def detect_faces(target_file, region): client=boto3.client('rekognition', region_name=region) imageTarget = open(target_file, 'rb') response = client.detect_faces(Image={'Bytes': imageTarget.read()}, 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']) photo = 'photo-name' region = 'region-name' 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.")
  2. コードを保存して実行します。

SearchFacesByImage オペレーションを呼び出す

  1. SearchFacesByImage を使って検出された顔とコレクション内にある顔とを比較するコードを作成します。上の「新規ユーザー登録」のセクションで紹介したコードを使って、入力イメージを SearchFacesByImage オペレーションに提供します。

    以下のコード例で、collectionId の値を、検索するコレクションに変更します。また、bucket の値を Amazon S3 バケットの名前に変更し、fileName の値を そのバケット内のイメージファイルに変更します。region の値を、アカウントに関連付けられたリージョンの名前に置き換えます。さらに、threshold の値を、選択したパーセンタイルに置き換えて、類似度のしきい値を指定します。

    import boto3 bucket = 'amzn-s3-demo-bucket' collectionId = 'collection-id-name' region = "region-name" fileName = 'file-name' threshold = 70 maxFaces = 1 client = boto3.client('rekognition', region_name=region) # input image should be local file here, not s3 file with open(fileName, 'rb') as image: response = client.search_faces_by_image(CollectionId=collectionId, Image={'Bytes': image.read()}, FaceMatchThreshold=threshold, MaxFaces=maxFaces)
  2. コードを保存して実行します。

返された FaceID と信頼度を確認

FaceID、Similarity、Confidence の各属性など、レスポンスの要素を出力することにより、一致した FaceID の情報を確認できるようになりました。

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']))