本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 Amazon Rekognition 進行身分驗證
Amazon Rekognition 為使用者提供多項操作,可讓您輕鬆建立身分驗證系統。Amazon Rekognition 可讓使用者偵測影像中的人臉,然後比較人臉資料,將任何偵測到的人臉與其他人臉進行比較。此人臉資料存儲於稱為「集合」的伺服器端容器中。透過使用 Amazon Rekognition 的人臉偵測、人臉比較和集合管理操作,您可以使用身分驗證解決方案建立應用程式。
本教學課程將示範兩種常見的工作流程,以建立需要身分驗證的應用程式。
第一個工作流程涉及在集合中註冊新使用者。第二個工作流程涉及為了登錄傳回的使用者而搜尋現有集合。
您將在本教學課程中使用適用於 Python 的AWS SDK
先決條件
開始本教學課程之前,您需要安裝 Python 並完成設定 Python AWS SDK
-
建立 Amazon 簡易儲存服務儲存貯體,並上傳您希望用作身分驗證之 ID 的映像。
-
選擇第二張影像作為身份驗證的目標影像。
建立集合
您必須先擁有要使用的集合,才能在集合中註冊新使用者或搜尋系列。Amazon Rekognition 集合是伺服器端容器,用於儲存偵測到的人臉的相關資訊。
建立集合
您將首先編寫一個函數,該函數會建立供應用程式使用的集合。Amazon Rekognition 會在伺服器端容器 (稱為「集合」) 中儲存偵測到的人臉相關資訊。您可以搜尋儲存在集合中的人臉資訊,找出已知的人臉。若要儲存人臉資訊,您首先需要使用該 CreateCollection
操作建立集合。
-
選擇您想要建立的收藏名稱。在下列程式碼中,將
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)
-
儲存並執行程式碼。複製下來集合阿恩。
現在 Rekognition 系列已經建立完畢,您可以將人臉資訊和識別碼儲存在該集合中。您還可以將人臉與儲存的資訊比較以進行驗證。
新使用者註冊
您將希望能夠註冊新使用者並將他們的資訊新增到收藏中。註冊新使用者的過程通常包括以下步驟:
呼叫 DetectFaces
操作。
編寫程式碼以通過 DetectFaces
操作檢查人臉映像的質量。您將使用該 DetectFaces
操作來確定相機拍攝的映像是否適合通過 SearchFacesByImage
操作進行處理。影像應該只包含一個人臉。您將提供本機輸入影像檔案給 DetectFaces
操作,並接收影像中偵測到的人臉的詳細資訊。下列範例程式碼會提供 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.")
-
儲存並執行任務程式碼。
呼叫 CompareFaces
操作。
您的應用程式必須能夠在集合中註冊新使用者,並確認回訪使用者的身分。您將首先建立用於註冊新使用者的功能。您將首先使用 CompareFaces
操作來比較使用者的本地輸入/目標映像和 ID/儲存的映像。如果在兩個影像中偵測到的人臉之間存在相符專案,您可以搜尋集合,以查看使用者是否已在其中註冊。
首先撰寫一個函數,將輸入影像與您存放在 Amazon S3 儲存貯體中的 ID 映像進行比較。在下面的程式碼範例中,您將需要自己提供輸入映像,這些映像應在使用某種形式的活體偵測器後被擷取。您還需要傳遞您的 Amazon S3 儲存貯體中所存放的映像名稱。
-
將
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.")
-
儲存並執行任務程式碼。
將傳回一個回應物件,其中包含有關匹配的人臉和可信度的資訊。
呼叫 SearchFacesByImage
操作。
如果 CompareFaces
操作的信賴等級高於您所選擇的 SimilarityThreshold
,則您需要搜尋集合中可能與輸入映像匹配的人臉。如果在您的收藏中找到匹配項,這意味著該使用者很可能已經在收藏中註冊,並且不需要在您的收藏中註冊新使用者。如果沒有相符專案,您可以在收藏中註冊新使用者。
-
首先編寫將調用
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']))
-
儲存並執行任務程式碼。如果有匹配項,則表示映像中識別的人已經是收藏的一部分,因此無需繼續進行後續步驟。在這種情況下,您可以直接允許使用者存取應用程式。
呼叫 IndexFaces
操作。
假設在您搜尋的集合中找不到相符專案,您會想要將使用者的人臉新增至您的收藏。您可以透過呼叫作業來執行此 IndexFaces
操作。當您呼叫 IndexFaces Face 時,Amazon Rekognition 會擷取輸入影像中識別的人臉特徵,並將資料儲存在指定的集合中。
-
首先編寫要呼叫的程式碼
IndexFaces
。將image
的值取代為您要用作 IndexFaces 作業輸入影像的本機檔案名稱。您還需要將photo_name
的值替換為輸入映像的所需名稱。以您先前建立的集合 ID 取代collection_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))
-
儲存並執行任務程式碼。決定是否要儲存
IndexFaces
操作傳回的任何資料,例如指定給影像中人物的 FaceID。下一節將研究如何儲存這些資料。在繼續之前,請先複製傳回的FaceId
、ImageId
、和Confidence
值。
將映像和 FaceID 資料存放在 Amazon S3 和 Amazon DynamoDB
取得輸入影像的人臉識別碼後,影像資料即可儲存在 Amazon S3 中,而人臉資料和影像 URL 則可輸入 DynamoDB 等資料庫中。
-
撰寫程式碼,將輸入映像上傳到您的 Amazon S3 資料庫。在接下來的程式碼範例中,以您想要上傳檔案的儲存貯體名稱取代
bucket
的值,然後以您想要存放在 Amazon S3 儲存貯體的本機檔案名稱取代file_name
的值。提供可識別 Amazon S3 儲存貯體中檔案的金鑰名稱,方法是將key_name
的值取代為映像檔的名稱。您要上傳的檔案與先前程式碼範例中定義的檔案相同,即您用於 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)
-
儲存並執行正在進行的程式碼範例,將您的輸入影像上傳到 Amazon S3。
-
您也需要將傳回的 Face ID 儲存到資料庫中。這可以透過建立 DynamoDB 資料庫資料表,然後將人臉識別碼上傳至該資料表來完成。以下程式碼範例會建立 DynamoDB 資料表。請注意,您只需要執行一次建立此資料表的程式碼。在下列程式碼中,將
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)
-
儲存並執行正在進行的程式碼以建立資料表。
-
建立資料表後,您可以將傳回的 FaceId 上傳到該表中。若要這麼做,您將使用 Table 函數建立與資料表的連線,然後使用
put_item
函數上傳資料。在下列程式碼範例中,將
bucket
的值取代為包含您上傳至 Amazon S3 之輸入影像的儲存貯體名稱。您還需要將file_name
的值替換為上傳到 Amazon S3 儲存貯體的輸入檔案名稱,以及先前用於識別輸入檔案的金鑰的key_name
值。最後,將region
的值替換為與您的帳戶相關聯的區域名稱。這些值應與步驟 1 中提供的值相符。AddDBEntry
會儲存指派給集合中人臉的 FaceId、ImageId 和可信度值。提供以下功能,其中包含您在繼續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)
-
儲存並執行正在進行的程式碼範例,將傳回的 Face ID 資料儲存在資料表中。
現有使用者簽署
使用者在集合中註冊之後,可以使用該 SearchFacesByImage
操作在傳回時對其進行驗證。您將需要獲取輸入映像,然後使用 DetectFaces
檢查輸入映像的質量。這會決定在執行 SearchFacesbyImage
操作之前是否已使用合適的影像。
呼叫 DetectFaces 操作
-
您將使用該
DetectFaces
操作來檢查人臉影像的品質,並確定相機拍攝的影像是否適合透過SearchFacesByImage
操作進行處理。輸入映像應該只包含一張臉。下列程式碼範例會取得輸入影像,並將其提供給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.")
-
儲存並執行程式碼。
呼叫 SearchFacesByImage 操作
-
撰寫程式碼,使用
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)
-
儲存並執行程式碼。
檢查傳回的 FaceID 和可信度水平
現在,您可以透過列印出諸如 FaceId、相似性和可信度屬性之類的回應元素來檢查匹配的 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']))