使用 scipy.fftpack 进行频域滤波,ifft2 未给出所需的结果

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

我试图使用以下代码在频域中的灰度输入 lena 图像上简单地应用高斯滤波器,这是我得到的错误输出:

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

但是,如果我这样做但使用 signal.fftconvolve,我会得到所需的模糊图像输出,如下所示:

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

我的输入图像是 220x220,是否存在填充问题?如果是这样,如何解决它并使第一个代码(没有 fftconvolve)工作?任何帮助将不胜感激。

首先,在进行 IFFT 之前,无需将 FFT 的结果移回原来的位置。这只是大量的移动,它们对结果没有影响。无论您是否移动它们,都以相同的方式将两个数组相乘。

您在输出中注意到的问题是四个象限被交换了。发生这种情况的原因是因为过滤器移动了一半大小,导致输出发生相同的移动。

为什么要移动?嗯,因为 FFT 将原点放在图像的左上角。这不仅适用于 FFT 的输出,也适用于其输入。因此,您需要生成一个原点位于左上角的内核。如何?在 调用 fft:

之前,只需将 ifftshift 应用于
freq = fp.fft2(im)
freq_kernel = fp.fft2(fp.ifftshift(kernel))
convolved = freq*freq_kernel
im_out = fp.ifft2(convolved).real

请注意,ifftshift 将原点从中心移到左上角,而 fftshift 将原点从角移到中心。