为什么在 Matlab 中使用 ifft2 时图像会移动
Why image is shifted when using ifft2 in Matlab
我正在使用 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));
这是原图:
结果在这里:
为什么会这样?我该如何解决?请帮我。
非常感谢。
问题是你的滤波器的频率响应,
filter = fspecial('gaussian', 53, 3);
相对于坐标原点移位。要检查这一点,请使用
imagesc(filter)
您可以看到 filter
在坐标 27
、27
处有最大值,而不是 1
、1
。偏移量可以计算为 (size(filter)-1)/2
(对于奇数大小的脉冲响应),在本例中为 [26, 26]
.
下面以这张图片为例:
img = im2single(imread('cameraman.tif')); % size [256, 256]
稍后在您的代码中,当您使用可选的第二个和第三个参数调用 fft2
时,
mask = fft2(filter, size(img, 1), size(img, 2));
第一个输入隐式右填充,每个维度都用零来匹配指定的大小,在我的示例中是256
img
。您可以通过绘制其逆变换来检查这一点:
imagesc(real(ifft2(mask)))
之后,您的代码将原始图像的变换与滤波器的脉冲响应相乘,然后再变换回来。这相当于原始图像 img
和脉冲响应 filter
的 循环卷积 。现在,由于后者在两个维度上相对于原点移动 26
个样本,因此在输出信号中产生 循环移位 。 这就是您观察到的问题。
要解决此问题,您需要更正移位,同时考虑填充。
最简单的方法是手动进行填充(而不是让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
现在修正后的脉冲响应 filter_corrected
具有所需的大小,其最大值为 1
,1
(尽管在示例中很难观察到):
imagesc(filter_corrected)
因此您可以在其余代码中使用 filter_corrected
:
F = fft2(img);
mask = fft2(filter_corrected, size(img, 1), size(img, 2));
filtered_img = ifft2(F .* mask);
imshow(real(filtered_img));
有了这个,原图和过滤后的图就是
imshow(img)
figure
imshow(real(filtered_img))
作为补充说明,
- 观察过滤过程如何使图像的下半部分(摄影师的腿)"spill"进入上半部分。这是您用于过滤的方法的结果,即在 DFT 域中相乘,这对应于原始域中的 circular 卷积。
- 最好不要使用
filter
作为变量名,因为那样会掩盖同名的内置函数。
我正在使用 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));
这是原图:
结果在这里:
为什么会这样?我该如何解决?请帮我。 非常感谢。
问题是你的滤波器的频率响应,
filter = fspecial('gaussian', 53, 3);
相对于坐标原点移位。要检查这一点,请使用
imagesc(filter)
您可以看到 filter
在坐标 27
、27
处有最大值,而不是 1
、1
。偏移量可以计算为 (size(filter)-1)/2
(对于奇数大小的脉冲响应),在本例中为 [26, 26]
.
下面以这张图片为例:
img = im2single(imread('cameraman.tif')); % size [256, 256]
稍后在您的代码中,当您使用可选的第二个和第三个参数调用 fft2
时,
mask = fft2(filter, size(img, 1), size(img, 2));
第一个输入隐式右填充,每个维度都用零来匹配指定的大小,在我的示例中是256
img
。您可以通过绘制其逆变换来检查这一点:
imagesc(real(ifft2(mask)))
之后,您的代码将原始图像的变换与滤波器的脉冲响应相乘,然后再变换回来。这相当于原始图像 img
和脉冲响应 filter
的 循环卷积 。现在,由于后者在两个维度上相对于原点移动 26
个样本,因此在输出信号中产生 循环移位 。 这就是您观察到的问题。
要解决此问题,您需要更正移位,同时考虑填充。
最简单的方法是手动进行填充(而不是让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
现在修正后的脉冲响应 filter_corrected
具有所需的大小,其最大值为 1
,1
(尽管在示例中很难观察到):
imagesc(filter_corrected)
因此您可以在其余代码中使用 filter_corrected
:
F = fft2(img);
mask = fft2(filter_corrected, size(img, 1), size(img, 2));
filtered_img = ifft2(F .* mask);
imshow(real(filtered_img));
有了这个,原图和过滤后的图就是
imshow(img)
figure
imshow(real(filtered_img))
作为补充说明,
- 观察过滤过程如何使图像的下半部分(摄影师的腿)"spill"进入上半部分。这是您用于过滤的方法的结果,即在 DFT 域中相乘,这对应于原始域中的 circular 卷积。
- 最好不要使用
filter
作为变量名,因为那样会掩盖同名的内置函数。