Home > Back-end >  How to calculate pixel area of an image in Lambda from an S3 bucket?
How to calculate pixel area of an image in Lambda from an S3 bucket?

Time:01-21

I am trying to calculate the pixel area of images uploaded to a bucket in S3. So far, I have managed to put a trigger on my Lambda function in response to an image upload in S3, I have also managed to add all the necessary libraries.

To read the image loaded into the bucket I used the key inside cv2.imread(), but in doing so I got a path integrity warning.

warning

[ WARN:[email protected]] global /io/opencv/modules/imgcodecs/src/loadsave.cpp
(239) findDecoder imread_('public/IMG-10.jpg'):
can't open/read file: check file path/integrity

lambda_function.py

import boto3
import base64
import numpy as np
import cv2

s3_client = boto3.client('s3')


def lambda_handler(event, context):
    print(event)


    # getting bucket and object key from event object
    source_bucket = event['Records'][0]['s3']['bucket']['name']
    key = event['Records'][0]['s3']['object']['key']

    # taking image from bucket to calculate pixel area
    image = cv2.imread(key)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray,0,255,cv2.THRESH_OTSU   cv2.THRESH_BINARY)[1]
    cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    total = 0

    for c in cnts:
        x,y,w,h = cv2.boundingRect(c)
        mask = np.zeros(image.shape, dtype=np.uint8)
        cv2.fillPoly(mask, [c], [255,255,255])
        mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
        pixels = cv2.countNonZero(mask)
        total  = pixels
        cv2.putText(image, '{}'.format(pixels), (x,y - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,255,255), 2)

    print(total)

My problem is how to correctly access the image path to be read via opencv.

CodePudding user response:

It's need to first establish a connection to S3, then download the image data, and finally decode the data with OpenCV.

Full sample code:

from io import BytesIO
import boto3
import base64
import numpy as np
import cv2


s3_client = boto3.client('s3')


def lambda_handler(event, context):
    print(event)

    # getting bucket and object key from event object
    source_bucket = event['Records'][0]['s3']['bucket']['name']
    key = event['Records'][0]['s3']['object']['key']
    img_file = BytesIO()
    s3_client.download_fileobj(source_bucket, key, img_file)
        
    
    np_1d_array = np.frombuffer(img_file.getbuffer(), dtype="uint8")
    image = cv2.imdecode(np_1d_array, cv2.IMREAD_COLOR)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray,0,255,cv2.THRESH_OTSU   cv2.THRESH_BINARY)[1]
    cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    total = 0

    for c in cnts:
        x,y,w,h = cv2.boundingRect(c)
        mask = np.zeros(image.shape, dtype=np.uint8)
        cv2.fillPoly(mask, [c], [255,255,255])
        mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
        pixels = cv2.countNonZero(mask)
        total  = pixels
        cv2.putText(image, '{}'.format(pixels), (x,y - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,255,255), 2)

    print("ÁREA EM PIXEL:", total)

  • Related