Drawing Rekognition Bounding Boxes on images

In the last post we the Raspberry pi to take a image when it detected motion and sent that to AWS Rekognition to find and print out everything that Rekognition found. In this post we are going to take that one step farther and draw and label all the bounding boxes that Rekognition sent back to us.


Boudning Boxes

I really really recommend reading AWS page on how these work, but i’ll give a very quick explanation. AWS will return 4 numbers. These number will be between 0 and 1, and will need to be multiplied by the image width or hight to get the pixel. For instance if you get 0.5 for the Left number of an image that is 700 pixel wide 0.5*700 = 350. The left of that start at pixel 350.

  • Left * image width– this is how many pixel from the 0 width pixel the bounding box starts at
  • Top * image height – this is how many pixel from the 0 height pixel the bounding box starts at (Left + top give you the top left corner)
  • Width * image width — this is the width of the bounding box
  • Height * image height — this is the height of the bounding box

Not every object has a bounding box, only when AWS find a specific instance of an object will it return a bounding box. So i use the following bit of code to go through each item Rekognition give us and check to see if it has a bounding box.

    def draw_bounding_box(self, results):
        for each in results['Labels']:
            if 'Instances' in each:
                for instance in each['Instances']:
                    if 'BoundingBox' in instance:
                        box = self.covert_bounding_box(instance['BoundingBox']['Left'],
                                                       instance['BoundingBox']['Top'],
                                                       instance['BoundingBox']['Width'],
                                                       instance['BoundingBox']['Height'])
                        con = str(each['Confidence']).split('.')[0]
                        label = each['Name'] + ": " + str(con) + '%'
                        self.draw_box(box, label)

If we have a bounding box i will call the following function covert_bounding_box to covert the numbers in to pixels.

    def covert_bounding_box(self, left, top, width, height):
        left_box = left * self.image_width
        top_box = top * self.image_height
        width_box = width * self.image_width
        height_box = height * self.image_height
        return [width_box, height_box, left_box, top_box]

Finally i’m going to use opencv (check here how to install) to draw the boxes on the image.

    def draw_box(self, box, label):
        imgData = cv2.imread(self.source_photo)
        imgHeight, imgWidth, _ = imgData.shape
        left = int(box[2])
        top = int(box[3])
        right = left + int(box[0])
        bottom = top + int(box[1])
        thick = (imgHeight + imgWidth) // 900
        color = (0,255,0)
        cv2.rectangle(imgData, (left, top), (right, bottom), color, thick)
        cv2.putText(imgData, label, (left, top - 12), 0, 1e-3 * imgHeight, color, 2)
        cv2.imwrite(self.source_photo, imgData)

This function does a lot so i’ll step through each line. This function get called once for each bounding box.
Line 2: We read in the image that the Raspberry pi took
Line 3: We get the image height and width
Line 4-7: We set the 4 corners of the bounding box
Line 8: I’m creating the thickness of the line by adding the image hight + width and doing a floor division // which return a whole number rounded down.
Line 9: I’m setting the Color to green
Line 10: This line draws the box
Line 11: This line write the labels above the box
Line 12: Write this to the image

You can view the entire source code here

Leave a comment

Blog at WordPress.com.

Up ↑