'Image processing for blur detection

I am trying to detect blurred images. Thanks to this post, I managed to create a script using Fast Fourier Transform and so far it worked quite well. But for some photos, I am not able to get correct results.

When the background is almost as the same color than the objects from the front, I think my script is not able to give good result. Do you have any leads to correct this ? The picture I want to testResult : really burry according to my script

import cv2
import imutils
from PIL import Image as pilImg
from IPython.display import display
import numpy as np
from matplotlib import pyplot as plt

def detect_blur_fft(image, size=60, thresh=17, vis=False):
    """
    Detects blur by comparing the image to a blurred version of the image
    
    :param image: The image to detect blur in
    :param size: the dimension of the smaller square extracted from the image, defaults to 60 (optional)
    :param thresh: the lower this value, the more blur is acceptable, defaults to 17 (optional)
    :param vis: Whether or not to return a visualization of the detected blur points, defaults to False
    (optional)
    """
    # grab the dimensions of the image and use the dimensions to
    # derive the center (x, y)-coordinates
    (h, w) = image.shape
    (cX, cY) = (int(w / 2.0), int(h / 2.0))
    # compute the FFT to find the frequency transform, then shift
    # the zero frequency component (i.e., DC component located at
    # the top-left corner) to the center where it will be more
    # easy to analyze
    fft = np.fft.fft2(image)
    fftShift = np.fft.fftshift(fft)
    # check to see if we are visualizing our output
    if vis:
        # compute the magnitude spectrum of the transform
        magnitude = 20 * np.log(np.abs(fftShift))
        # display the original input image
        (fig, ax) = plt.subplots(1, 2, )
        ax[0].imshow(image, cmap="gray")
        ax[0].set_title("Input")
        ax[0].set_xticks([])
        ax[0].set_yticks([])
        # display the magnitude image
        ax[1].imshow(magnitude, cmap="gray")
        ax[1].set_title("Magnitude Spectrum")
        ax[1].set_xticks([])
        ax[1].set_yticks([])
        # show our plots
        plt.show()
    # zero-out the center of the FFT shift (i.e., remove low
    # frequencies), apply the inverse shift such that the DC
    # component once again becomes the top-left, and then apply
    # the inverse FFT
    fftShift[cY - size:cY + size, cX - size:cX + size] = 0
    fftShift = np.fft.ifftshift(fftShift)
    recon = np.fft.ifft2(fftShift)
    # compute the magnitude spectrum of the reconstructed image,
    # then compute the mean of the magnitude values
    magnitude = 20 * np.log(np.abs(recon))
    mean = np.mean(magnitude)
    # the image will be considered "blurry" if the mean value of the
    # magnitudes is less than the threshold value
    return (mean, mean <= thresh)

pathImg = "path to the image"
image = cv2.imread(pathImg)
# Resizing the image to 500 pixels in width.
image = imutils.resize(image, width= 500)
# Converting the image to gray scale.
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Using the FFT to detect blur.
(mean, blurry) = detect_blur_fft(gray, size=60)
image = np.dstack([gray] * 3)
# This is a conditional statement that will set the color to red if the image is blurry or green
color = (0, 0, 255) if blurry else (0, 255, 0)
text = "Blurry ({:.4f})" if blurry else "Not Blurry ({:.4f})"
text = text.format(mean)
# Adding text to the image.
cv2.putText(image, text, (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2)
print("[INFO] {}".format(text))
# show the output image
display(pilImg.fromarray(image))


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source