

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

# 比较图像中的人脸
<a name="faces-comparefaces"></a>

使用 Rekognition，您可以使用该操作比较两张图像之间的面孔。[CompareFaces](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_CompareFaces.html)此特征对于身份验证或照片匹配等应用非常有用。

CompareFaces 将*源*图像中的人脸与*目标*图像中的每张人脸进行比较。图像通过以下 CompareFaces 任一方式传递给：
+ 图像的 Base64 编码表示。
+ Amazon S3 对象。

**人脸检测与人脸比较**

人脸比较不同于人脸检测。人脸检测（使用 DetectFaces）仅识别图像或视频中人脸的存在和位置。相比之下，人脸比较涉及将源图像中检测到的人脸与目标图像中的人脸进行比较以找到匹配项。

**相似度阈值**

使用 `similarityThreshold` 参数定义响应中要包含的匹配项的最低置信度。默认情况下，响应中只返回相似度得分大于或等于 80% 的人脸。

**注意**  
`CompareFaces` 使用机器学习算法，这些算法是概率性的。假阴性是一种错误的预测，即与源图像中的人脸相比，目标图像中的人脸具有较低的相似性置信度得分。为了降低假阴性的可能性，我们建议您将目标图像与多个源图像进行比较。如果您计划使用 `CompareFaces` 来做出影响个人权利、隐私或服务访问权限的决定，我们建议您在采取行动之前将结果交给人类进行审查和进一步验证。

 

以下代码示例演示了如何使用各种 CompareFaces 操作 AWS SDKs。在 AWS CLI 示例中，您将两张 JPEG 图像上传到您的 Amazon S3 存储桶并指定对象密钥名称。在其他示例中，您从本地文件系统中加载两个文件并将它们作为图像字节数组输入。

**比较人脸**

