Skip to content

DynamoDB

James A Henriquez edited this page Feb 19, 2024 · 15 revisions

Storing Amazon Rekognition information into DynamoDB

Amazon gives instructions for how to store Amazon Rekognition information onto DynamoDB, while it is not live video and instead images I believe some of this information will prove useful for getting our application to work.

Prerequisites

  • You will first need DynamoDB
  • Python SDK (Boto3)
  • S3 Buckets filled with the images
  • DynamoDB database instance to store the data

Lables for images in S3

In the example Amazon gives us, the S3 buckets are filled with images in which Amazon Rekognition will take the images within the buckets and give them labels (for example, "Flower", "Tree", "Train").

We are going to have to connect to this S3 bucket using boto3 (a python software development kit) to retrieve the image and then pass both the bucket and image name to DetectLabels. DetectLabels is one of the many actions Amazon Rekognition is capable of. So, we will take the image, run it through DetectLabels and in return recieve the image name and lable it was given.

(Example code given from Amazon)

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):

    s3 = boto3.resource('s3')
    bucket = s3.Bucket(name=bucket_name)
    Object = bucket.Object(image_name)

    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()


    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

Creating a DynamoDB Table

In order to create a table within Python, you will need to make a CreateTable method, this table will include a primary key containing a partition key called Image and a sort key called Labels. Image key will have the name of the image and Label key will contain the label accompanied with the image. The code only needs to be ran once to create the table.


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)

Uploading Data to Database

We will first have to upload the data to DynamoDB we create a function called get_images_name which will retrieve the names of the images from previous code and retrieve the names of each image.

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

We will then do the same thing with labels, associating each image with the respective label(s) they have recieved.

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

We then will take all this information and load it into the DynamoDB table.

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!!")

Then to bring them all working together we will run the code below.

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!")