

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 Amazon Rekognition 進行身分驗證
<a name="identity-verification-tutorial"></a>

Amazon Rekognition 為使用者提供多項操作，可讓您輕鬆建立身分驗證系統。Amazon Rekognition 可讓使用者偵測影像中的人臉，然後比較人臉資料，將任何偵測到的人臉與其他人臉進行比較。此人臉資料存儲於稱為「集合」的伺服器端容器中。透過使用 Amazon Rekognition 的人臉偵測、人臉比較和集合管理操作，您可以使用身分驗證解決方案建立應用程式。

本教學課程將示範兩種常見的工作流程，以建立需要身分驗證的應用程式。

第一個工作流程涉及在集合中註冊新使用者。第二個工作流程涉及為了登錄傳回的使用者而搜尋現有集合。

您將在本教學課程中使用[適用於 Python 的 AWS SDK](https://aws.amazon.com/sdk-for-python/)。您也可以查看AWS文件開發套件範例 [GitHub 儲存庫](https://github.com/awsdocs/aws-doc-sdk-examples)，以取得更多 Python 教學課程。



**Topics**
+ [先決條件](#tutorial-prerequisites)
+ [建立集合](#tutorial-step1)
+ [新使用者註冊](#tutorial-step1.3.1)
+ [現有使用者簽署](#tutorial-step1.4)

## 先決條件
<a name="tutorial-prerequisites"></a>

開始本教學課程之前，您需要安裝 Python 並完成[設定 Python AWSSDK](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) 所需的步驟。除此之外，請務必備妥：
+ [建立 AWS 帳戶和 IAM 角色](https://docs.aws.amazon.com/rekognition/latest/dg/setting-up.html)
+ [已安裝 Python SDK (Boto3)](https://aws.amazon.com/sdk-for-python/)
+ [正確設定您的AWS存取憑證](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html)
+ [建立 Amazon 簡易儲存服務儲存貯體](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html)，並上傳您希望用作身分驗證之 ID 的映像。
+ 選擇第二張影像作為身份驗證的目標影像。

## 建立集合
<a name="tutorial-step1"></a>

您必須先擁有要使用的集合，才能在集合中註冊新使用者或搜尋系列。Amazon Rekognition 集合是伺服器端容器，用於儲存偵測到的人臉的相關資訊。



### 建立集合
<a name="tutorial-step1.2"></a>

您將首先編寫一個函數，該函數會建立供應用程式使用的集合。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)
   ```

1. 儲存並執行程式碼。複製下來集合阿恩。

   現在 Rekognition 系列已經建立完畢，您可以將人臉資訊和識別碼儲存在該集合中。您還可以將人臉與儲存的資訊比較以進行驗證。

## 新使用者註冊
<a name="tutorial-step1.3.1"></a>

您將希望能夠註冊新使用者並將他們的資訊新增到收藏中。註冊新使用者的過程通常包括以下步驟：    檢查輸入映像 (通常由相機拍攝) 是否與使用的參考映像匹配 `CompareFaces`。在本教學中，您將使用本機映像作為輸入/目標映像，並使用 Amazon S3 儲存貯體中的映像作為參考映像。   在您的集合中搜尋可能的匹配項，以確保新使用者尚未使用註冊 `SearchFacesByImage`。   如果使用者尚未在集合中，請使用註冊集合中輸入影像中找到的人臉 `IndexFaces`。   將輸入影像資料和 `FaceID` 資料分別存放在 Amazon S3 和 DynamoDB 中。   

### 呼叫 `DetectFaces` 操作。
<a name="tutorial-step1.3.2"></a>

編寫程式碼以通過 `DetectFaces` 操作檢查人臉映像的質量。您將使用該 `DetectFaces` 操作來確定相機拍攝的映像是否適合通過 `SearchFacesByImage` 操作進行處理。影像應該只包含一個人臉。您將提供本機輸入影像檔案給 `DetectFaces` 操作，並接收影像中偵測到的人臉的詳細資訊。下列範例程式碼會提供 `DetectFaces` 輸入影像，然後檢查影像中是否偵測到只有一個人臉。

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.")
   ```

1. 儲存並執行任務程式碼。

### 呼叫 `CompareFaces` 操作。
<a name="tutorial-step1.3.3"></a>

您的應用程式必須能夠在集合中註冊新使用者，並確認回訪使用者的身分。您將首先建立用於註冊新使用者的功能。您將首先使用 `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.")
   ```

1. 儲存並執行任務程式碼。

   將傳回一個回應物件，其中包含有關匹配的人臉和可信度的資訊。

### 呼叫 `SearchFacesByImage` 操作。
<a name="tutorial-step1.3.4"></a>

如果 `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']))
   ```

1. 儲存並執行任務程式碼。如果有匹配項，則表示映像中識別的人已經是收藏的一部分，因此無需繼續進行後續步驟。在這種情況下，您可以直接允許使用者存取應用程式。

### 呼叫 `IndexFaces` 操作。
<a name="tutorial-step1.3.5"></a>

假設在您搜尋的集合中找不到相符專案，您會想要將使用者的人臉新增至您的收藏。您可以透過呼叫作業來執行此 `IndexFaces` 操作。當您呼叫 IndexFaces Face 時，Amazon Rekognition 會擷取輸入影像中識別的人臉特徵，並將資料儲存在指定的集合中。

1. 首先編寫要呼叫的程式碼 `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))
   ```

1. 儲存並執行任務程式碼。決定是否要儲存 `IndexFaces` 操作傳回的任何資料，例如指定給影像中人物的 FaceID。下一節將研究如何儲存這些資料。在繼續之前，請先複製傳回的 `FaceId`、`ImageId`、和 `Confidence` 值。

### 將映像和 FaceID 資料存放在 Amazon S3 和 Amazon DynamoDB
<a name="tutorial-step1.3.6"></a>

取得輸入影像的人臉識別碼後，影像資料即可儲存在 Amazon S3 中，而人臉資料和影像 URL 則可輸入 DynamoDB 等資料庫中。

1. 撰寫程式碼，將輸入映像上傳到您的 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)
   ```

1. 儲存並執行正在進行的程式碼範例，將您的輸入影像上傳到 Amazon S3。

1. 您也需要將傳回的 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)
   ```

1. 儲存並執行正在進行的程式碼以建立資料表。

1. 建立資料表後，您可以將傳回的 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)
   ```

1.  儲存並執行正在進行的程式碼範例，將傳回的 Face ID 資料儲存在資料表中。

## 現有使用者簽署
<a name="tutorial-step1.4"></a>

使用者在集合中註冊之後，可以使用該 `SearchFacesByImage` 操作在傳回時對其進行驗證。您將需要獲取輸入映像，然後使用 `DetectFaces` 檢查輸入映像的質量。這會決定在執行 `SearchFacesbyImage` 操作之前是否已使用合適的影像。

### 呼叫 DetectFaces 操作
<a name="tutorial-step1.4.1"></a>

1. 您將使用該 `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.")
   ```

1. 儲存並執行程式碼。

### 呼叫 SearchFacesByImage 操作
<a name="tutorial-step1.4.2"></a>

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)
   ```

1. 儲存並執行程式碼。

### 檢查傳回的 FaceID 和可信度水平
<a name="tutorial-step1.4.3"></a>

現在，您可以透過列印出諸如 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']))
```