2.2.1 小波系数的频域分布
小波系数的空间分布同原始图像的空间分布具有很好的对应关系(如图2-9所示)。LL频带是图像内容的缩略图,它是图像数据能量集中的频带。由于经过了小波系数的正规化处理,即等式的处理操作,所以系数的显示能看出图像的内容。而HL、LH和HH频带存放的是图像的细节信息,它们的关系如下:
l HL频带存放的是图像水平方向的高频信息,它反映了图像水平方向上的变化信息和边缘信息;
l LH频带存放的是图像竖直方向的高频信息,它反映了图像在竖直方向上的灰度变化信息和图像边缘信息;
l HH频带存放的是图像在对角线方向的高频信息,它反映了水平方向和竖直方向上图像灰度的综合变化信息,同时包含了少量的边缘信息。
2.2.2 基于小波变换的图像滤波处理
图像滤波处理是通过滤波器将指定频带的能量进行有效的衰减而对于需要保留的频带能量进行增强。传统基于傅立叶变换的图像滤波处理大都采用傅立叶变换后的频率域的乘法运算,但是傅立叶变换的计算量大,并且变换后的频谱与原始图像的相关性不强。
小波变换将原始图像和变换系数之间建立了十分好的相关性。所以,在滤波器的设计上,可以针对不同频带分别设计。例如,需要削弱图像水平方向上的毛刺或高频信息,可以通过处理HL频带的小波系数,而不必影像其他方向上的边缘信息。并且,对于多层小波变换而言,还能对不同分辨率级的小波系数进行单独的处理而达到设想的滤波效果。倘若是进行低通滤波,那么可以通过保留LL频带的数据,而将高频小波系数进行有效的衰减。
2.2.3 指纹图像低通滤波的实现及运行结果
本节将分析基于小波变换的低通滤波实现。
为了保持图像边缘信息以及充分利用小波变换的多分辨率特性,在编程中采用了3层小波变换。而进行滤波处理时,为了保持图像信息,可以选择去除下层高频带的小波系数,而保留上层高频带的小波系数,这样能达到较好的滤波效果。如果需要保留部分的边缘信息,也可以将高频带的小波系数进行衰减,而不去除它们。如图2-19所示,程序完成了图像低尺度下的低通滤波操作,去除了大量的图像高频边缘信息。
图2-18 图像的低通滤波
下面的函数实现了图像的低通滤波处理:
(1)函数描述: LPass_Filter实现小波变换的低通滤波,减少图像的边缘信息,使图像更加平滑
(2)函数参数:
unsigned char **pData:图像小波变换后的小波系数矩阵
int nHeight :图像属性参数,数值为原始图像的高度值
int nWidth :图像属性参数,数值为原始图像的宽度值
int nLayer :低通滤波器的滤波阶数,数值为小波变换的层数
(3)函数返回值:
函数无返回值,小波系数参数是利用指针进行调用
(4)函数代码
void CWFilter::LPass_Filter(short **pData, int nHeight, int nWidth, int nLayer, int scale)
{ short **spOriginData, **spTransData0, **spTransData1;
int iHeight = nHeight, iWidth = nWidth;
spOriginData = pData;
spTransData0 = new short *[nHeight];
spTransData1 = new short *[nHeight];
m_FilterData = new short * [nHeight];
for(int i = 0; i < nHeight; i ++)
{ spTransData0[i] = new short [nWidth];
spTransData1[i] = new short [nWidth];
m_FilterData[i] = new short [nWidth];
for(int j = 0; j < nWidth; j ++)
{ m_FilterData[i][j] = 0;
} }
CWvltTrans *Trans;
Trans->DWT_TriLayers(spOriginData, spTransData0, spTransData1, nHeight, nHeight/2, nWidth, nWidth/2, nLayer, 1.414);
for(i=0;i<(int)nHeight/(4*scale);i++)
{ for(int j=0;j<(int)nWidth/(4*scale);j++)
{ m_FilterData[i][j] = spTransData1[i][j];
}}
delete spTransData0;
delete spTransData1;
DWT_Inverse(iHeight, iWidth, 3);
}
滤波处理后的数据将通过指针传递给CWvltDoc,通过CWvltDoc::OnFilterBlur()函数完成最终滤波结果的显示。图2-20所示,定义了两个低通滤波的菜单,完成不同尺度的低通滤波效果。图2-21所示是“低通滤波1”的小波ID定义。
图2-19 菜单选项
图2-20 小波ID的定义
下面是函数CWvltDoc::OnFilterBlur()的编程实现。
void CWvltDoc::OnFilterBlur()
{ // TODO: Add your command handler code here
//读取数字图像的文件头,获取图像的属性参数
LPBITMAPINFOHEADER lpBitmapInfoHeader = (LPBITMAPINFOHEADER)(m_pBitmap+14);
LPBITMAPFILEHEADER lpBitmapFileHeader = (LPBITMAPFILEHEADER)m_pBitmap;
unsigned char *lpData = m_pBitmap + lpBitmapFileHeader->bfOffBits;
unsigned long biHeight = lpBitmapInfoHeader->biHeight;
unsigned long biWidth = lpBitmapInfoHeader->biWidth;
unsigned long biAlign = (biWidth*3+3)/4 *4;
unsigned long bmSize = biHeight * biAlign;
if(m_pTransfered==NULL) m_pTransfered=(unsigned char*) malloc (bmSize);
if(m_pTransfered==NULL)return; //图像小波系数的低通滤波层数为3层
int MaxLayer = 3;
short **ImgData;
float fTempBufforDisp; //图像矩阵坐标与图像数据
int tempR, tempG, tempB, x, y, cur; //分配图像数据的内存空间
ImgData = new short * [biHeight];
for(int i = 0; i < biHeight; i ++)
{ ImgData[i] = new short [biWidth];
} //获取显示缓存中的原始图像数据
for(y=0; y<(int)biHeight; y++)
{ for(x=0; x<(int)biWidth; x++)
{ cur = y*biAlign+3*x;
tempB=lpData[cur];
tempG=lpData[cur+1];
tempR=lpData[cur+2];
ImgData[biHeight-1-y][x]=(short)(0.3*tempR+0.59*tempG+0.11*tempB);
//no problem
}} //创建小波滤波器类
CWFilter Filter; //小波低通滤波处理
Filter.LPass_Filter(ImgData, biHeight, biWidth, MaxLayer, 1);
//屏蔽图像复原操作标志
m_bFilter = TRUE; //将处理后的图像数据放入显示缓存中
for(y=0; y<(int)biHeight; y++)
{ for(x=0; x<(int)biWidth; x++)
{ cur= y*biAlign+3*x; //当前像素的位置
m_pTransfered[cur] = (unsigned char)Filter.m_FilterData[biHeight - 1- y][x];
m_pTransfered[cur+1]= (unsigned char)Filter.m_FilterData[biHeight - 1 - y][x];
m_pTransfered[cur+2]= (unsigned char)Filter.m_FilterData[biHeight - 1 - y][x];
} } //显示图像
UpdateAllViews(NULL); //删除临时的图像数据空间
delete ImgData;}
运行结果如图2-21:
图2-21 图像的低通滤波
2.2.4 指纹图像的高通滤波及编程实现和运行结果
1、图像的高通滤波
图像的高通滤波类似于图像的低通滤波,通过对低频带小波系数的衰减处理,将图像的边缘信息突出。如果完全去除了图像LL频带的小波系数,那么将进行图像的边缘提取操作,如图2-22所示。
图2-22 去除LL小波系数的高通滤波处理
利用小波变换处理分频带的图像信息处理是十分容易的,通过改变各频带小波系数的幅值,或者是小波系数的相位信息均能完成很好的处理。这种边缘的处理只需要通过去除LL频带的小波系数,而保留高频带的小波系数,然后将处理后的结果进行逆变换便能完成。其思路与低通滤波非常相似。CWFilter::HPass_Filter()实现了这种边缘提取的滤波操作,CWvltDoc将图像数据传递给它,函数将处理后的逆变换结果返回。完成整个滤波处理的CWvltDoc函数是CWvltDoc::OnFilterSharpness(),其对应的菜单是“滤波处理→高通滤波1”
2、高通滤波的实现及程序、结果
如果将LL的小波系数进行有效的衰减,那么便起到图像锐化的效果。至于衰减的系数可以随实际应用进行调整,如果为了保证图像信息的不失真,也可以通过增强高频带小波系数的方法来实现。
下面的函数代码实现了图像锐化处理。
(1)函数描述:
HPass_Filter完成图像的高通滤波处理,得到图像的边缘信息。
(2)函数参数:
short **pData:二维指针,存放正则化后的小波系数
int nHeight:图像属性参数,数值为原始图像的高度值
int nHeight_H:图像属性参数,数值为原始图像高度值的一半
int nWidth:图像属性参数,数值为原始图像的宽度值
int nLayer:小波变换的层数
(3)函数返回值:
函数无返回值,小波系数参数是利用指针进行调用
(4)函数代码
void CWFilter::HPass_Filter2(short **pData, int nHeight, int nWidth,int nLayer)
{ short **spOriginData, **spTransData0, **spTransData1;
int iHeight = nHeight, iWidth = nWidth;
spOriginData = pData;
spTransData0 = new short *[nHeight];
spTransData1 = new short *[nHeight];
m_FilterData = new short * [nHeight];
for(int i = 0; i < nHeight; i ++)
{ spTransData0[i] = new short [nWidth];
spTransData1[i] = new short [nWidth];
m_FilterData[i] = new short [nWidth]; }
CWvltTrans *Trans;
Trans->DWT_TriLayers(spOriginData,spTransData0,spTransData1,nHeight,nHeight/2, nWidth, nWidth/2, nLayer, 1.414);
for(i = 0; i < nHeight; i ++)
{ for(int j = 0; j < nWidth ; j ++)
{ m_FilterData[i][j] = spTransData1[i][j];
if(i < nHeight / 8 && j < nWidth / 8) m_FilterData[i][j] /= 2;
}}
delete spTransData0;
delete spTransData1;
DWT_Inverse(iHeight, iWidth, 3);
}
该函数衰减了LL频带的小波系数:衰减为原来的1/2,而高频频带的小波系数不衰减,这样逆变换后,使得图像的边缘信息十分明显。CWFilter::HPass_Filter2()将逆变换后的数据传递给CWvltDoc,再通过CWvltDoc::OnFilterSharpness()来完成全部的操作,它所对应的菜单如图2-23所示,消息ID的定义如图2-24所示。