11

I'd like to try Rekognition's CompareFaces, but I don't see a full example of the syntax for using the HTTP API. Assuming I have two images, how would I call this API from Python to retrieve a similarity score?

4

1 回答 1

21

关于代码的信息

关于使用 AWS Rekognition 的 HTTP API 的文档很少,但是使用大多数代码用来访问 AWS 服务 HTTP 端点的模型非常简单。

有关以下代码的重要信息:

  • 你一定已经requests安装了。如果没有,可以在 shell 中运行以下命令(virtualenv建议在其中执行)。

    pip install requests
    
  • 使用us-east-1区域。Rekognition 目前在 , 中受支持us-east-1eu-west-1因此us-west-2您可以根据需要修改代码以支持不同的区域端点

  • 它期望磁盘上存在两个文件以供读取,称为source.jpgtarget.jpg

    正如她在我最近看过的电影中一样,我使用了《星球大战:侠盗一号》中菲丽希缇·琼斯的图像作为我的来源和目标。

    source.jpgFelicity Jones 源图像

    target.jpgFelicity Jones 目标图像

  • 它包括使用AWS Signature Version 4进行签名的代码。那里有一些库可以为您生成签名,但我不想过多地依赖第三方库来演示一个完整的示例。

  • 您使用的 AWS 凭证应该具有适用于 Rekognition 的有效策略

  • 它是为 Python 2.7 编写的(迁移到 Python 3 应该不难)。


编码

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import base64
import datetime
import hashlib
import hmac
import json

import requests

# Key derivation functions
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def sign(key, msg):
    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()


def getSignatureKey(key, date_stamp, regionName, serviceName):
    kDate = sign(('AWS4' + key).encode('utf-8'), date_stamp)
    kRegion = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, 'aws4_request')
    return kSigning


if __name__ == '__main__':
    # Read credentials from the environment
    access_key = os.environ.get('AWS_ACCESS_KEY_ID')
    secret_key = os.environ.get('AWS_SECRET_ACCESS_KEY')

    # Uncomment this line if you use temporary credentials via STS or similar
    #token = os.environ.get('AWS_SESSION_TOKEN')

    if access_key is None or secret_key is None:
        print('No access key is available.')
        sys.exit()

    # This code shows the v4 request signing process as shown in
    # http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html

    host = 'rekognition.us-east-1.amazonaws.com'
    endpoint = 'https://rekognition.us-east-1.amazonaws.com'
    service = 'rekognition'

    # Currently, all Rekognition actions require POST requests
    method = 'POST'

    region = 'us-east-1'

    # This defines the service target and sub-service you want to hit
    # In this case you want to use 'CompareFaces'
    amz_target = 'RekognitionService.CompareFaces'



    # Amazon content type - Rekognition expects 1.1 x-amz-json
    content_type = 'application/x-amz-json-1.1'

    # Create a date for headers and the credential string
    now = datetime.datetime.utcnow()
    amz_date = now.strftime('%Y%m%dT%H%M%SZ')
    date_stamp = now.strftime('%Y%m%d') # Date w/o time, used in credential scope

    # Canonical request information
    canonical_uri = '/'
    canonical_querystring = ''
    canonical_headers = 'content-type:' + content_type + '\n' + 'host:' + host + '\n' + 'x-amz-date:' + amz_date + '\n' + 'x-amz-target:' + amz_target + '\n'

    # list of signed headers
    signed_headers = 'content-type;host;x-amz-date;x-amz-target'

    # Our source image: http://i.imgur.com/OK8aDRq.jpg
    with open('source.jpg', 'rb') as source_image:
        source_bytes = base64.b64encode(source_image.read())

    # Our target image: http://i.imgur.com/Xchqm1r.jpg
    with open('target.jpg', 'rb') as target_image:
        target_bytes = base64.b64encode(target_image.read())

    # here we build the dictionary for our request data
    # that we will convert to JSON
    request_dict = {
            'SimilarityThreshold': 75.0,
            'SourceImage': {
                'Bytes': source_bytes
            },
            'TargetImage': {
                'Bytes': target_bytes
            }
    }

    # Convert our dict to a JSON string as it will be used as our payload
    request_parameters = json.dumps(request_dict)

    # Generate a hash of our payload for verification by Rekognition
    payload_hash = hashlib.sha256(request_parameters).hexdigest()

    # All of this is 
    canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash

    algorithm = 'AWS4-HMAC-SHA256'
    credential_scope = date_stamp + '/' + region + '/' + service + '/' + 'aws4_request'
    string_to_sign = algorithm + '\n' +  amz_date + '\n' +  credential_scope + '\n' +  hashlib.sha256(canonical_request).hexdigest()

    signing_key = getSignatureKey(secret_key, date_stamp, region, service)
    signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()

    authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' +  'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature

    headers = { 'Content-Type': content_type,
            'X-Amz-Date': amz_date,
            'X-Amz-Target': amz_target,

            # uncomment this if you uncommented the 'token' line earlier
            #'X-Amz-Security-Token': token,
            'Authorization': authorization_header}

    r = requests.post(endpoint, data=request_parameters, headers=headers)

    # Let's format the JSON string returned from the API for better output
    formatted_text = json.dumps(json.loads(r.text), indent=4, sort_keys=True)

    print('Response code: {}\n'.format(r.status_code))
    print('Response body:\n{}'.format(formatted_text))

