LoginSignup
0

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-11-02

前回に続き、「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関数のアクセス制限の設定方法がメインとなっていました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0