Hello everyone, I hope you are doing great.
I have recently been reading some of the tutorials and experimenting with them until I hit a wall when I got to : OpenCV: Out-of-focus Deblur Filter
no matter how I tried I cant get the same output! could someone kindly point out where the issue is?
The problem should be fairly easy, create a PSF
, shift and take its dft
and calculate the Wiener deconvolution, and then apply it on the input image! However, I get a bad result, nowhere close to what is shown in the tutorial!
This is my code by the way:
def calculate_psf(size, r):
# create an array of zeros
kernel = np.zeros((size,size),dtype=np.float32) if not hasattr(size,'__iter__') else np.zeros(shape=tuple(size), dtype=np.float32)
cx,cy = kernel.shape[0]//2, kernel.shape[1]//2
# draw a circle at the center
cv2.circle(kernel, center=(cy,cx), radius=r, color=255, thickness=-1, lineType=cv2.LINE_8)
# now normalize the kernel
kernel /= np.sum(kernel)
return kernel
def calculate_weiner(psf, snr):
psf = np.fft.fftshift(psf)
# note the tutorial seems to use the psf real values only,
# while infact it should be the conjugate of psf! I however
# am following the tutorial anyway here
psf_mag = psf.real/(np.abs(psf)**2 + 1/snr)
# psf_mag = np.conj(psf)/(np.abs(psf)**2 + 1/snr)
return psf_mag
def filter2DFreq(img, H):
fft = np.fft.fftn(img.astype(np.float32))
result = np.multiply(fft,H)
ift = np.fft.ifftn(result)
return ift
img = cv2.imread('./img/blurred_letter.jpg',0)
# this is a bitwise operation in C++ that rounds down
# the number of rows and columns in the image to the nearest even number.
# its the same as doing
# img_size = (img.shape[0]//2 *2, img.shape[1]//2 * 2)
img_size = tuple(d&-2 for d in img.shape[:2])
# use the reported values in the tutorial which are r=53 and snr=5200
psf = calculate_psf(size=img_size, r=53)
fft_mag = calculate_weiner(psf, snr=5200)
img_out = filter2DFreq(img, fft_mag)
cv2.imshow('img',img)
cv2.imshow('img_out.real', img_out.real.clip(0,255).astype(np.uint8))
cv2.imshow('img_out normalized', cv2.normalize(img_out.real, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U))
cv2.imshow('kernel-psf', cv2.normalize(psf,None, 0,255,cv2.NORM_MINMAX,dtype=cv2.CV_8U))
and this is what I get: