Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image MATLAB中图像的高通巴特沃斯滤波器_Image_Matlab_Image Processing_Filtering_Signal Processing - Fatal编程技术网

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

Image MATLAB中图像的高通巴特沃斯滤波器,image,matlab,image-processing,filtering,signal-processing,Image,Matlab,Image Processing,Filtering,Signal Processing,我需要在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

我需要在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);

首先,没有名为
ifftshow
的命令。其次,你没有过滤任何东西。你所做的就是可视化图像的光谱

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

您可以使用
abs
功能找到光谱的幅值。即使您这样做,如果您直接在震级上显示了
imshow
,除了中间的之外,您将得到一个处处为零的可视化效果。这是因为直流分量非常大,而光谱的其他部分相对较小

让我给你举个例子。这是图像处理工具箱中的摄影师图像:

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

现在,让我们将频谱可视化,并确保直流分量位于图像的中心-您已经使用
fftshift
完成了此操作。将图像投射到
双精度
也是一个好主意,以确保数据的最佳精度。此外,请确保应用
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
,因此在
Do
的截止距离处,
D(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);
我们得到这个:


我认为你应该做一些不同的工作

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');

高通滤波器的这个公式正确吗?另一个答案似乎有不同的公式。“可视化图像光谱的更好方法通常是对光谱应用对数变换。”或者贬低图像。此外,你还谈到了数值的不精确性;永远不要像这样计算平方根
D=(x.^2+y.^2)。^(0.5)
,改用函数
sqrt
。@Sheljohn谢谢你的建议