答案 0 :(得分:5)
问题在于您的滤波器的频率响应,
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))
作为附加说明,
filter
作为变量名,因为这样会以相同的名称遮盖内置函数。