我正在使用FFT实现2D卷积。这是我的代码:
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
个样本,因此在输出信号中产生circular shift。 This是您观察到的问题。
为解决这个问题,您需要在考虑填充的情况下纠正偏移。
最简单的方法是手动进行填充(而不是让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)
因此您可以在其余的代码中使用它:
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))
作为附加说明
,filter
作为变量名,因为这样会以相同的名称遮盖内置函数。