'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 ?


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 |
|---|
