Frequency domain filtering with scipy.fftpack, ifft2 does not give the desired result

Frequency domain filtering with scipy.fftpack, ifft2 does not give the desired result



I am trying to simply apply a Gaussian filter on a gray-scale input lena image in frequency domain with the following code and here is the wrong output I am getting:



enter image description here


from scipy import signal
from skimage.io import imread
import scipy.fftpack as fp
import matplotlib.pyplot as plt

im = imread('lena.jpg') # read lena gray-scale image
# create a 2D-gaussian kernel with the same size of the image
kernel = np.outer(signal.gaussian(im.shape[0], 5), signal.gaussian(im.shape[1], 5))

freq = fp.fftshift(fp.fft2(im))
freq_kernel = fp.fftshift(fp.fft2(kernel))
convolved = freq*freq_kernel # simply multiply in the frequency domain
im_out = fp.ifft2(fp.ifftshift(convolved)).real # output blurred image



enter image description here



However, if I do the same but use signal.fftconvolve I get the desired blurred image output as shown below:


signal.fftconvolve


im_out = signal.fftconvolve(im, kernel, mode='same') # output blurred image



enter image description here



My input image is 220x220, is there any padding issue? if so, how to solve it and make the first code (without fftconvolve) work? any help will be highly appreciated.


fftconvolve




1 Answer
1



First of all, there is no need to shift the result of the FFT just to shift it back before doing the IFFT. This just amounts to a lot of shifting they has no effect on the result. Multiplying the two arrays happens in the same way whether you shift them both or not.



The problem you noticed in your output is that the four quadrants are swapped. The reason this happens is because the filter is shifted by half its size, causing the same shift in the output.



Why is it shifted? Well, because the FFT puts the origin in the top-left corner of the image. This is not only true for the output of the FFT, but also for its input. Thus, you need to generate a kernel whose origin is at the top-left corner. How? Simply apply ifftshift to it before calling fft:


ifftshift


fft


freq = fp.fft2(im)
freq_kernel = fp.fft2(fp.ifftshift(kernel))
convolved = freq*freq_kernel
im_out = fp.ifft2(convolved).real



Note that ifftshift shifts the origin from the center to the top-left corner, whereas fftshift shifts it from the corner to the center.


ifftshift


fftshift





Great answer, thank you very much.
– Sandipan Dey
Jul 6 at 5:54






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)