2016-12-30 1 views

Répondre

13

Informations sur le code

Il y a peu de documentation autour de l'utilisation de l'API HTTP pour AWS Rekognition, mais il est assez simple d'utiliser le modèle que la plupart code utilise pour frapper AWS services points de terminaison HTTP.

Informations importantes concernant le code qui suit:

  • Vous devez avoir installé requests. Si vous ne l'avez pas, vous pouvez exécuter ce qui suit dans votre shell (il est recommandé de le faire en virtualenv).

    pip install requests 
    
  • La région us-east-1 est utilisé. Rekognition est actuellement pris en charge dans us-east-1, eu-west-1 et us-west-2 afin que vous puissiez modifier le code pour prendre en charge different region endpoints comme vous le souhaitez.

  • Il s'attend à ce que deux fichiers existent sur le disque pour la lecture, appelés source.jpg et target.jpg. Comme elle est dans le film le plus récent que j'ai vu, j'utilise des images de Felicity Jones de Star Wars: Rogue One comme ma source et ma cible.

    Le source.jpg est: Felicity Jones source image

    Le target.jpg est: Felicity Jones target image

  • Il inclut le code pour le faire signer avec AWS Signature Version 4. Il y a des bibliothèques qui vont faire la génération de signature pour vous, mais je ne voulais pas trop compter sur les bibliothèques tierces afin de montrer un exemple complet. Les informations d'identification AWS que vous utilisez doivent avoir un policy for Rekognition valide.

  • Il a été écrit pour Python 2.7 (ne devrait pas être terriblement difficile de passer à Python 3).


Le code

#!/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)) 

Code de sortie

Si vous obtenez le code en cours d'exécution, il doit quelque chose comme de sortie ceci:

Response code: 200 

Response body: 
{ 

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

Vraiment, il suffit d'utiliser boto3

La chose la plus simple que vous pouvez faire est d'utiliser boto3.

Le code serait simplifié à quelque chose comme le suivant, car toute la génération de signature et le travail JSON deviennent inutiles. Assurez-vous d'avoir configuré boto3 avec les informations d'identification dans l'environnement ou via le fichier de configuration, ou insérez vos informations d'identification dans le code. Pour plus d'informations, voir boto3 configuration. Le code pour cela utilise le boto3 Rekognition 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) 

L'exemple ci-dessus boto3 devrait afficher ceci:

{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}} 
+1

J'essaie 'boto3' car il semble certainement plus simple. L'appel initial ne devrait-il pas être quelque chose comme: 'client = boto3.client ('rekognition', aws_access_key_id = clé, aws_secret_access_key = secret, région_name = région)'? – jensph

+0

Je suis capable d'utiliser la démo Rekognition dans la console AWS, cependant j'obtiens une erreur en utilisant 'boto3':' Une erreur est survenue (AccessDeniedException) lors de l'appel de l'opération CompareFaces: Utilisateur: X n'est pas autorisé à effectuer: rekognition: CompareFaces Peut-être que j'ai besoin de vérifier mes clés, mais je voulais vérifier que le client est correctement configuré. – jensph

+1

@jensph Si vous utilisez boto3, vous pouvez spécifier la clé/secret/jeton/région en demandant un client ou en les spécifiant dans les variables d'environnement. Mes exemples de code supposent ce dernier. Il existe également [d'autres moyens de fournir des informations d'identification] (http://boto3.readthedocs.io/en/latest/guide/configuration.html). En ce qui concerne l'autre problème que vous rencontrez, il semble que votre stratégie IAM n'accorde pas l'accès à l'utilisation des ressources de 'rekognition'. – birryree