AWS python lambda Blur detection in an image for Tulip

I wanted to play with a bit of the opencv vision library, and use it for basic blur detection. This is what I came up with.

First up, trying to get a lambda layer for opencv

This guy has a video on it https://www.youtube.com/watch?v=Y2rWypy8OaM

Or, you can get a pre built one from here

https://github.com/076923/aws-lambda-python-opencv-layer/tree/master/python%203.9.16

I think you need to use opencv-python-headless-4.6.0.66.zip since 4.7 throws a opencv-aws-lambda-lib64-libz-so-1-version-zlib-1-2-9-not-found

And then why you are at it, create an imutils layer. I think the easiest method is the ec2 micro method with https://medium.com/brlink/how-to-create-a-python-layer-in-aws-lambda-287235215b79

Ok, so how do we figure out if an image is blurry or not? Luckily, this guy knows how

https://pyimagesearch.com/2015/09/07/blur-detection-with-opencv/

variation of the Laplacian

Make a little lambda function (add your lambda layers)

import boto3
import logging
import urllib3
import os
import numpy as np
import argparse
import cv2
import json

# Configure Logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# AWS Runtime Region
aws_runtime_region = os.environ['AWS_REGION']

# Argument Parsing
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument("-t", "--threshold", type=float, default=100.0,
    help="focus measures below this value are considered 'blurry'")
cmd_args = vars(arg_parser.parse_args())

def compute_laplacian_variance(image):
    return cv2.Laplacian(image, cv2.CV_64F).var()

def download_image(url):
    http_client = urllib3.PoolManager()
    try:
        response = http_client.request('GET', url)
        image_data = np.asarray(bytearray(response.data), dtype="uint8")
        return cv2.imdecode(image_data, cv2.IMREAD_COLOR)
    except Exception as error:
        logger.error(f"Error in downloading image: {error}")
        return None

def lambda_handler(event, context):
    logger.debug(f"Event: {event}")

    image_url = event.get("url")
    if not image_url:
        return {'statusCode': 400, 'body': json.dumps({'error': 'No URL provided'})}

    image = download_image(image_url)
    if image is None or not image.size:
        return {'statusCode': 400, 'body': json.dumps({'error': 'Failed to download image'})}

    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    laplacian_variance = compute_laplacian_variance(gray_image)

    logger.debug(f"Laplacian Variance: {laplacian_variance}")

    is_blurry = laplacian_variance < cmd_args["threshold"]
    is_blurry = bool(is_blurry) 
    if is_blurry:
        logger.debug("Image is blurry.")
    else:
        logger.debug("Image is not blurry.")

    return {'statusCode': 200, 'body': {'is_blurry': is_blurry}}

Create permissions, and then a postgres function to call it

CREATE OR REPLACE FUNCTION public.check_image_for_blur(url text)
 RETURNS boolean
 LANGUAGE plpgsql
AS $function$
declare
 
  create_json TEXT;
  response TEXT;
  is_blurry_boolean boolean;
  
begin
RAISE INFO 'Started';     
   
-- Create Json    
select
    into
    create_json row_to_json(t)
from
    (
    select
       url
       ) t;
       
SELECT into response payload FROM aws_lambda.invoke(aws_commons.create_lambda_function_arn('check-image-for-blur', 'us-east-1'),
create_json::json,'RequestResponse'
);
 
RAISE INFO 'response:%',response;
 
-- Parse the response to get is_blurry
select into is_blurry_boolean (response::json->'body'->>'is_blurry')::boolean;

-- Return the is_blurry boolean value
return is_blurry_boolean;
 
end;
$function$
;

Make your tulip function (use image_url as the input)

Then a trigger off a camera widget

Leave a comment