Dev AWSome Day 2018の復習④ ~Amazon Rekognition編~
Dev AWSome Day 2018の復習④ ~Amazon Rekognition編~:
前回に続き、「Dev AWSome Day 2018」の復習として、「Amazon Rekognition」を勉強し直します。
今回ハンズオンで作成したサービスは、画像をアップロードし、AIで識別した結果を表示するものになります。
今回は、その裏側の処理であるAI部分の作成の説明になります。
処理の流れとしては、
※実は、Rekognitionは呼ぶだけになりますので、説明の中心はLambdaになります
DynamoDB は、どのような規模のデータも、スループットも満たすことができるフルマネージド型のNoSQL データベースです。
今回は、AWS CLIを使用して、DynamoDBの設定を行います。
まずテーブルの作成を行います。
「photo-table.json」に設定されている内容で、DynamoDBにテーブルを作成します。
「photo-table.json」の内容は以下のようになっています。
正常に作成されると、以下のように表示されます。
もちろん、マネージメントコンソールから作成することも可能です。
今回作成するLambda関数は、S3、DynamoDB、Rekognition、および、内部的にCloudWatch Logsにアクセスします。
それらの設定をIAMロールに登録します。
作成の仕方はこちらを参考にしてもらうとして、アクセス権限ポリシーをアタッチする画面で、以下の許可を行います。
まず、コード(Pythonで記述)をzipにまとめます。
次にデプロイします。
※「DevAWSomeImageLambda」は作成したLambda関数の名前です
なお、デプロイしたコードは以下のようになっています。
デプロイが正常に終了すると、以下のような表示になります。
次に、タイムアウトの値を20秒に変更します。
最後に、S3バケットに画像が登録されたら、そのイベント処理としてLambdaを実行するようにS3バケットの設定を追加します。
肝心のRekognitionを使っているところは、Lambda関数のコード内にあります。
今回はLambda関数からの呼び出し方、および、Lambda関数のアクセス制限の設定方法がメインとなっていました。
前回に続き、「Dev AWSome Day 2018」の復習として、「Amazon Rekognition」を勉強し直します。
今回ハンズオンで作成したサービスは、画像をアップロードし、AIで識別した結果を表示するものになります。
今回は、その裏側の処理であるAI部分の作成の説明になります。
処理の流れとしては、
- S3に画像ファイルが登録されると、
- それをLambdaが見つけ、
- Rekognitionに渡し、
- 結果を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」の内容は以下のようになっています。
{ "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関数の作成
- マネージメントコンソールを開く
- 「Lambda」を選択
- 「関数の作成」ボタンをクリック
- 「一から作成」を選択
- 「名前」を入力し、「ロール」は既存のロールを選択、「既存のロール」に先ほど作成したIAMロールを選択
- 「関数の作成」ボタンをクリック
まず、コード(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
なお、デプロイしたコードは以下のようになっています。
# 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": "" }
aws lambda update-function-configuration \ --function-name DevAWSomeImageLambda \ --region us-west-2 \ --timeout 20
イベントの設定
最後に、S3バケットに画像が登録されたら、そのイベント処理としてLambdaを実行するようにS3バケットの設定を追加します。- マネージメントコンソールを開く
- 「S3」を選択
- 前回作成したバケットを選択
- 「プロパティ」タブを選択
- 「Events」を選択
- 「通知の追加」を選択
- 「名前」を入力し、「イベント」で「Put」のみを選択、「送信先」で「Lambda関数」を選択、「Lambda」で先ほど作成したLambda関数名を選択
- 「保存」ボタンをクリック
まとめ
肝心のRekognitionを使っているところは、Lambda関数のコード内にあります。今回はLambda関数からの呼び出し方、および、Lambda関数のアクセス制限の設定方法がメインとなっていました。
コメント
コメントを投稿