1. 如果您尚未执行以下操作，请：

   1. 创建或更新具有`AmazonRekognitionFullAccess`和`AmazonS3ReadOnlyAccess`（仅限AWS CLI 示例）权限的用户。有关更多信息，请参阅 [步骤 1：设置 AWS 账户并创建用户](setting-up.md#setting-up-iam)。

   1. 安装并配置 AWS CLI 和 AWS SDKs。有关更多信息，请参阅 [第 2 步：设置 AWS CLI 和 AWS SDKs](setup-awscli-sdk.md)。

1. 使用以下示例代码调用 `CompareFaces` 操作。

------
#### [ Java ]

   此示例显示有关与从本地文件系统加载的源和目标图像中的人脸进行匹配的信息。

   将 `sourceImage` 和 `targetImage` 的值分别替换为源和目标图像的路径和文件名。

   ```
   //Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   //PDX-License-Identifier: MIT-0 (For details, see https://github.com/awsdocs/amazon-rekognition-developer-guide/blob/master/LICENSE-SAMPLECODE.)
   
   package aws.example.rekognition.image;
   import com.amazonaws.services.rekognition.AmazonRekognition;
   import com.amazonaws.services.rekognition.AmazonRekognitionClientBuilder;
   import com.amazonaws.services.rekognition.model.Image;
   import com.amazonaws.services.rekognition.model.BoundingBox;
   import com.amazonaws.services.rekognition.model.CompareFacesMatch;
   import com.amazonaws.services.rekognition.model.CompareFacesRequest;
   import com.amazonaws.services.rekognition.model.CompareFacesResult;
   import com.amazonaws.services.rekognition.model.ComparedFace;
   import java.util.List;
   import java.io.File;
   import java.io.FileInputStream;
   import java.io.InputStream;
   import java.nio.ByteBuffer;
   import com.amazonaws.util.IOUtils;
   
   public class CompareFaces {
   
      public static void main(String[] args) throws Exception{
          Float similarityThreshold = 70F;
          String sourceImage = "source.jpg";
          String targetImage = "target.jpg";
          ByteBuffer sourceImageBytes=null;
          ByteBuffer targetImageBytes=null;
   
          AmazonRekognition rekognitionClient = AmazonRekognitionClientBuilder.defaultClient();
   
          //Load source and target images and create input parameters
          try (InputStream inputStream = new FileInputStream(new File(sourceImage))) {
             sourceImageBytes = ByteBuffer.wrap(IOUtils.toByteArray(inputStream));
          }
          catch(Exception e)
          {
              System.out.println("Failed to load source image " + sourceImage);
              System.exit(1);
          }
          try (InputStream inputStream = new FileInputStream(new File(targetImage))) {
              targetImageBytes = ByteBuffer.wrap(IOUtils.toByteArray(inputStream));
          }
          catch(Exception e)
          {
              System.out.println("Failed to load target images: " + targetImage);
              System.exit(1);
          }
   
          Image source=new Image()
               .withBytes(sourceImageBytes);
          Image target=new Image()
               .withBytes(targetImageBytes);
   
          CompareFacesRequest request = new CompareFacesRequest()
                  .withSourceImage(source)
                  .withTargetImage(target)
                  .withSimilarityThreshold(similarityThreshold);
   
          // Call operation
          CompareFacesResult compareFacesResult=rekognitionClient.compareFaces(request);
   
   
          // Display results
          List <CompareFacesMatch> faceDetails = compareFacesResult.getFaceMatches();
          for (CompareFacesMatch match: faceDetails){
            ComparedFace face= match.getFace();
            BoundingBox position = face.getBoundingBox();
            System.out.println("Face at " + position.getLeft().toString()
                  + " " + position.getTop()
                  + " matches with " + match.getSimilarity().toString()
                  + "% confidence.");
   
          }
          List<ComparedFace> uncompared = compareFacesResult.getUnmatchedFaces();
   
          System.out.println("There was " + uncompared.size()
               + " face(s) that did not match");
      }
   }
   ```

------
#### [ Java V2 ]

   此代码取自 AWS 文档 SDK 示例 GitHub 存储库。请在[此处](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/javav2/example_code/rekognition/src/main/java/com/example/rekognition/CompareFaces.java)查看完整示例。

   ```
   import java.util.List;
   
   import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
   import software.amazon.awssdk.regions.Region;
   import software.amazon.awssdk.services.rekognition.RekognitionClient;
   import software.amazon.awssdk.services.rekognition.model.RekognitionException;
   import software.amazon.awssdk.services.rekognition.model.Image;
   import software.amazon.awssdk.services.rekognition.model.BoundingBox;
   import software.amazon.awssdk.services.rekognition.model.CompareFacesMatch;
   import software.amazon.awssdk.services.rekognition.model.CompareFacesRequest;
   import software.amazon.awssdk.services.rekognition.model.CompareFacesResponse;
   import software.amazon.awssdk.services.rekognition.model.ComparedFace;
   import software.amazon.awssdk.core.SdkBytes;
   import java.io.FileInputStream;
   import java.io.FileNotFoundException;
   import java.io.InputStream;
   
   // snippet-end:[rekognition.java2.detect_faces.import]
   
   /**
    * Before running this Java V2 code example, set up your development environment, including your credentials.
    *
    * For more information, see the following documentation topic:
    *
    * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
    */
   public class CompareFaces {
   
       public static void main(String[] args) {
   
           final String usage = "\n" +
               "Usage: " +
               "   <pathSource> <pathTarget>\n\n" +
               "Where:\n" +
               "   pathSource - The path to the source image (for example, C:\\AWS\\pic1.png). \n " +
               "   pathTarget - The path to the target image (for example, C:\\AWS\\pic2.png). \n\n";
   
           if (args.length != 2) {
               System.out.println(usage);
               System.exit(1);
           }
   
           Float similarityThreshold = 70F;
           String sourceImage = args[0];
           String targetImage = args[1];
           Region region = Region.US_EAST_1;
           RekognitionClient rekClient = RekognitionClient.builder()
               .region(region)
               .credentialsProvider(ProfileCredentialsProvider.create("profile-name"))
               .build();
   
           compareTwoFaces(rekClient, similarityThreshold, sourceImage, targetImage);
           rekClient.close();
      }
   
       // snippet-start:[rekognition.java2.compare_faces.main]
       public static void compareTwoFaces(RekognitionClient rekClient, Float similarityThreshold, String sourceImage, String targetImage) {
           try {
               InputStream sourceStream = new FileInputStream(sourceImage);
               InputStream tarStream = new FileInputStream(targetImage);
               SdkBytes sourceBytes = SdkBytes.fromInputStream(sourceStream);
               SdkBytes targetBytes = SdkBytes.fromInputStream(tarStream);
   
               // Create an Image object for the source image.
               Image souImage = Image.builder()
                   .bytes(sourceBytes)
                   .build();
   
               Image tarImage = Image.builder()
                   .bytes(targetBytes)
                   .build();
   
               CompareFacesRequest facesRequest = CompareFacesRequest.builder()
                   .sourceImage(souImage)
                   .targetImage(tarImage)
                   .similarityThreshold(similarityThreshold)
                   .build();
   
               // Compare the two images.
               CompareFacesResponse compareFacesResult = rekClient.compareFaces(facesRequest);
               List<CompareFacesMatch> faceDetails = compareFacesResult.faceMatches();
               for (CompareFacesMatch match: faceDetails){
                   ComparedFace face= match.face();
                   BoundingBox position = face.boundingBox();
                   System.out.println("Face at " + position.left().toString()
                           + " " + position.top()
                           + " matches with " + face.confidence().toString()
                           + "% confidence.");
   
               }
               List<ComparedFace> uncompared = compareFacesResult.unmatchedFaces();
               System.out.println("There was " + uncompared.size() + " face(s) that did not match");
               System.out.println("Source image rotation: " + compareFacesResult.sourceImageOrientationCorrection());
               System.out.println("target image rotation: " + compareFacesResult.targetImageOrientationCorrection());
   
           } catch(RekognitionException | FileNotFoundException e) {
               System.out.println("Failed to load source image " + sourceImage);
               System.exit(1);
           }
       }
       // snippet-end:[rekognition.java2.compare_faces.main]
   }
   ```

------
#### [ AWS CLI ]

   此示例显示`compare-faces` AWS CLI 操作的 JSON 输出。

   将`amzn-s3-demo-bucket`替换为包含源和目标图像的 Amazon S3 存储桶的名称。将 `source.jpg` 和 `target.jpg` 替换为源和目标图像的文件名。

   ```
   aws rekognition compare-faces --target-image \
   "{"S3Object":{"Bucket":"amzn-s3-demo-bucket","Name":"image-name"}}" \
   --source-image "{"S3Object":{"Bucket":"amzn-s3-demo-bucket","Name":"image-name"}}" 
   --profile profile-name
   ```

    如果您在 Windows 设备上访问 CLI，请使用双引号代替单引号，并用反斜杠（即 \$1）对内部双引号进行转义，以解决可能遇到的任何解析器错误。例如，请参阅以下内容：

   ```
   aws rekognition compare-faces --target-image "{\"S3Object\":{\"Bucket\":\"amzn-s3-demo-bucket\",\"Name\":\"image-name\"}}" \ 
   --source-image "{\"S3Object\":{\"Bucket\":\"amzn-s3-demo-bucket\",\"Name\":\"image-name\"}}" --profile profile-name
   ```

------
#### [ Python ]

   此示例显示有关与从本地文件系统加载的源和目标图像中的人脸进行匹配的信息。

   将 `source_file` 和 `target_file` 的值分别替换为源和目标图像的路径和文件名。将创建 Rekognition 会话的行中的`profile_name`值替换为您的开发人员资料的名称。

   ```
   # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   # PDX-License-Identifier: MIT-0 (For details, see https://github.com/awsdocs/amazon-rekognition-developer-guide/blob/master/LICENSE-SAMPLECODE.)
   
   import boto3
   
   def compare_faces(sourceFile, targetFile):
   
       session = boto3.Session(profile_name='profile-name')
       client = session.client('rekognition')
   
       imageSource = open(sourceFile, 'rb')
       imageTarget = open(targetFile, 'rb')
   
       response = client.compare_faces(SimilarityThreshold=80,
                                       SourceImage={'Bytes': imageSource.read()},
                                       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')
   
       imageSource.close()
       imageTarget.close()
       return len(response['FaceMatches'])
   
   def main():
       source_file = 'source-file-name'
       target_file = 'target-file-name'
       face_matches = compare_faces(source_file, target_file)
       print("Face matches: " + str(face_matches))
   
   if __name__ == "__main__":
       main()
   ```

------
#### [ .NET ]

   此示例显示有关与从本地文件系统加载的源和目标图像中的人脸进行匹配的信息。

   将 `sourceImage` 和 `targetImage` 的值分别替换为源和目标图像的路径和文件名。

   ```
   //Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   //PDX-License-Identifier: MIT-0 (For details, see https://github.com/awsdocs/amazon-rekognition-developer-guide/blob/master/LICENSE-SAMPLECODE.)
   
   using System;
   using System.IO;
   using Amazon.Rekognition;
   using Amazon.Rekognition.Model;
   
   public class CompareFaces
   {
       public static void Example()
       {
           float similarityThreshold = 70F;
           String sourceImage = "source.jpg";
           String targetImage = "target.jpg";
   
           AmazonRekognitionClient rekognitionClient = new AmazonRekognitionClient();
   
           Amazon.Rekognition.Model.Image imageSource = new Amazon.Rekognition.Model.Image();
           try
           {
               using (FileStream fs = new FileStream(sourceImage, FileMode.Open, FileAccess.Read))
               {
                   byte[] data = new byte[fs.Length];
                   fs.Read(data, 0, (int)fs.Length);
                   imageSource.Bytes = new MemoryStream(data);
               }
           }
           catch (Exception)
           {
               Console.WriteLine("Failed to load source image: " + sourceImage);
               return;
           }
   
           Amazon.Rekognition.Model.Image imageTarget = new Amazon.Rekognition.Model.Image();
           try
           {
               using (FileStream fs = new FileStream(targetImage, FileMode.Open, FileAccess.Read))
               {
                   byte[] data = new byte[fs.Length];
                   data = new byte[fs.Length];
                   fs.Read(data, 0, (int)fs.Length);
                   imageTarget.Bytes = new MemoryStream(data);
               }
           }
           catch (Exception)
           {
               Console.WriteLine("Failed to load target image: " + targetImage);
               return;
           }
   
           CompareFacesRequest compareFacesRequest = new CompareFacesRequest()
           {
               SourceImage = imageSource,
               TargetImage = imageTarget,
               SimilarityThreshold = similarityThreshold
           };
   
           // Call operation
           CompareFacesResponse compareFacesResponse = rekognitionClient.CompareFaces(compareFacesRequest);
   
           // Display results
           foreach(CompareFacesMatch match in compareFacesResponse.FaceMatches)
           {
               ComparedFace face = match.Face;
               BoundingBox position = face.BoundingBox;
               Console.WriteLine("Face at " + position.Left
                     + " " + position.Top
                     + " matches with " + match.Similarity
                     + "% confidence.");
           }
   
           Console.WriteLine("There was " + compareFacesResponse.UnmatchedFaces.Count + " face(s) that did not match");
   
       }
   }
   ```

------
#### [ Ruby ]

   此示例显示有关与从本地文件系统加载的源和目标图像中的人脸进行匹配的信息。

   将 `photo_source` 和 `photo_target` 的值分别替换为源和目标图像的路径和文件名。

   ```
     # Add to your Gemfile
      # gem 'aws-sdk-rekognition'
      require 'aws-sdk-rekognition'
      credentials = Aws::Credentials.new(
         ENV['AWS_ACCESS_KEY_ID'],
         ENV['AWS_SECRET_ACCESS_KEY']
      )
      bucket        = 'bucket' # the bucketname without s3://
      photo_source  = 'source.jpg'
      photo_target  = 'target.jpg'
      client   = Aws::Rekognition::Client.new credentials: credentials
      attrs = {
        source_image: {
          s3_object: {
            bucket: bucket,
            name: photo_source
          },
        },
        target_image: {
          s3_object: {
            bucket: bucket,
            name: photo_target
          },
        },
        similarity_threshold: 70
      }
      response = client.compare_faces attrs
      response.face_matches.each do |face_match|
        position   = face_match.face.bounding_box
        similarity = face_match.similarity
        puts "The face at: #{position.left}, #{position.top} matches with #{similarity} % confidence"
      end
   ```

------
#### [ Node.js ]

   此示例显示有关与从本地文件系统加载的源和目标图像中的人脸进行匹配的信息。

   将 `photo_source` 和 `photo_target` 的值分别替换为源和目标图像的路径和文件名。将创建 Rekognition 会话的行中的`profile_name`值替换为您的开发人员资料的名称。

   ```
   // Load the SDK
   var AWS = require('aws-sdk');
   const bucket = 'bucket-name' // the bucket name without s3://
   const photo_source  = 'photo-source-name' // path and the name of file
   const photo_target = 'photo-target-name'
   
   var credentials = new AWS.SharedIniFileCredentials({profile: 'profile-name'});
   AWS.config.credentials = credentials;
   AWS.config.update({region:'region-name'});
   
   const client = new AWS.Rekognition();
      const params = {
        SourceImage: {
          S3Object: {
            Bucket: bucket,
            Name: photo_source
          },
        },
        TargetImage: {
          S3Object: {
            Bucket: bucket,
            Name: photo_target
          },
        },
        SimilarityThreshold: 70
      }
      client.compareFaces(params, function(err, response) {
        if (err) {
          console.log(err, err.stack); // an error occurred
        } else {
          response.FaceMatches.forEach(data => {
            let position   = data.Face.BoundingBox
            let similarity = data.Similarity
            console.log(`The face at: ${position.Left}, ${position.Top} matches with ${similarity} % confidence`)
          }) // for response.faceDetails
        } // if
      });
   ```

------

## CompareFaces 操作请求
<a name="comparefaces-request"></a>

对 `CompareFaces` 的输入是一个图像。在本示例中，源和目标图像是从本地文件系统加载的。`SimilarityThreshold` 输入参数指定所比较的人脸必须匹配以包含在响应中的最小置信度。有关更多信息，请参阅 [使用图像](images.md)。

```
{
    "SourceImage": {
        "Bytes": "/9j/4AAQSk2Q==..."
    },
    "TargetImage": {
        "Bytes": "/9j/4O1Q==..."
    },
    "SimilarityThreshold": 70
}
```

## CompareFaces 操作响应
<a name="comparefaces-response"></a>

响应包括以下内容：
+ 一组匹配的人脸：包含每张匹配人脸的相似度得分和元数据的匹配人脸列表。如果多张人脸匹配，则 `faceMatches`

   数组包括所有人脸匹配。
+ 人脸匹配详细信息：每张匹配的人脸还提供边界框、置信度值、标记位置和相似度得分。
+ 不匹配的人脸列表：响应还包括目标图像中与源图像人脸不匹配的人脸。包括每张不匹配人脸的边界框。
+ 源人脸信息：包含有关用于比较的源图像中的人脸的信息（包括边界框和置信度值）。

该示例显示已在目标图像中找到一个人脸匹配。对于该人脸匹配，它提供了一个边界框和一个置信度值（Amazon Rekognition 在边界框中包含人脸的置信度值）。相似度得分为 99.99 指示人脸的相似程度。该示例也显示 Amazon Rekognition 在目标图像中找到的与源图像中分析的人脸不匹配的一张人脸。

```
{
    "FaceMatches": [{
        "Face": {
            "BoundingBox": {
                "Width": 0.5521978139877319,
                "Top": 0.1203877404332161,
                "Left": 0.23626373708248138,
                "Height": 0.3126954436302185
            },
            "Confidence": 99.98751068115234,
            "Pose": {
                "Yaw": -82.36799621582031,
                "Roll": -62.13221740722656,
                "Pitch": 0.8652129173278809
            },
            "Quality": {
                "Sharpness": 99.99880981445312,
                "Brightness": 54.49755096435547
            },
            "Landmarks": [{
                    "Y": 0.2996366024017334,
                    "X": 0.41685718297958374,
                    "Type": "eyeLeft"
                },
                {
                    "Y": 0.2658946216106415,
                    "X": 0.4414493441581726,
                    "Type": "eyeRight"
                },
                {
                    "Y": 0.3465650677680969,
                    "X": 0.48636093735694885,
                    "Type": "nose"
                },
                {
                    "Y": 0.30935320258140564,
                    "X": 0.6251809000968933,
                    "Type": "mouthLeft"
                },
                {
                    "Y": 0.26942989230155945,
                    "X": 0.6454493403434753,
                    "Type": "mouthRight"
                }
            ]
        },
        "Similarity": 100.0
    }],
    "SourceImageOrientationCorrection": "ROTATE_90",
    "TargetImageOrientationCorrection": "ROTATE_90",
    "UnmatchedFaces": [{
        "BoundingBox": {
            "Width": 0.4890109896659851,
            "Top": 0.6566604375839233,
            "Left": 0.10989011079072952,
            "Height": 0.278298944234848
        },
        "Confidence": 99.99992370605469,
        "Pose": {
            "Yaw": 51.51519012451172,
            "Roll": -110.32493591308594,
            "Pitch": -2.322134017944336
        },
        "Quality": {
            "Sharpness": 99.99671173095703,
            "Brightness": 57.23163986206055
        },
        "Landmarks": [{
                "Y": 0.8288310766220093,
                "X": 0.3133862614631653,
                "Type": "eyeLeft"
            },
            {
                "Y": 0.7632885575294495,
                "X": 0.28091415762901306,
                "Type": "eyeRight"
            },
            {
                "Y": 0.7417283654212952,
                "X": 0.3631140887737274,
                "Type": "nose"
            },
            {
                "Y": 0.8081989884376526,
                "X": 0.48565614223480225,
                "Type": "mouthLeft"
            },
            {
                "Y": 0.7548204660415649,
                "X": 0.46090251207351685,
                "Type": "mouthRight"
            }
        ]
    }],
    "SourceImageFace": {
        "BoundingBox": {
            "Width": 0.5521978139877319,
            "Top": 0.1203877404332161,
            "Left": 0.23626373708248138,
            "Height": 0.3126954436302185
        },
        "Confidence": 99.98751068115234
    }
}
```