在Matlab中使用ifft2时为什么会移动图像

Kha*_*ong 1 matlab signal-processing fft image-processing convolution

我正在使用FFT实现二维卷积。这是我的代码:

img = im2single(imread('dog.bmp'));
filter = fspecial('gaussian', 53, 3);
F = fft2(img);
mask = fft2(filter, size(img, 1), size(img, 2));
filtered_img = ifft2(F .* mask);
imshow(real(filtered_img));
Run Code Online (Sandbox Code Playgroud)

这是原始图像:

在此处输入图片说明

结果在这里: 在此处输入图片说明

为什么会这样?我该如何解决?请帮我。非常感谢。

Lui*_*ndo 5

问题是您的滤波器的频率响应

filter = fspecial('gaussian', 53, 3);

转移相对于坐标原点。要对此进行检查,请使用

imagesc(filter)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

你可以看到,filter有它在坐标最大2727而不是11。可以计算出偏移量(对于奇数大小的脉冲响应)为(size(filter)-1)/2,在这种情况下为[26, 26]

在下面,我将使用此图像作为示例:

img = im2single(imread('cameraman.tif')); % size [256, 256]
Run Code Online (Sandbox Code Playgroud)

在代码的后面,当您fft2使用可选的第二和第三个参数进行调用时,

mask = fft2(filter, size(img, 1), size(img, 2));

在第一个输入中,每个维都隐式地用零填充以匹配指定的大小,256在我的示例中img。您可以通过绘制其逆变换来检查它:

imagesc(real(ifft2(mask)))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


之后,您的代码将原始图像的变换与滤波器的脉冲响应相乘,然后变换回去。这等效于原始图像和脉冲响应的循环卷积。现在,由于后者在两个维度上都相对于原点偏移了样本,因此在输出信号中产生了圆形偏移是您观察到的问题。imgfilter26


要解决此问题,您需要在考虑填充的情况下更正偏移。

最简单的方法是手动进行填充(而不是fft2隐式地进行填充),同时(size(filter)-1)/2在每个维度上将样本循环左移:

filter_corrected = filter; % initiallize
filter_corrected(size(img, 1), size(img, 2)) = 0; % this right-pads with zeros
shift = (size(filter)-1)/2; % as seen above
filter_corrected = filter_corrected( ...
    mod((1:end)+shift(1)-1, end)+1, ...
    mod((1:end)+shift(2)-1, end)+1); % this undoes the circular shifting
Run Code Online (Sandbox Code Playgroud)

现在,校正后的脉冲响应filter_corrected拥有所需的大小,其最大值为11(尽管在示例中很难观察到):

imagesc(filter_corrected)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

因此,您可以filter_corrected在其余的代码中使用:

F = fft2(img);
mask = fft2(filter_corrected, size(img, 1), size(img, 2));
filtered_img = ifft2(F .* mask);
imshow(real(filtered_img));
Run Code Online (Sandbox Code Playgroud)

这样,原始图像和过滤后的图像

imshow(img)
figure
imshow(real(filtered_img))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

在此处输入图片说明


作为附加说明

  • 观察过滤过程如何使图像下部的一点(摄影师的双腿)“溢出”到上部。这是您用于过滤的方法的结果,即在DFT域中相乘,这对应于原始域中的循环卷积。
  • 最好不要将其filter用作变量名,因为这样会使内置函数具有相同的名称。