翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
Amazon RDS および DynamoDB で Amazon Rekognition データを保存する
Amazon Rekognition の API を使用する場合、API オペレーションは生成されたラベルを一切保存しないことを覚えておくことが重要です。これらのラベルは、それぞれのイメージの識別子と一緒にデータベースに登録することで保存できます。
このチュートリアルでは、ラベルを検出し、検出したラベルをデータベースに保存する方法を説明します。このチュートリアルで開発されたサンプルアプリケーションは、Amazon S3 バケットからイメージを読み取り、そのイメージに対して DetectLabels オペレーションを呼び出し、結果のラベルをデータベースに保存します。アプリケーションは、使用したいデータベースタイプに応じて、Amazon RDS データベースインスタンスまたは DynamoDB データベースのいずれかにデータを保存します。
AWS SDK for Python
トピック
前提条件
このチュートリアルを開始する前に、Python をインストールし、Python AWS SDK のセットアップ
Python SDK (Boto3) をインストールしました
Amazon S3 バケットを作成し、イメージで埋め尽くしました
RDS を使用してデータを保存する場合、RDS データベースインスタンスを作成した
Amazon S3 バケット内のイメージのラベルを取得する
まず、Amazon S3 バケットにあるイメージの名前を受け取り、そのイメージを取得する関数を作成します。このイメージは、正しいイメージが関数内の DetectLabels の呼び出しに渡されていることを確認するために表示されます。
-
使用したい Amazon S3 バケットを見つけ、名前を書き込みます。この Amazon S3 バケットを呼び出して、その中のイメージを読み取ります。DetectLabels オペレーションに渡すイメージがバケットに含まれていることを確認します。
-
Amazon S3 バケットに接続するためのコードを書き込みます。Boto3 を使用して Amazon S3 リソースに接続して、Amazon S3 バケットからイメージを取得できます。Amazon S3 リソースに接続したら、バケットメソッドに Amazon S3 バケット名を指定して、バケットにアクセスできます。Amazon S3 バケットに接続後、Object メソッドでバケットからイメージを取得します。Matplotlib を利用することで、この接続を使用してイメージを可視化することができます。Boto3 は、Rekognition クライアントへの接続にも使用されます。
以下のコードで、リージョンを region_name パラメータに指定します。DetectLabels に Amazon S3 バケット名とイメージ名を渡すと、対応するイメージのラベルが返されます。レスポンスからラベルのみを選択すると、イメージ名とラベルの両方が返されます。
import boto3 from io import BytesIO from matplotlib import pyplot as plt from matplotlib import image as mp_img boto3 = boto3.Session() def read_image_from_s3(bucket_name, image_name): # Connect to the S3 resource with Boto 3 # get bucket and find object matching image name s3 = boto3.resource('s3') bucket = s3.Bucket(name=bucket_name) Object = bucket.Object(image_name) # Downloading the image for display purposes, not necessary for detection of labels # You can comment this code out if you don't want to visualize the images file_name = Object.key file_stream = BytesIO() Object.download_fileobj(file_stream) img = mp_img.imread(file_stream, format="jpeg") plt.imshow(img) plt.show() # get the labels for the image by calling DetectLabels from Rekognition client = boto3.client('rekognition', region_name="region-name") response = client.detect_labels(Image={'S3Object': {'Bucket': bucket_name, 'Name': image_name}}, MaxLabels=10) print('Detected labels for ' + image_name) full_labels = response['Labels'] return file_name, full_labels
-
このコードを get_images.py というファイルに保存します。
Amazon DynamoDB テーブルを作成する
以下のコードでは、boto3 を使って DynamoDB に接続し、DynamoDB CreateTable
メソッドを使って、Images という名前のテーブルを作成しています。テーブルには、Image というパーティションキーおよび Labels というソートキーで構成されている複合プライマリキーがあります。Image キーにはイメージの名前が含まれ、Labels キーにはそのイメージに割り当てられたラベルが保存されます。
import boto3 def create_new_table(dynamodb=None): dynamodb = boto3.resource( 'dynamodb',) # Table defination table = dynamodb.create_table( TableName='Images', KeySchema=[ { 'AttributeName': 'Image', 'KeyType': 'HASH' # Partition key }, { 'AttributeName': 'Labels', 'KeyType': 'RANGE' # Sort key } ], AttributeDefinitions=[ { 'AttributeName': 'Image', 'AttributeType': 'S' }, { 'AttributeName': 'Labels', 'AttributeType': 'S' }, ], ProvisionedThroughput={ 'ReadCapacityUnits': 10, 'WriteCapacityUnits': 10 } ) return table if __name__ == '__main__': device_table = create_new_table() print("Status:", device_table.table_status)
このコードをエディタに保存し、一度実行すると DynamoDB テーブルが作成されます。
DynamoDB へのデータのアップロード
DynamoDB データベースが作成され、イメージのラベルを取得する関数ができたので、ラベルを DynamoDB に保存することができます。次のコードは、S3 バケット内のすべてのイメージを取得し、それらのラベルを取得し、データを DynamoDB に保存します。
-
DynamoDB にデータをアップロードするためのコードを書く必要があります。
get_image_names
という関数で Amazon S3 バケットに接続し、バケット内のすべてのイメージの名前をリストとして返します。このリストをread_image_from_S3
関数に渡すと、作成したget_images.py
ファイルからインポートされます。import boto3 import json from get_images import read_image_from_s3 boto3 = boto3.Session() def get_image_names(name_of_bucket): s3_resource = boto3.resource('s3') my_bucket = s3_resource.Bucket(name_of_bucket) file_list = [] for file in my_bucket.objects.all(): file_list.append(file.key) return file_list
-
先ほど作成した
read_image_from_S3
関数は、処理中のイメージの名前と、そのイメージに関連するラベルのディクショナリを返します。find_values
という関数は、レスポンスからラベルのみを取得するために使用されます。イメージの名前とそのラベルを DynamoDB テーブルにアップロードする準備が整いました。def find_values(id, json_repr): results = [] def _decode_dict(a_dict): try: results.append(a_dict[id]) except KeyError: pass return a_dict json.loads(json_repr, object_hook=_decode_dict) # Return value ignored. return results
-
load_data
という 3 番目の関数で、作成した DynamoDB テーブルにイメージとラベルを実際にロードします。def load_data(image_labels, dynamodb=None): if not dynamodb: dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('Images') print("Adding image details:", image_labels) table.put_item(Item=image_labels) print("Success!!")
-
ここでは、前回定義した 3 つの関数が呼び出され、オペレーションが実行されます。上記で定義した 3 つの関数を、以下のコードとともに Python ファイルに追加します。コードを実行します。
bucket = "bucket_name" file_list = get_image_names(bucket) for file in file_list: file_name = file print("Getting labels for " + file_name) image_name, image_labels = read_image_from_s3(bucket, file_name) image_json_string = json.dumps(image_labels, indent=4) labels=set(find_values("Name", image_json_string)) print("Labels found: " + str(labels)) labels_dict = {} print("Saving label data to database") labels_dict["Image"] = str(image_name) labels_dict["Labels"] = str(labels) print(labels_dict) load_data(labels_dict) print("Success!")
DetectLabels を使用してイメージのラベルを生成し、そのラベルを DynamoDB インスタンスに保存します。このチュートリアルの間に作成したリソースはすべて取り外しておいてください。これにより、使用していないリソースに課金されることを防ぐことができます。
Amazon RDS で MySQL データベースを作成する
先に進む前に、Amazon RDS の セットアップ手順 が完了し、Amazon RDS を使用して MySQL DB インスタンスを作成した ことを確認してください。
次のコードは、PyMySQLconnect
関数に与え、カーソルのインスタンスを作成することで、 Amazon RDS に接続することになります。
-
次のコードでは、ホストの値を Amazon RDS ホストエンドポイントに置き換え、ユーザーの値を Amazon RDS インスタンスに関連付けられたマスターユーザーネームに置き換えます。また、パスワードをメインユーザーのマスターパスワードに置き換える必要があります。
import pymysql host = "host-endpoint" user = "username" password = "master-password"
-
データベースと、イメージとラベルデータを挿入するテーブルを作成します。作成クエリを実行し、コミットすることで行います。次のコードでは、データベースを作成します。このコードは 1 回だけ実行してください。
conn = pymysql.connect(host=host, user=user, passwd=password) print(conn) cursor = conn.cursor() print("Connection successful") # run once create_query = "create database rekogDB1" print("Creation successful!") cursor.execute(create_query) cursor.connection.commit()
-
データベースを作成したら、イメージ名とラベルを挿入するテーブルを作成する必要があります。テーブルを作成するには、まず use SQL コマンドとデータベースの名前を
execute
関数に渡します。接続が完了すると、テーブルを作成するためのクエリが実行されます。次のコードは、データベースに接続し、image_id
というプライマリキーと、ラベルを保存するテキスト属性の両方を持つテーブルを作成します。先ほど定義したインポートと変数を使用し、このコードを実行してデータベースにテーブルを作成します。# connect to existing DB cursor.execute("use rekogDB1") cursor.execute("CREATE TABLE IF NOT EXISTS test_table(image_id VARCHAR (255) PRIMARY KEY, image_labels TEXT)") conn.commit() print("Table creation - Successful creation!")
Amazon RDS の MySQL テーブルへのデータのアップロード
Amazon RDS データベースとデータベースにテーブルを作成した後、イメージのラベルを取得し、それらのラベルを Amazon RDS データベースに保存することができます。
-
Amazon S3 バケットに接続し、バケット内のすべてのイメージの名前を取得します。これらのイメージ名は、先に作成した
read_image_from_s3
関数に渡され、すべてのイメージのラベルを取得します。次のコードは Amazon S3 バケットに接続し、バケット内のすべてのイメージのリストを返します。import pymysql from get_images import read_image_from_s3 import json import boto3 host = "host-endpoint" user = "username" password = "master-password" conn = pymysql.connect(host=host, user=user, passwd=password) print(conn) cursor = conn.cursor() print("Connection successful") def get_image_names(name_of_bucket): s3_resource = boto3.resource('s3') my_bucket = s3_resource.Bucket(name_of_bucket) file_list = [] for file in my_bucket.objects.all(): file_list.append(file.key) return file_list
-
DetectLabels API からのリスポンスにはラベル以外のものも含まれているため、ラベルの値のみを抽出する関数を記述するようにしてください。次の関数は、ラベルだけを集めたリストを返します。
def find_values(id, json_repr): results = [] def _decode_dict(a_dict): try: results.append(a_dict[id]) except KeyError: pass return a_dict json.loads(json_repr, object_hook=_decode_dict) # Return value ignored. return results
-
イメージ名とラベルをテーブルに挿入する関数が必要です。次の関数は、挿入クエリを実行し、与えられたイメージ名とラベルのペアを挿入します。
def upload_data(image_id, image_labels): # insert into db cursor.execute("use rekogDB1") query = "INSERT IGNORE INTO test_table(image_id, image_labels) VALUES (%s, %s)" values = (image_id, image_labels) cursor.execute(query, values) conn.commit() print("Insert successful!")
-
最後に、上で定義した関数を実行する必要があります。次のコードでは、バケット内のイメージすべての名前が収集され、DetectLabels を呼び出す関数に提供されます。その後、ラベルとラベルが適用されるイメージの名前が Amazon RDS データベースにアップロードされます。上記で定義した 3 つの関数を、以下のコードとともに Python ファイルにコピーします。Python ファイルを実行します。
bucket = "bucket-name" file_list = get_image_names(bucket) for file in file_list: file_name = file print("Getting labels for " + file_name) image_name, image_labels = read_image_from_s3(bucket, file_name) image_json = json.dumps(image_labels, indent=4) labels=set(find_values("Name", image_json)) print("Labels found: " + str(labels)) unique_labels=set(find_values("Name", image_json)) print(unique_labels) image_name_string = str(image_name) labels_string = str(unique_labels) upload_data(image_name_string, labels_string) print("Success!")
DetectLabels を使用してイメージのラベルを生成し、Amazon RDS を使用して MySQL データベースにそのラベルを保存しました。このチュートリアルの間に作成したリソースはすべて取り外しておいてください。これにより、使用していないリソースに課金されることを防ぐことができます。
その他の AWS マルチサービスの例については、 AWS 「Documentation SDK examples GitHub repository」を参照してください。