使用 Amazon RDS 和 DynamoDB 儲存 Amazon Rekognition 資料 - Amazon Rekognition

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 Amazon RDS 和 DynamoDB 儲存 Amazon Rekognition 資料

使用 Amazon Rekognition 的 API 時,請務必記住,API 操作不會儲存任何產生的標籤。您可以通過將這些標籤與相應映像的標識符儲存至資料庫中來儲存這些標籤。

本教學課程示範偵測標籤,並將這些偵測到的標籤儲存至資料庫。本教學中開發的範例應用程式會讀取 Amazon S3 儲存貯體呼叫 DetectLabel 這些映像中的映像,並將產生的標籤儲存在資料庫中。應用程式會根據您要使用的資料庫類型,將資料儲存在 Amazon RDS 資料庫執行個體或 DynamoDB 資料庫中。

您將使用適用於 Python 的AWS SDK 或本教學課程。您也可以查看 AWS 文件開發套件範例 GitHub 儲存庫,以取得更多 Python 教學課程。

先決條件

開始本教學課程之前,您需要安裝 Python 並完成設定 Python AWS SDK 所需的步驟。除此之外,請務必備妥:

建立 AWS 帳戶和 IAM 角色

已安裝 Python SDK (Boto3)

正確設定您的 AWS 存取憑證

建立的 Amazon S3 儲存貯體充滿映像

如果 使用 RDS 存儲資料,則建立 RDS 資料庫執行個體

在 Amazon S3 儲存貯體中的映像的標籤

首先編寫一個函數,該函數將在 Amazon S3 儲存貯體中獲取映像的名稱,然後檢索該映像。將顯示此映像以確認正確的映像正在傳遞給 DetectLabel 的呼叫,該呼叫也在函數中。

  1. 找到您想要使用的 Amazon S3 儲存貯體,並寫下其名稱。您將撥打這個 Amazon S3 儲存貯體的呼叫,並讀取其中的映像檔。確保您的儲存貯體包含一些要傳遞給 DetectLabel 操作的映像。

  2. 撰寫程式碼以連線到您的 Amazon S3 儲存貯體。您可以使用 Boto3 連接到 Amazon S3 資源,以從 Amazon S3 儲存貯體擷取映像。連線到 Amazon S3 資源之後,可以透過為儲存貯體方法提供您 Amazon S3 儲存貯體名稱来存取儲存貯體。連線到 Amazon S3 儲存貯體之後,可以使用物件方法從儲存貯體擷取映像。通過使用 Matplotlib,您可以使用此連接在處理映像時可視化映像。Boto3 也可用來連線至 Rekognition 使用者端。

    在下列程式碼中,將您所在的地區提供給 region_name 參數。您將傳遞 Amazon S3 儲存貯體名稱和映像名稱至 DetectLabels,其會傳回相應映像的標籤。僅從回應中選擇標籤後,將傳回映像的名稱和標籤。

    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
  3. 將此程式碼儲存於一個名為 get_images.py 的檔案中。

建立 Amazon DynamoDB 資料表

下列程式碼使用 Boto3 連線至 DynamoDB,並使用 DynamoDB CreateTable 方法建立名為映像的資料表。该資料表的複合主鍵包含分割區金鑰 (映像鍵) 與排序索引鍵 (標籤鍵)。映像鍵包含映像的名稱,而標籤鍵則儲存指定給該映像的標籤。

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 中。

  1. 您需要撰寫程式碼,以便將資料上傳至 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
  2. 我們之前建立的 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
  3. 您將使用第三個函數 (稱為 load_data ),將映像和標籤實際載入您建立的 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!!")
  4. 這是我們之前定義的三個函數被調用的地方,並執行操作。將上面定義的三個函數與下面的程式碼一起新增到 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!")

您剛剛使用 DetectLabel 為映像生成標籤,並將這些標籤儲存在 DynamoDB 執行個體中。確保您移除了在閱讀本教學課程時建立的所有資源。這樣可以防止您為未使用的資源收取費用。

在 Amazon RDS 中建立 MySQL 資料庫

在繼續進行之前,請確定您已完成 Amazon RDS 的設定程序,並使用 Amazon RDS 建立 MySQL 資料庫執行個體

下列程式碼會使用 PyMySQL 程式庫和 Amazon RDS 資料庫執行個體。其建立一個資料表來儲存映像的名稱以及與這些映像相關聯的標籤。Amazon RDS 會接收用於建立資料表和將資料插入資料表的命令。若要使用 Amazon RDS,您必須使用主機名稱、使用者名稱和密碼連接到 Amazon RDS 主機。您將透過向 PyMySQL 的 connect 函數提供這些引數,並建立游標的執行個體來連接到 Amazon RDS。

  1. 在下列程式碼中,將主機的值取代為 Amazon RDS 主機端點,並以與 Amazon RDS 執行個體關聯的主使用者名稱取代使用者的值。您還需要將密碼替換為主要使用者的主密碼。

    import pymysql host = "host-endpoint" user = "username" password = "master-password"
  2. 建立要插入映像和標籤資料的資料庫和資料表。透過執行並提交建立查詢來執行此操作。下面的程式碼建立一個資料庫。只執行一次此程式碼。

    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()
  3. 建立資料庫之後,您必須建立一個資料表來插入映像名稱和標籤。如要建立資料表,您首先將 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 資料庫中。

  1. 連線到 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
  2. 來自 DetectLabel 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
  3. 您將需要一個函數來插入映像名稱和標籤到您的資料表中。下面的函數執行插入查詢,並插入任何給定的一對映像名稱和標籤。

    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!")
  4. 最後,您必須執行上面定義的函數。在下列程式碼中,會收集儲存貯體中所有映像的名稱,並將其提供給呼叫 DetectLabels 的函數。之後,標籤和其套用的映像名稱會上傳到您的 Amazon RDS 資料庫。將上面定義的三個函數與下面的程式碼一起複製到 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 文件開發套件範例 GitHub 儲存庫。