

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 Amazon Rekognition 进行身份验证
<a name="identity-verification-tutorial"></a>

Amazon Rekognition 为用户提供了多种操作，可以轻松创建身份验证系统。Amazon Rekognition 允许用户检测图像中的人脸，然后通过比较人脸数据将任何检测到的人脸与其他人脸进行比较。这些人脸数据存储在名为“集合”的服务器端容器中。通过利用 Amazon Rekognition 的人脸检测、人脸比较和集合管理操作，您可以创建带有身份验证解决方案的应用程序。

本教程将演示创建需要身份验证的应用程序的两个常见工作流程。

第一个工作流程涉及在集合中注册新用户。第二个工作流程涉及搜索现有集合，以便登录回归用户。

在本教程中，您将使用 [AWS SDK for Python](https://aws.amazon.com/sdk-for-python/)。您还可以查看AWS文档 SDK 示例存储库，了解更多 [GitHub P](https://github.com/awsdocs/aws-doc-sdk-examples) ython 教程。



**Topics**
+ [先决条件](#tutorial-prerequisites)
+ [创建集合](#tutorial-step1)
+ [新用户注册](#tutorial-step1.3.1)
+ [现有用户登录](#tutorial-step1.4)

## 先决条件
<a name="tutorial-prerequisites"></a>

在开始本教程之前，你需要安装 Python 并完成[设置 Python AWS 开发工具包](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 Simple Storage Service 存储桶](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. 保存并运行代码。复制集合 Arn。

   现在 Rekognition 集合已经创建，您可以在该集合中存储人脸信息和标识符。您还可以将人脸与存储的信息进行比较以进行验证。

## 新用户注册
<a name="tutorial-step1.3.1"></a>

您需要能够注册新用户并将其信息添加到集合中。注册新用户的过程通常涉及以下步骤：    使用 `CompareFaces` 检查输入图像（通常由摄像机拍摄）是否与参考图像匹配。在本教程中，您将使用本地图像作为图像，并使用您的 Amazon S3 存储桶中的图像作为参考图像。 input/target    在您的集合中搜索可能的匹配项，以确保新用户尚未使用 `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`操作来比较用户的本地 input/target 图像和 ID/stored 图像。如果在两张图片中检测到的人脸相符，则可以在集合中进行搜索，以查看用户是否已在其中注册。

首先编写一个函数，将输入图像与您存储在 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，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))
   ```

1. 保存并运行正在进行的代码。确定是否要保存 `IndexFaces` 操作返回的任何数据，例如分配给图像中人物的 FaceID。下一节将探讨如何保存这些数据。在继续操作之前，请复制返回的 `FaceId`、`ImageId` 和`Confidence`值。

### 将图像和 FaceID 数据存储在 Amazon S3 和 Amazon DynamoDB 中
<a name="tutorial-step1.3.6"></a>

获取输入图像的人脸 ID 后，可以将图像数据保存在 Amazon S3 中，而人脸数据和图像 URL 可以输入到 DynamoDB 等数据库中。

1. 编写代码，将输入图像上传到 Amazon S3 数据库。在下面的代码示例中，将`bucket`的值替换为您要将文件上传到的存储桶的名称，然后将`file_name`的值替换为您要存储在 Amazon S3 存储桶中的本地文件的名称。提供一个用于识别 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 Amazon S3。

1. 您还需要将返回的人脸 ID 保存到数据库中。这可以通过创建 DynamoDB 数据库表，然后将人脸 ID 上传到该表来完成。以下代码示例将创建 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 到表中。为此，您需要使用表函数与表建立连接，然后使用`put_item`函数上传数据。

   在以下代码示例中，将`bucket`的值替换为包含您上传到 Amazon S3 的输入图像的存储桶名称。您还需要将` file_name`的值替换为您上传到 Amazon S3 存储桶的输入文件的名称，并将`key_name`的值替换为您之前用于识别输入文件的密钥。最后，将`region`的值替换为与您的账户关联的区域名称。这些值应与步骤 1 中提供的值相匹配。

   将分配给人脸的 FaceId ImageId、和置信度值`AddDBEntry`存储在集合中。在下面的函数中提供您在后续 `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.  保存并运行后续代码示例，将返回的人脸 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']))
```