代码输出

如果你让代码运行,它应该输出如下内容:

Response code: 200

Response body: 
{

    "FaceMatches": [],
    "SourceImageFace": {
        "BoundingBox": {
            "Height": 0.9448398351669312,
            "Left": 0.12222222238779068,
            "Top": -0.017793593928217888,
            "Width": 0.5899999737739563
        },
        "Confidence": 99.99041748046875
    }
}

真的,只需使用 boto3

您可以做的最简单的事情是使用boto3.

代码将被简化为如下所示,因为所有签名生成和 JSON 工作都变得不必要了。

确保您已boto3在环境中或通过配置文件配置了凭据,或者将您的凭据与代码内联。有关详细信息,请参阅boto3配置

用于此的代码使用boto3Rekognition API

import pprint

import boto3

# Set this to whatever percentage of 'similarity'
# you'd want
SIMILARITY_THRESHOLD = 75.0

if __name__ == '__main__':
    client = boto3.client('rekognition')

    # Our source image: http://i.imgur.com/OK8aDRq.jpg
    with open('source.jpg', 'rb') as source_image:
        source_bytes = source_image.read()

    # Our target image: http://i.imgur.com/Xchqm1r.jpg
    with open('target.jpg', 'rb') as target_image:
        target_bytes = target_image.read()

    response = client.compare_faces(
                   SourceImage={ 'Bytes': source_bytes },
                   TargetImage={ 'Bytes': target_bytes },
                   SimilarityThreshold=SIMILARITY_THRESHOLD
    )

    pprint.pprint(response)

上面的boto3例子应该输出这个:

{u'FaceMatches': [],
 'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive',
                                      'content-length': '195',
                                      'content-type': 'application/x-amz-json-1.1',
                                      'date': 'Sat, 31 Dec 2016 23:15:56 GMT',
                                      'x-amzn-requestid': '13edda2d-cfaf-11e6-9999-d3abf4c2feb3'},
                      'HTTPStatusCode': 200,
                      'RequestId': '13edda2d-cfaf-11e6-9999-d3abf4c2feb3',
                      'RetryAttempts': 0},
 u'SourceImageFace': {u'BoundingBox': {u'Height': 0.9448398351669312,
                                       u'Left': 0.12222222238779068,
                                       u'Top': -0.017793593928217888,
                                       u'Width': 0.5899999737739563},
                      u'Confidence': 99.99041748046875}}
于 2016-12-30T04:48:54.730 回答