离散傅里叶变换是傅里叶变换在时域和频域上都呈现离散的形式,将时域信号的采样变换为在离散时间傅里叶变换(DTFT)频域的采样。在形式上,变换两端(时域和频域上)的序列是有限长的,而实际上这两组序列都应当被认为是离散周期信号的主值序列。即使对有限长的离散信号作DFT,也应当将其看作经过周期延拓成为周期信号再作变换。
对于二维图像求傅里叶变换,需要用到二维离散傅里叶变换,设尺寸为M*N的二维离散图像函数为:
快速傅里叶变换FFT并不是与傅里叶变换DFT不同的另一种变换,快速傅里叶变换是减少DFT运算次数的一种改进算法。它是对变换式进行一次次分解,使其成为若干小点数的组合,从而减少运算量。常用的FFT是以2为基数的,其长度N=2l。它的效率高,程序简单,使用非常方便,当要变换的序列长度不等于2的整数次方时,为了使用以2为基数的FFT,可以用末位补零的方法,使其长度延长至2的整数次方。
在数字图像处理中,常常需要将的原点移到频域的中心以便清楚地观察谱的情况。要做到这一点只需令:,则有:
因此若要将图像谱的原点从(0,0)移到图像的中心点(N/2,N/2)处,只要将乘上因子,然后进行傅立叶变换即可。
低通滤波是要保留图像中的低频分量而去除图像中的高频分量。图像中的边缘和噪声都对应图像频域中的高频部分,所以通过在频域中的低通滤波可以除去或消弱噪声影响并模糊边缘轮廓,与时域中的平滑方法效果类似。要实现低通滤波需要选一个合适的模板以得到消弱图像频率域的高频分量。高斯滤波器的二维函数为:
式中是距频率矩形中心的距离。是截止频率,图1给出不同值的滤波器径向剖面图。
图1不同值的滤波器径向剖面图
与此相对的,截止频率处在距频率矩形中心距离为值的高斯高通滤波器(GHPF)的传递函数由下式给出:
故可以使用原图像减去不同截止频率值的滤波图像后的GHPF锐化效果。
编写函数fftcenter()实现图像中心化变换,对比MATLAB自带的函数fftshift()处理后的图像,图像的亮度变暗。要注意中心化变换因子是与图像本身相乘,而不是和傅里叶变换后的矩阵相乘。对比中心化变换前后的傅里叶谱图可看出,图像的频谱幅度图的高亮部分搬移到频域的中心,傅里叶谱更加清晰。
使用fftcenter()实现图像中心化变换存在一个问题,就是图像乘以时,有一半的像素值变为负数,而MATLAB的图像输出灰度范围只有0到255,因此所有负数的点均变成黑色,造成中心化后的图像亮度变低。
调用自编函数spatial_filtering(A,to,B)对两个图像进行四则算术运算,其中A和B是两幅输入图像,同时规定B可以是一个常数。to是一个表示运算符号的形参。当to的值为‘*’时进行两幅图像的相乘运算。这里的乘法处理是直接计算两幅图像像素点的乘积,主要应用举例是图像的局部显示,广泛使用于图像的各种滤波算法。
编写函数lowpassFiltering()构造高斯低通滤波器,在滤波之前需要对输入图像进行填充,如图2所示。
图2将输入图像填充为P*Q尺寸的图像
图9显示了使用不同截止频率的高斯低通滤波器对图像滤波的效果。很明显当取20到40时可以取得更有意义的效果,因为低通滤波器的目的是尽可能地模糊更多的细节,而保留大的可识别特征。由于图像是在一个填充区域上实现滤波,故输出的图像边缘出现了渐变的黑色区域。
图10给出了用原图像减去不同截止频率的滤波图像后的锐化效果。可以看到在取较小的值的时候锐化效果更为明显。观察结果图像与课本图4.56中得到的高斯高通滤波结果图的差异,在取值相同的情况下,原图像减去滤波图像后的输出图像的边缘亮度要高于直接使用高斯滤波器的滤波图像。调整高斯低通滤波器变量,得到的减法锐化图像与图4.56(c)效果接近。
本实验使用冈萨雷斯主编数字图像处理第三版中的素材Fig4.41(a).jpg进行二维快速傅里叶变换、图像傅里叶频谱计算及高斯低通滤波器的设计与验证。
图3输入图像的二维幅度谱和相位谱
图4输入图像的三维幅度谱和相位谱
图5自编函数fftcenter()中心化后的傅里叶图谱,只有中间一亮点
图6中心化变换后的二维幅度谱(左图调用fftshift函数,右图使用了自己编写的程序)
图7中心化变换后图像的三维幅度谱和相位谱
图8使用自编函数中心化变换图像亮度变暗
由于自编函数fftcenter()导致图像输出变暗,因此在高斯滤波过程中选择调用MATLAB自带函数fftshift()进行中心化处理。以下给出不同截止频率D0的高斯滤波器对图像滤波后的效果:
图9使用不同截止频率D0的高斯滤波器对图像滤波后的效果
图10用原图像减去不同截止频率D0的滤波图像后的锐化效果
下面给出主要部分的MATLAB代码:
function imt = fftcenter(ima) % 图像中心化转换函数
[xs,ys] = size(ima);
for i = 1:xs
for j = 1:ys
imt(i,j) = ima(i,j)*power((-1),(i+j)) ;%输入图像每个像素点乘以(-1)^x+y因子
end
end
return
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 2-D FFT 程序包
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function proj04();
ima = imread('Fig4.41(a).jpg');
imshow(ima);
title('原始图像');
ima_f = fft2(ima); % 对图像ima求二维快速傅里叶变换
mod_ima = abs(ima_f) % 要求幅度谱,需对傅里叶变换求模
mod_ima_log = uint8(log2((mod_ima))) % 要求幅度谱需对FFT后得到的模取对数
phase_ima = atan2(imag(ima_f),real(ima_f)); % 求相位谱,arctan必须使用一个四象限反正切来计算,调用MATLAB的atan2函数
figure,subplot(1,2,1),imshow(mod_ima_log,[]); % []的作用是将mod_ima_log的最大最小值分别作为纯白255和纯黑0,中间值映射到0到255之间
title('输入图像的二维傅里叶幅度谱');
subplot(1,2,2),imshow(phase_ima,[]);
title('输入图像的二维傅里叶相位谱');
threeD_mod_ima_log = log2(mod_ima)+1;
[x1,y1] = size(threeD_mod_ima_log);
[a1,b1]=meshgrid(1:x1,1:y1); % 使用函数mesh绘制三维傅立叶图需要先进行meshgrid
figure,subplot(1,2,1),mesh(a1,b1,threeD_mod_ima_log);
shading interp; % 在网格片内采用颜色插值处理,使得三维表面图显得光滑
title('输入图像的三维傅里叶幅度谱');
[x2,y2] = size(phase_ima);
[a2,b2] = meshgrid(1:x2,1:y2); % 使用函数mesh绘制三维傅立叶图需要先进行meshgrid
subplot(1,2,2),mesh(a2,b2,phase_ima);
shading interp;
title('输入图像的三维傅里叶相位谱');
%
s = fftshift(ima_f); % 调用fftcenter函数实现图像的中心化变换(为了对比fftcenter)
mod_s = abs(s) % 要求幅度谱,需对傅里叶变换求模
mod_s_log = uint8(log2(mod_s)) % 要求幅度谱需对FFT后得到的模取对数
phase_s = atan2(imag(s),real(s)); % 求相位谱,arctan必须使用一个四象限反正切来计算,调用MATLAB的atan2函数
figure,imshow(mod_s_log,[]); % []的作用是将mod_ima_log的最大最小值分别作为纯白255和纯黑0,中间值映射到0到255之间
title('fftshift函数的中心变换图的二维傅里叶幅度谱');
imt = fftcenter(ima); % 调用自编函数对图像进行中心化变换
imt_f = fft2(imt); % 对中心化变换后的图像求二维傅里叶变换
figure,imshow(imt_f,[]);
title('使用自编函数fftcenter()中心变换图的二维傅里叶图谱');
mod_imt = abs(imt_f); % 要求幅度谱,需对傅里叶变换求模
mod_imt_log = uint8(log2(mod_imt)); % 要求幅度谱需对FFT后得到的模取对数
phase_imt = atan2(imag(imt_f),real(imt_f)); % 求相位谱,arctan必须使用一个四象限反正切来计算,调用MATLAB的atan2函数
figure,subplot(1,2,1),imshow(mod_imt_log,[ ]);
title('中心变换图的二维傅里叶幅度谱');
subplot(1,2,2),imshow(phase_imt,[]),
title('中心变换图的二维傅里叶相位谱');
%
threeD_mod_imt_log = log10(mod_imt)+1;
[x3,y3] = size(threeD_mod_imt_log);
[a3,b3]=meshgrid(1:x3,1:y3); % 使用函数mesh绘制三维傅立叶图需要先进行meshgrid
figure,subplot(1,2,1),mesh(a3,b3,threeD_mod_imt_log);
shading interp;
%figure,plot3((1:x),(1:y),ak); shading interp;
title('中心变换图的三维傅里叶幅度谱');
[x4,y4] = size(phase_imt);
[a4,b4] = meshgrid(1:x4,1:y4); % 使用函数mesh绘制三维傅立叶图需要先进行meshgrid
subplot(1,2,2),mesh(a4,b4,phase_imt);
shading interp;
title('中心变换图的三维傅里叶相位谱');
%
imt_if = ifft2(imt_f);
imt_if_abs = abs(imt_if);
figure,subplot(1,2,1),imshow(imt_if_abs,[]);
title('中心化变化图像');
ima = imread('Fig4.41(a).jpg');
subplot(1,2,2),imshow(ima);
title('原始图像');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 设计一个高斯滤波器
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function im=Lowpassfiltering()
st = imread('Fig4.41(a).jpg');
[M,N] = size(st);
D0 = 20; % 设定截止频率D0
x = 2*M;
y = 2*N;
% 进行高斯滤波之前先对图像进行填充,填充后的图像尺寸为(2M*2N)
for i=1:x
for j=1:y
if((i<=M)&&(j<=N))
st(i,j)=st(i,j);
else
st(i,j)=0;
end
end
end
figure,imshow(st);
title('对输入图像进行填充');
imwrite(st,'K1.jpg');
figure(2);
st = fftshift(fft2(st)); % 自编函数中心化效果有问题,因此调用fftshift函数实现中心化
for i = 1:x
for j = 1:y
D(i,j) = sqrt((i-M)^2+(j-N)^2); % 中心点为(M,N)
h(i,j) = 1*exp(-1/2*(D(i,j)^2/D0^2)); % 系统函数H(u,v)
st(i,j) = h(i,j)*st(i,j); % 滤波过程
end
end
st = fftshift(ifft2(st)); % 进行傅里叶反变换时再进行一次中心化
st_abs = abs(st);
for i=1:M
for j=1:N
st_k(i,j)=st_abs(i,j); % 对图像进行裁剪,去除填充部分
end
end
imshow(st_k,[])
title('GLPF滤波后的输出图像(已裁剪)');
st_k1 = imread('Fig4.41(a).jpg');
for i=1:M
for j=1:N
st_k2(i,j) = st_k1(i,j) - ( st_k(i,j)); % 原始图像减去GLPF图像,得到锐化图像
end
end
figure,imshow(st_k2,[])
title('原始图像减去GLPF滤波图像后的锐化图像');