MATLAB中图像的高通巴特沃斯滤波器

Posted

技术标签:

【中文标题】MATLAB中图像的高通巴特沃斯滤波器【英文标题】:High Pass Butterworth Filter on images in MATLAB 【发布时间】:2015-07-28 11:36:16 【问题描述】:

出于图像过滤的目的,我需要在 MATLAB 中实现高通巴特沃斯滤波器。我已经实现了一个,但看起来它不起作用。这是我写的代码。谁能告诉我怎么了?

n=1;
d=50;
A=1.5;
im=imread('imagex.jpg');
h=size(im,1);
w=size(im,2);
[x y]=meshgrid(-floor(w/2):floor(w-1/2),-floor(h/2):floor(h-1/2));
hhp=(1./(d./(x.^2+y.^2).^0.5).^(2*n));
image_2Dfilter=fftshift(fft2(im));
Image_butterworth=image_2Dfilter;
imshow(Image_butterworth);
ifftshow(Image_butterworth);

【问题讨论】:

【参考方案1】:

一方面,没有这样的命令称为ifftshow。其次,你没有过滤任何东西。您所做的只是可视化图像的光谱。

就频谱的可视化而言,您现在的做法是非常危险的。一方面,您正在可视化每个空间频率分量的系数,这些空间频率分量本质上是复值。如果您想以对我们大多数人都有意义的方式可视化频谱,最好查看 幅度相位。但是,因为这是一个巴特沃斯滤波器,所以最好将其应用于滤波器的幅度。

您可以使用abs 函数找到频谱的幅度。即使你这样做了,如果你直接在幅度上做imshow,你会得到一个在中间除了处处为零的可视化。这是因为直流分量非常大,而其余频谱则相对较小。

让我给你看一个例子。这是作为图像处理工具箱一部分的摄影师图像:

im = imread('cameraman.tif');
figure;
imshow(im);

现在,让我们可视化频谱并确保 DC 分量位于图像的中心 - 您已经使用 fftshift 完成了此操作。 将图像投射到double 也是一个好主意,以确保数据的最佳精度。另外,请确保您应用abs 来查找大小:

fftim = fftshift(fft2(double(im)));
mag = abs(fftim);
figure;
imshow(mag, []);

如您所见,由于我提到的原因,它不是很有用。可视化图像光谱的更好方法通常是对光谱应用 log 变换。如果您想要去均值或去除均值,这也很有用,以便动态范围更适合显示。换句话说,您可以将幅度加 1,然后对幅度应用对数,以便更高的值逐渐减小。用哪个底都没关系,我就用log命令封装的自然对数吧:

figure;
imshow(log(1 + mag), []);

现在这好多了。现在我们将讨论您的过滤机制。您的巴特沃斯过滤器有点不正确。坐标的meshgrid 略有错误。结束区间的-1操作需要往外跑:

[x y]=meshgrid(-floor(w/2):floor(w/2)-1,-floor(h/2):floor(h/2)-1);

请记住,您正在定义一个关于图像中心的对称间隔,而您最初的定义是不正确的。我还想提一下,这看起来像一个高通滤波器,所以输出应该看起来像一个边缘检测。另外,巴特沃斯高通滤波器的定义是不正确的。频域滤波器的正确定义是:

D(u,v) 是频域图像中心的距离,Do 是截止距离,而B 是控制比例因子,用于控制在截止距离处所需的增益。 n 是过滤器的顺序。 Do 在您的情况下是 d = 50。在实践中,B = sqrt(2) - 1 使得在DoD(u,v) = 1 / sqrt(2) = 0.707 的截止距离处,这是在电子电路滤波器中最常见的 3 dB 截止频率。有时您会看到 B 为简单起见设置为 1,但通常将其设置为 B = sqrt(2) - 1

但是,您当前的代码没有进行任何过滤。要在频域中进行滤波,您只需将图像的频谱与滤波器本身的频谱相乘。这相当于空间域中的卷积。完成此操作后,您只需撤消对图像执行的fftshift,进行逆 FFT,然后消除由于数值不精确导致的任何虚部。另外,让我们转换为 uint8 以确保我们尊重原始图像类型。

可以这样做:

%// Your code with meshgrid fix
n=1;
d=50;
h=size(im,1);
w=size(im,2);
fftim = fftshift(fft2(double(im)));
[x y]=meshgrid(-floor(w/2):floor(w/2)-1,-floor(h/2):floor(h/2)-1);
%hhp=(1./(d./(x.^2+y.^2).^0.5).^(2*n));

