Detecting blurriness in a RGB image

Viewed 105

I want to detect blurriness in an image. For that, i am converting the RGB image to gray scale and convolve it with laplacian kernel and calculate the variance. If the variance is high, then image is focused and blurred otherwise. I have attached the ss of code snippet below. But i am getting an error. Please help me with this code. Below is the function that convolves the image and calculates variance :

def is_blur(image) :
   """
   This function convolves a grayscale image with
   laplacian kernel and calculates its variance.
   """
   #Laplacian kernel
   laplacian_kernel = np.array([[0,1,0],[1,-4,1],[0,1,0]])
   laplacian_kernel = tf.expand_dims(laplacian_kernel, 0)
   laplacian_kernel = tf.expand_dims(laplacian_kernel, 0)
   laplacian_kernel = tf.cast(laplacian_kernel, tf.float32)
   #Convolving image with laplacian kernel
   new_img = tf.nn.conv2d(image, laplacian_kernel, stride=[1, 1, 1, 1], padding="SAME")
   #Calculating variance
   img_var = tf.math.reduce_variance(new_img)
   return img_var

Below is the code to load images and call the above function :

from tqdm import tqdm
path = "/content/Data/Train/{0}/"
N_CLASSES = 43
blurness_list = []
for itr in tqdm(range(N_CLASSES)) :
   files = os.listdir(path.format(itr))
   for img in files :
      image_string = tf.io.read_file(path.format(itr) + img)
      #decoding image
      image = tf.image.decode_png(image_string, channels=3)
      #Converting image to grayscale
      image = tf.image.rgb_to_grayscale(image)
      # This will convert to float values in [0, 1]
      image = tf.image.convert_image_dtype(image, tf.float32)
      #Reshaping image since conv2d accepts a 4-d tensor.
      image = tf.reshape(image, shape=[1, image.shape[0], image.shape[1], 1])
      blurness_list.append(is_blur(image))

Below is the error that i am getting :

InvalidArgumentError: input depth must be evenly divisible by filter depth: 1 vs 3 [Op:Conv2D]

Please help me with this code.

1 Answers

This should be easy to fix: You are constructing your 2d 3x3 filter and are then inserting size-1 dimensions in the beginning via tf.expand_dims, presumably to make the filter 4d as is required by conv2d. However, conv2d needs filters to be width x height x in_channels x out_channels, i.e. the filter dimensions need to be at the end. This should fix it:

laplacian_kernel = np.array([[0,1,0],[1,-4,1],[0,1,0]])
laplacian_kernel = tf.expand_dims(laplacian_kernel, -1)
laplacian_kernel = tf.expand_dims(laplacian_kernel, -1)
laplacian_kernel = tf.cast(laplacian_kernel, tf.float32)

Alternatively, note that you can also do something like this:

laplacian_kernel = laplacian_kernel[..., None, None]

where None is used to insert axes.

Related