我需要在图像上应用简单的低通滤波器,但这需要在频域中完成。然而,最终结果是一个非常嘈杂的图像,表明我的过程在某处不正确。
我的思想轨迹已经
1)使图像居中(Testpatt)并应用2D FFT
tpa1 = size(Testpatt, 1); tpa2 = size(Testpatt, 2);
dTestpatt = double(Testpatt);
for i = 1:tpa1
for j = 1:tpa2
dTestpatt(i,j) = (dTestpatt(i,j))*(-1)^(i + j);
end
end
fftdTestpatt = fft2(dTestpatt);
2)生成低通滤波器并将其与傅立叶变换图像相乘(注意:低通滤波器需要在半径范围内为1的圆圈)
lowpfilter = zeros(tpa1, tpa2);
Do = 120;
for i = 1:tpa1
for j = 1:tpa2
if sqrt((i - tpa1/2)^2 + (j - tpa2/2)^2) <= Do
lowpfilter(i,j) = 1;
end
end
end
filteredmultip = lowpfilter*fftdTestpatt;
3)采用逆2D FFT的实部,并恢复居中。
filteredimagecent = real(ifft2(filteredmultip));
for i = 1:tpa1
for j = 1:tpa2
filteredimage(i,j) = (filteredimagecent(i,j))*(-1)^(i + j);
end
end
非常感谢任何帮助或评论。
答案 0 :(得分:9)
我很惊讶为什么这并没有给你一个错误,但你正在执行矩阵乘法,而不是频域中的逐元素乘法。回想一下,频域中的滤波需要两个变换信号的逐元素乘法,以在空间域中执行等效的covnvolution操作。您只需更改乘法语句,使其与元素相当:
filteredmultip = lowpfilter.*fftdTestpatt;
此外,请确保在显示之前将图像转换回与原始图像相同的数据类型。例如,如果您的图片为uint8
,则您希望使用im2uint8
进行转换。这主要用于显示目的和将图像写入文件。如果您在代码中将其保留为double
,则显示图像将显示为大部分为白色,因为显示double类型的图像假定值的范围来自[0,1]
。
作为旁注,我怀疑你没有得到错误的原因是因为你的图像和滤镜是方形的,所以矩阵乘法的尺寸是有效的。如果您决定在非方形图像上执行此操作,您肯定会收到错误。
您正在实施的是使用理想低通滤波器进行过滤,因此当您低通滤波器时,您将看到振铃效果。之所以如此,是因为这直接来自信号处理理论。它需要空间域中的大量(或相当无限......)数量的正弦曲线来实现频域中的硬边缘。请记住,FFT是根据正弦曲线分解信号。当您使用此低通滤波器来过滤图像时,这可视化为重建图像中的振铃,因为硬边需要大量的正弦曲线(因此振铃的事实)来创建它们。
为了向您展示这些效果,让我们演示一个示例图像。我将使用摄影师图像作为图像处理工具箱的一部分。如果我使用半径Do = 40
并运行您的代码(更正),这是原始图像,这是我在过滤后得到的:
正如你所看到的那样,非常糟糕。振铃来自频域中滤波器的硬边缘。当你离中心越来越远时,人们倾向于使用更加渐进的幅度减小。一个很好的例子是高斯模糊。你要做的是定义标准差,然后创建一个与代表2D高斯的图像大小相同的掩码。
回想一下,2D高斯可以表示为:
来源:Wikipedia
您只需遍历所有像素坐标并计算上述等式。因为你真的不需要这样做,所以我没有乘以前面的比例因子。因此,您可以使用此代码生成高斯蒙板,这与您的两个for
循环相同,但更多的是向量化。我定义了一个2D坐标网格,其尺寸与图像相同,然后针对图像中的每个位置运行等式。我们当然需要居中内核,因此您必须像使用之前的低通滤波代码一样在图像中间偏移。我还决定使用您的Do
变量作为标准偏差。
Do = 40;
[X,Y] = meshgrid(1:tpa2, 1:tpa1);
lowpfilter = exp(-((X - (tpa2/2)).^2 + (Y - (tpa1/2)).^2) / (2*Do*Do));
所以我们现在把它作为过滤器响应:
...当我过滤时,我得到:
与原始图像比较:
正如您所看到的,模糊效果要好得多。没有响。因此,当您过滤图像时,请确保避免过滤器中的硬边缘,因为这会在空间域中产生振铃伪影。
我还有一些建议可以帮助您快速运行此代码。
正如您从信号处理理论中已经知道的那样,如果您预先将图像中的像素值乘以(-1)^(i+j)
,其中(i,j)
是您要过滤的像素的空间位置,这会使您居中频域中的图像。我实际上会避免使用循环来执行此操作,然后先使用FFT 然后使图像居中。您可以使用名为fftshift
的函数为您执行居中。首先对图像进行FFT,然后在以下情况下调用此函数:
fftdTestpatt = fft2(dTestpatt);
fftdTestpatt = fftshift(fftdTestpatt); % Centre the FFT
我也会避免使用循环来生成过滤器。具体来说,对于具有理想滤波器的代码,请使用与高斯滤波器相同的逻辑替换代码。我们还可以删除sqrt
操作,并确保您与半径的平方进行比较,以避免任何不必要的计算:
[X,Y] = meshgrid(1:tpa2, 1:tpa1);
lowpfilter = (X - tpa1/2).^2 + (Y - tpa2/2).^2 <= Do^2;
lowpfilter = double(lowpfilter);
在上面的代码中特别注意元素功率操作(.^
)。最后一个语句很重要,因为我们需要将结果强制转换回double
,因为首先生成过滤器实际上会为您提供logical
类型。我们需要double
类型以确保FFT的精度得到遵守。
在您完成过滤后,再次乘以(-1)^(i+j)
即可完成过滤。使用FFT过滤后,使用相关的ifftshift
函数来查看图像:
filteredmultip = ifftshift(filteredmultip); % Uncentre first
filteredimage = real(ifft2(filteredmultip));