本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
比较图像中的人脸
使用 Rekognition,您可以使用该操作比较两张图像之间的面孔。CompareFaces此功能对于身份验证或照片匹配等应用程序非常有用。
CompareFaces 将源图像中的人脸与目标图像中的每张人脸进行比较。图像以以下 CompareFaces 任一方式传递给:
-
以 base64 编码的图像表示形式。
-
亚马逊 S3 对象。
人脸检测与人脸比较
人脸比较不同于人脸检测。人脸检测(使用 DetectFaces)仅识别图像或视频中人脸的存在和位置。相比之下,人脸比较涉及将源图像中检测到的人脸与目标图像中的人脸进行比较以找到匹配项。
相似度阈值
使用similarityThreshold
参数定义响应中要包含的匹配项的最低置信度。默认情况下,响应中只返回相似度分数大于或等于 80% 的人脸。
CompareFaces
使用机器学习算法,这些算法是概率性的。假阴性是一种错误的预测,即与源图像中的人脸相比,目标图像中的人脸具有较低的相似性置信度得分。为了降低假阴性的可能性,我们建议您将目标图像与多个源图像进行比较。如果您计划使用 CompareFaces
来做出影响个人权利、隐私或服务访问权限的决定,我们建议您在采取行动之前将结果交给人类进行审查和进一步验证。
以下代码示例演示了如何将这些 CompareFaces 操作用于各种 AWS SDK。在 AWS CLI 示例中,您将两张 JPEG 图像上传到您的 Amazon S3 存储桶并指定对象密钥名称。在其他示例中,您从本地文件系统中加载两个文件并将它们作为图像字节数组输入。
比较人脸
-
如果您尚未执行以下操作,请:
-
创建或更新具有AmazonRekognitionFullAccess
和AmazonS3ReadOnlyAccess
(仅限AWS CLI 示例)权限的用户。有关更多信息,请参阅 步骤 1:设置AWS账户并创建用户。
-
安装和配置 AWS CLI 和 AWS SDK。有关更多信息,请参阅 第 2 步:设置 AWS CLI 以及 AWS SDKs。
-
使用以下示例代码调用 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 存储库。请在此处查看完整示例。
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 输出。
将bucket-name
替换为包含源和目标图像的 Amazon S3 存储桶的名称。将 source.jpg
和 target.jpg
替换为源和目标图像的文件名。
aws rekognition compare-faces --target-image \
"{"S3Object":{"Bucket":"bucket-name","Name":"image-name"}}" \
--source-image "{"S3Object":{"Bucket":"bucket-name","Name":"image-name"}}"
--profile profile-name
如果您在 Windows 设备上访问 CLI,请使用双引号代替单引号,并用反斜杠(即 \)对内部双引号进行转义,以解决可能遇到的任何解析器错误。例如,请参阅以下内容:
aws rekognition compare-faces --target-image "{\"S3Object\":{\"Bucket\":\"bucket-name\",\"Name\":\"image-name\"}}" \
--source-image "{\"S3Object\":{\"Bucket\":\"bucket-name\",\"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 操作请求
对 CompareFaces
的输入是一个图像。在本示例中,源和目标图像是从本地文件系统加载的。SimilarityThreshold
输入参数指定所比较的人脸必须匹配以包含在响应中的最小置信度。有关更多信息,请参阅 使用图像。
{
"SourceImage": {
"Bytes": "/9j/4AAQSk2Q==..."
},
"TargetImage": {
"Bytes": "/9j/4O1Q==..."
},
"SimilarityThreshold": 70
}
CompareFaces 操作响应
响应包括以下内容:
-
人脸匹配数组:包含每张匹配面孔的相似度分数和元数据的匹配面孔列表。如果多张面孔匹配,则 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
}
}