I was wanting to brainstorm some simple ideas for ML/Vision type experiments. One of the first I came up with is that we take a whole lot of pictures with Tulip, so I thought - It would be useful to check if the image was blurry. Actually maybe this would be useful to be built into the camera widget itself ![]()
First off, what are your ideas for simple, very foundational ML/Vision/LLM experiments to try? ![]()
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
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 How to Create a Python Layer in Aws Lambda | by Rafael Campana | BRLink | Medium
Ok, so how do we figure out if an image is blurry or not? Luckily, this guy knows how
variation of the Laplacian
Make a little lambda function (add your lambda layers)
59 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