%%%%%%// New code
B = sqrt(2) - 1; %// Define B
D = sqrt(x.^2 + y.^2); %// Define distance to centre
hhp = 1 ./ (1 + B * ((d ./ D).^(2 * n)));
out_spec_centre = fftim .* hhp;

%// Uncentre spectrum
out_spec = ifftshift(out_spec_centre);

%// Inverse FFT, get real components, and cast
out = uint8(real(ifft2(out_spec)));

%// Show image
imshow(out);

如果您想查看过滤后的光谱是什么样子,只需执行以下操作:

figure;
imshow(log(1 + abs(out_spec_centre)), []);

我们得到:

这是有道理的。您会看到,在光谱的中间,与光谱的外边缘相比,它稍微暗一些。这是因为使用高通巴特沃斯滤波器,您正在放大高频项,并且它被可视化为更高的强度。

现在,out 包含您过滤后的图像,我们终于得到了:

看起来不错的结果!但是,天真地将图像转换为uint8 会将任何负值截断为 0,并将任何大于 255 的正值截断为 255。因为这是一个边缘检测,所以您希望同时检测负转换和正转换......所以这是个好主意将规范化输出,使其范围为[0,1],然后在乘以255后使用uint8进行投射。这样,图像中的任何变化都不会显示为灰色的负面变化被可视化为黑暗和积极的变化被可视化为白色......所以你会做这样的事情:

%// Your code with meshgrid fix
n=1;
d=50;
h=size(im,1);
w=size(im,2);
fftim = fftshift(fft2(double(im)));
[x y]=meshgrid(-floor(w/2):floor(w/2)-1,-floor(h/2):floor(h/2)-1);
%hhp=(1./(d./(x.^2+y.^2).^0.5).^(2*n));

%%%%%%// New code
B = sqrt(2) - 1; %// Define B
D = sqrt(x.^2 + y.^2); %// Define distance to centre
hhp = 1 ./ (1 + B * ((d ./ D).^(2 * n)));
out_spec_centre = fftim .* hhp;

%// Uncentre spectrum
out_spec = ifftshift(out_spec_centre);

%// Inverse FFT, get real components
out = real(ifft2(out_spec));

%// Normalize and cast
out = (out - min(out(:))) / (max(out(:)) - min(out(:)));
out = uint8(255*out);

%// Show image
imshow(out);

我们得到这个:

【讨论】:

“可视化图像光谱的更好方法通常是对光谱应用对数变换。”或者贬低形象。此外,您还谈到了数值上的不精确性;永远不要像 D = (x.^2 + y.^2).^(0.5); 这样计算平方根,请改用函数 sqrt @Sheljohn 感谢您的建议。我会相应地编辑我的帖子。我快速阅读并注意到,如果我们确定要找到平方根,请使用调整后的 sqrt() 函数。否则,这将调用通用的幂函数,并且不会像使用 sqrt 那样精确。【参考方案2】:

我认为你应该工作有点不同

n=1;
D0=50; % change the name for d0, d is usuaally the (u²+v²)⁽1/2)

A=1.5; % normally the amplitude is 1

im=imread('cameraman.jpg');

[M,N]=size(im); % is easy to get the h and w like this

% compute the 2d fourier transform in order to multiply

F=fft2(double(im));

% compute your filter and do the meshgrid for your matrix but it is M*n, and get only the real part

u=0:(M-1);
v=0:(N-1);

idx=find(u>M/2);
u(idx)=u(idx)-M;
idy=find(v>N/2);
v(idy)=v(idy)-N;
[V,U]=meshgrid(v,u);
D=sqrt(U.^2+V.^2);
H =A * (1./(1 + (D0./D).^(2*n)));

% multiply element by element

G=H.*F;
g=real(ifft2(double(G)));
subplot(1,2,1); imshow(im); title('Input image');
subplot(1,2,2); imshow(g,[ ]); title('filtered image');

【讨论】:

这个高通滤波器的公式对吗?另一个答案似乎有不同的公式。

以上是关于MATLAB中图像的高通巴特沃斯滤波器的主要内容,如果未能解决你的问题,请参考以下文章

matlab巴特沃斯滤波器设计

如何级联两个二阶巴特沃斯滤波器

添加椒盐噪声并用巴特沃斯滤波器去噪matlab?

matlab 实现低通巴特沃斯滤波器切比雪夫1型/2型滤波器 和 椭圆滤波器

深入浅出matplotlib(106):使用巴特沃斯滤波器进行带通滤波和带阻滤波

巴特沃斯滤波器