Getting distorted image when trying one of the sites tutorials

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:

source data please.

this might interest you:

also the dude (and the sausage) is called Wiener, not Weiner, but I digress

2 Likes

Here is the image I used, the one used in the tutorial :

I couldnt add it to the original post due to my account limitation

OK , I found the issue, the image posted on the tutorial page(the 640x480 one) is not the original image. this is the original image (6,016x4,000)!:


The image size has a direct impact on the parameters. the 640x480 image on the tutorial page seems too small and has lost too much information, so I couldnt get muct out of it, the best result I could get was using r=6 and snr around 100 or 200! I guess whereas for the original image r=15 and snr=5200 works well.