Dev AWSome Day 2018の復習④ ~Amazon Rekognition編~

Dev AWSome Day 2018の復習④ ~Amazon Rekognition編~:

前回に続き、「Dev AWSome Day 2018」の復習として、「Amazon Rekognition」を勉強し直します。

今回ハンズオンで作成したサービスは、画像をアップロードし、AIで識別した結果を表示するものになります。

今回は、その裏側の処理であるAI部分の作成の説明になります。

処理の流れとしては、

  1. S3に画像ファイルが登録されると、
  2. それをLambdaが見つけ、
  3. Rekognitionに渡し、
  4. 結果をDynamoDBに登録する
といった感じになります。

※実は、Rekognitionは呼ぶだけになりますので、説明の中心はLambdaになります


DynamoDBの設定

DynamoDB は、どのような規模のデータも、スループットも満たすことができるフルマネージド型のNoSQL データベースです。

今回は、AWS CLIを使用して、DynamoDBの設定を行います。

まずテーブルの作成を行います。

> aws dynamodb create-table --cli-input-json file://./photos-table.json --region us-west-2 
「photo-table.json」に設定されている内容で、DynamoDBにテーブルを作成します。

「photo-table.json」の内容は以下のようになっています。

{ 
    "LocalSecondaryIndexes": [ 
        { 
            "IndexName": "username-updatetime-index",  
            "Projection": { 
                "ProjectionType": "ALL" 
            },  
            "KeySchema": [ 
                { 
                    "KeyType": "HASH",  
                    "AttributeName": "username" 
                },  
                { 
                    "KeyType": "RANGE",  
                    "AttributeName": "updatetime" 
                } 
            ] 
        } 
    ],  
    "AttributeDefinitions": [ 
        { 
            "AttributeName": "objectkey",  
            "AttributeType": "S" 
        },  
        { 
            "AttributeName": "updatetime",  
            "AttributeType": "S" 
        },  
        { 
            "AttributeName": "username",  
            "AttributeType": "S" 
        } 
    ],  
    "ProvisionedThroughput": { 
        "WriteCapacityUnits": 5,  
        "ReadCapacityUnits": 5 
    },  
    "TableName": "devawsome-photos",  
    "KeySchema": [ 
        { 
            "KeyType": "HASH",  
            "AttributeName": "username" 
        },  
        { 
            "KeyType": "RANGE",  
            "AttributeName": "objectkey" 
        } 
    ] 
} 
正常に作成されると、以下のように表示されます。

{ 
    "TableDescription": { 
        "TableArn": "arn:aws:dynamodb:us-west-2:212691234567:table/devawsome-photos", 
        "LocalSecondaryIndexes": [ 
        ~ 略 ~ 
        "ItemCount": 0, 
        "CreationDateTime": 1523425086.359 
    } 
} 
もちろん、マネージメントコンソールから作成することも可能です。


Lambda関数の作成


Lambda関数用のIAMロールの作成

今回作成するLambda関数は、S3、DynamoDB、Rekognition、および、内部的にCloudWatch Logsにアクセスします。

それらの設定をIAMロールに登録します。

作成の仕方はこちらを参考にしてもらうとして、アクセス権限ポリシーをアタッチする画面で、以下の許可を行います。

  • AmazonS3ReadOnlyAccess
  • AmazonDynamoDBFullAccess
  • AmazonRekognitionReadOnlyAccess
  • AWSLambdaBasicExecutionRole


Lambda関数の作成

  1. マネージメントコンソールを開く
  2. 「Lambda」を選択
    image.png

  3. 「関数の作成」ボタンをクリック
  4. 「一から作成」を選択
  5. 「名前」を入力し、「ロール」は既存のロールを選択、「既存のロール」に先ほど作成したIAMロールを選択
  6. 「関数の作成」ボタンをクリック
続いて、AWS CLIからコードをデプロイします。

まず、コード(Pythonで記述)をzipにまとめます。

> zip ImageLabel.zip lambda_function.py 
次にデプロイします。

aws lambda update-function-code \ 
  --function-name DevAWSomeImageLambda  \ 
  --zip-file fileb://ImageLabel.zip \ 
  --region us-west-2 
※「DevAWSomeImageLambda」は作成したLambda関数の名前です

なお、デプロイしたコードは以下のようになっています。

# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 
# 
# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except 
# in compliance with the License. A copy of the License is located at 
# 
# https://aws.amazon.com/apache-2-0/ 
# 
# or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, 
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 
# specific language governing permissions and limitations under the License. 
from __future__ import print_function 
import json 
import urllib 
import boto3 
from datetime import datetime 
 
s3 = boto3.client('s3') 
rek = boto3.client('rekognition') 
dynamodb = boto3.resource('dynamodb') 
 
def lambda_handler(event, context): 
    "Process upload event, get labels and update database" 
    bucket = event['Records'][0]["s3"]["bucket"]["name"] 
    key = event['Records'][0]["s3"]["object"]["key"] 
    key = urllib.parse.unquote(key); 
    print("Received event. Bucket: [%s], Key: [%s]" % (bucket, key)) 
 
    response = s3.head_object(Bucket=bucket, Key=key) 
    username =  response['Metadata']['username']; 
    description = response['Metadata']['description'] 
    print("username : %s" % username) 
    print("description : %s" % description) 
 
    response = rek.detect_labels( 
        Image={ 
            'S3Object': { 
                'Bucket': bucket, 
                'Name': key 
            } 
        }) 
    all_labels = [label['Name'] for label in response['Labels']] 
    csv_labels = ", ".join(all_labels) 
    print("Detect_labels finished. Key: [%s], Labels: [%s]" % (key, csv_labels)) 
 
    table    = dynamodb.Table('devawsome-photos') 
    response = table.put_item( 
        Item={ 
            'username': username, 
            'objectkey': key, 
            'description': description, 
            'labels': csv_labels, 
            'updatetime': datetime.now().strftime('%Y%m%d%H%M%S') 
        } 
    ) 
 
    return True 
 
# This is used for debugging, it will only execute when run locally 
if __name__ == "__main__": 
    # simulated sns event 
    fake_sns_event = { 
        "Records": [ 
            { 
                "EventSource": "aws:sns", 
                "EventVersion": "1.0", 
                "EventSubscriptionArn": "...", 
                "Sns": { 
                    "Message": """{\"Records\":[{\"eventVersion\":\"2.0\", 
                    \"eventSource\":\"aws:s3\",\"awsRegion\":\"us-west-2\", 
                    \"eventTime\":\"...\",\"eventName\":\"ObjectCreated:Put\", 
                    \"s3\":{\"bucket\":{\"name\":\"fake-bucket\"}, 
                    \"object\":{\"key\":\"photos/8d2567bc34013c97.png\"}}}]}""", 
                    "MessageAttributes": {} 
                } 
            } 
        ] 
    } 
    fake_context = [] 
    lambda_handler(fake_sns_event, fake_context) 
デプロイが正常に終了すると、以下のような表示になります。

{ 
    "TracingConfig": { 
        "Mode": "PassThrough" 
    }, 
    "CodeSha256": "DSR+YJAEAzDSnyeI/BTGFhzdXkoM3zAu1fhC5nqvSm0=", 
    ~ 途中略 ~ 
    "Handler": "lambda_function.lambda_handler", 
    "Runtime": "python3.6", 
    "Description": "" 
} 
次に、タイムアウトの値を20秒に変更します。

aws lambda update-function-configuration \ 
  --function-name DevAWSomeImageLambda  \ 
  --region us-west-2 \ 
  --timeout 20 


イベントの設定

最後に、S3バケットに画像が登録されたら、そのイベント処理としてLambdaを実行するようにS3バケットの設定を追加します。

  1. マネージメントコンソールを開く
  2. 「S3」を選択
  3. 前回作成したバケットを選択
  4. 「プロパティ」タブを選択
  5. 「Events」を選択
  6. 「通知の追加」を選択
  7. 「名前」を入力し、「イベント」で「Put」のみを選択、「送信先」で「Lambda関数」を選択、「Lambda」で先ほど作成したLambda関数名を選択
  8. 「保存」ボタンをクリック


まとめ

肝心のRekognitionを使っているところは、Lambda関数のコード内にあります。

今回はLambda関数からの呼び出し方、および、Lambda関数のアクセス制限の設定方法がメインとなっていました。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)