Visual+C++实现数字图像增强处理Word文件下载.docx
《Visual+C++实现数字图像增强处理Word文件下载.docx》由会员分享,可在线阅读,更多相关《Visual+C++实现数字图像增强处理Word文件下载.docx(12页珍藏版)》请在冰豆网上搜索。
pWnd=GetDlgItem(IDC_Graphic);
//得到ZFT对话框内的"
Frame"
控件的指针;
file:
//(IDC_Graphic为放置在对话框上的一个"
Picture"
控件,并讲类型设置为"
)。
pWnd->
GetClientRect(&
rect);
//得到"
控件窗口的"
视"
区域;
inti;
CPaintDCdc(pWnd);
控件的设备上下文;
//画直方图的x、y轴;
dc.MoveTo(0,rect.Height());
dc.LineTo(rect.Width(),rect.Height());
dc.LineTo(0,0);
//画直方图,num[]是"
的内部数组变量,存放的是图像各个灰度级出现的概率;
该数组的各个分量在 显示具体图像的直方图时设置;
for(i=0;
i<
256;
i++)//根据图像上的各个灰度级出现的概率,在坐标上对应的画出一根直线,从而各个表示各灰度级出现概率的直线构成了图像的直方图;
{
dc.MoveTo(i+1,rect.Height());
dc.LineTo(i+1,(rect.Height()-rect.Height()*num[i]*30));
file:
//此处num分量乘以"
30"
是为了放大个灰度级上对应的出现概率直线,增强显示效果;
}
////////////////////////////////////////////////////////
OnMouseMove(UINTnFlags,CPointpoint)
{//OnMouseMove函数处理鼠标消息,显示当前鼠标所在直方图上的灰度值等信息;
CWnd*pWnd,*pWndText;
//定义两个窗口对象;
CPointpoint1;
//定义个一个点对象;
point1=point;
//存放当前鼠标的位置信息;
//矩形对象;
CStringstring;
//字符串对象;
//得到显示直方图的框架窗口对象指针;
pWndText=GetDlgItem(IDC_NUM);
//得到指向文本框对象(IDC_NUM)窗口的指针;
GetWindowRect(&
//获取pWnd窗口对象窗口区域位置;
//屏幕坐标转换为客户区坐标;
ScreenToClient(&
//判断当前鼠标是否指在直方图内;
if(rect.PtInRect(point))
intx=point1.x-rect.left;
//当前鼠标位置减去区域的起始位置恰好为当前鼠标所指位置所表示的灰度级;
string.Format("
%d"
x);
//显示当前位置对应的图像的灰度级;
pWndText->
SetWindowText((LPCTSTR)string);
CDialog:
OnMouseMove(nFlags,point);
////////////////////////////////////////
voidCDibView:
OnImagehorgm()
file:
//在程序的"
类对象内处理显示图像直方图的函数;
CDibDoc*pDoc=GetDocument();
HDIBhdib;
hdib=pDoc->
GetHDIB();
BITMAPINFOHEADER*lpDIBHdr;
//位图信息头结构指针;
BYTE*lpDIBBits;
//指向位图像素灰度值的指针;
lpDIBHdr=(BITMAPINFOHEADER*)GlobalLock(hdib);
//得到图像的位图头信息
lpDIBBits=(BYTE*)lpDIBHdr+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD);
//获取图像像素值
ZFTdialog;
//直方图对话框模板对象;
inti,j;
intwImgWidth=lpDIBHdr->
biWidth;
intwImgHeight=lpDIBHdr->
biHeight;
//a[]数组用来存放各个灰度级出现的概率;
floata[256];
i++)//初始化数组;
{
a[i]=0;
}
//统计各个灰度级出现的次数;
WIMGHEIGHT;
I++)
for(j=0;
j<
WIMGWIDTH;
J++)
{
a[*(lpDIBBits+WIDTHBYTES(wImgWidth*8)*i+j)]++;
}
//统计各个灰度级出现的概率;
for(i=0;
i++)
a[i]=a[i]/(wImgHeight*wImgWidth);
//得到每个灰度级的出现概率;
memcpy(dialog.num,a,256*sizeof(float));
}
dialog.DoModal();
//显示直方图对话框;
return;
(a)LENA图像
(b)直方图
图一
上图为LENA的原始图像和其对应的直方图,在(b)图中的135表示当前鼠标在直方图中所指的位置对应的灰度级为135。
从该直方图可以看出,LENA图像的灰度主要分布在中高灰度级上,在低灰度级上图像的像素数几乎为零。
二、图像增强
影响系统图像清晰程度的因素很多,例如室外光照度不够均匀就会造成图像灰度过于集中;
由CCD(摄像头)获得的图像经过A/D(数/模转换,该功能在图像系统中由数字采集卡来实现)转换、线路传送都会产生噪声污染等等。
因此图像质量不可避免的降低了,轻者表现为图像不干净,难于看清细节;
重者表现为图像模糊不清,连概貌也看不出来。
因此,在对图像进行分析之前,必须要对图像质量进行改善,一般情况下改善的方法有两类:
图像增强和图像复原。
图像增强不考虑图像质量下降的原因,只将图像中感兴趣的特征有选择的突出,而衰减不需要的特征,它的目的主要是提高图像的可懂度。
图像增强的方法分为空域法和频域法两类,空域法主要是对图像中的各个像素点进行操作;
而频域法是在图像的某个变换域内,对图像进行操作,修改变换后的系数,例如付立叶变换、DCT变换等的系数,然后再进行反变换得到处理后的图像。
图像复原技术与增强技术不同,它需要了解图像质量下降的原因,首先要建立"
降质模型"
,再利用该模型,恢复原始图像。
本期讲座我们主要介绍各种增强技术在图象处理系统中的实际应用。
1.灰度变换
简单的说,灰度变换就是指对图像上各个像素点的灰度值x按某个函数T()变换到y。
例如为了提高图像的清晰度,需要将图像的灰度级整个范围或其中某一段(A,B)扩展或压缩到(A
,B
);
需要显示出图像的细节部分等都要求采用灰度变换方法。
灰度变换有时又被称为图像的对比度增强或对比度拉伸。
假定输入图像中的一个像素的灰度级为Z,经过T(Z)函数变换后输出图像对应的灰度级为Z
,其中要求Z和Z
都要在图像的灰度范围之内。
根据T()形式,可以将灰度变换分为线性变换和非线性变换。
具体应用中采用何种T(),需要根据变换的要求而定。
对于图像的灰度变换,我们这里介绍一种稍微复杂一点的方法,既直方图均衡化。
直方图均衡化是灰度变换的一个重要应用,广泛应用在图像增强处理中,它是以累计分布函数变换为基础的直方图修正法,可以产生一幅灰度级分布具有均匀概率密度的图像,扩展了像素的取值动态范围。
若像素点的原灰度为R,变换后的灰度为S,需要注意的是R、S是归一化后的灰度值,其灰度变换函数T()为:
S=T
(R);
k=0,1…,;
式中,
是第j级灰度值的概率,
是图像中j级灰度的像素总数,
是图像中灰度级的总数目,
是图象中像素的总数。
对变换后的S值取最靠近的一个灰度级的值,建立灰度级变换表,将原图像变换为直方图均衡的图像。
下面是实现图像直方图均衡化函数的源代码和效果图:
OnZftJh()
CClientDCpDC(this);
HDChDC=pDC.GetSafeHdc();
//获取当前设备上下文的句柄;
SetStretchBltMode(hDC,COLORONCOLOR);
floatp[256],p1[256],num[256];
inti,j,k;
i++)//清空三个数组;
{num[i]=0.0f;
p[i]=0.0f;
p1[i]=0.0f;
//num[]存放图象各个灰度级出现的次数;
intHeight=lpDIBHdr->
intWidth=lpDIBHdr->
HEIGHT;
for(j=30;
WIDTH-20;
num[*(lpDIBBits+WIDTHBYTES(Width*8)*i+j)]++;
//p[]存放图像各个灰度级的出现概率;
p[i]=num[i]/(Width*Height);
//p1[]存放各个灰度级之前的概率和,用于直方图变换;
{
for(k=0;
k<
=i;
k++)
p1[i]+=p[k];
//直方图变换;
{ *(lpDIBBits+WIDTHBYTES(Width*8)*i+j)=(BYTE)(p1[*(lpDIBBits+WIDTHBYTES(Width*8)*i+j)]*255+0.5);
StretchDIBits(hDC,0,0,lpDIBHdr->
biWidth,lpDIBHdr->
biHeight,0,0,
lpDIBHdr->
biHeight,
lpDIBBits,(LPBITMAPINFO)lpDIBHdr,
DIB_RGB_COLORS,
SRCCOPY);
//显示图像;
(a)LENA原图
(b)直方图均衡化后的效果图
(c)原始图象的直方图
(d)均衡化后的直方他图
图二
从上述效果图可以看出,经过直方图均衡化处理后,图像变的清晰了,从直方图来看,处理后的LENA的图像直方图分布更均匀了,在每个灰度级上图像都有像素点。
但是直方图均衡化存在着两个缺点:
1)变换后图像的灰度级减少,某些细节消失;
2)某些图像,如直方图有高峰,经处理后对比度不自然的过分增强。
为此M.Kamel和LianGuan等人从图像相邻像素一般高度相关这一事实出发,将灰度概率分布和空间相关性联系在一起,提出了用二维条件概率密度函数取代一维概率密度函数作为均衡化条件,很好的解决了这个问题,有兴趣的朋友可以参阅一些图像处理书籍和资料。
2.图像平滑
图像平滑主要是为了消除噪声。
噪声并不限于人眼所能看的见的失真和变形,有些噪声只有在进行图像处理时才可以发现。
图像的常见噪声主要有加性噪声、乘性噪声和量化噪声等。
图像中的噪声往往和信号交织在一起,尤其是乘性噪声,如果平滑不当,就会使图像本身的细节如边界轮廓、线条等变的模糊不清,如何既平滑掉噪声有尽量保持图像细节,是图像平滑主要研究的任务。
一般来说,图像的能量主要集中在其低频部分,噪声所在的频段主要在高频段,同时系统中所要提取的汽车边缘信息也主要集中在其高频部分,因此,如何去掉高频干扰又同时保持边缘信息,是我们研究的内容。
为了去除噪声,有必要对图像进行平滑,可以采用低通滤波的方法去除高频干扰。
图像平滑包括空域法和频域法两大类,在空域法中,图像平滑的常用方法是采用均值滤波或中值滤波,对于均值滤波,它是用一个有奇数点的滑动窗口在图像上滑动,将窗口中心点对应的图像像素点的灰度值用窗口内的各个点的灰度值的平均值代替,如果滑动窗口规定了在取均值过程中窗口各个像素点所占的权重,也就是各个像素点的系数,这时候就称为加权均值滤波;
对于中值滤波,对应的像素点的灰度值用窗口内的中间值代替。
实现均值或中值滤波时,为了简便编程工作,可以定义一个n*n的模板数组。
另外,读者需要注意一点,在用窗口扫描图像过程中,对于图像的四个边缘的像素点,可以不处理;
也可以用灰度值为"
的像素点扩展图像的边缘。
下面给出了采用加权均值滤波的图像平滑函数代码和效果图:
OnImagePh()
HANDLEdata1handle;
LPBITMAPINFOHEADERlpBi;
unsignedchar*hData;
unsignedchar*data;
BeginWaitCursor();
lpBi=(LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)hdib);
hData=(unsignedchar*)FindDIBBits((LPSTR)lpBi);
pDoc->
SetModifiedFlag(TRUE);
data1handle=GlobalAlloc(GMEM_SHARE,WIDTHBYTES(lpBi->
biWidth*8)*lpBi->
biHeight);
data=(unsignedchar*)GlobalLock((HGLOBAL)data1handle);
AfxGetApp()->
BeginWaitCursor();
inti,j,s,t,ms=1;
intsum=0,sumw=0;
intmask[3][3]={{1,1,1},{1,2,1},{1,1,1}};
//定义的3x3加权平滑模板;
ibiHeight;
i++)
for(j=0;
jbiWidth;
j++)
{
sumw=0;
sum=0;
for(s=(-ms);
s<
=ms;
s++)
for(t=(-ms);
t<
t++) if(((i+s)>
=0)&
&
((j+t)>
((i+s)biHeight)&
((j+t)biWidth))
sumw+=mask[1+s][1+t];
sum+=*(hData+(i+s)*WIDTHBYTES(lpBi->
biWidth*8)+(j+t))*mask[1+s][1+t];
if(sumw==0)sumw=1;
sum/=sumw;
if(sum>
255)sum=255;
if(sum<
0)sum=0;
*(data+i*WIDTHBYTES(lpBi->
biWidth*8)+j)=sum;
for(j=0;
jbiHeight;
j++)
ibiWidth;
i++) *(hData+i*WIDTHBYTES(lpBi->
biWidth*8)+j)=*(data+i*WIDTHBYTES(lpBi->
biWidth*8)+j);
StretchDIBits(hDC,0,0,lpBi->
biWidth,lpBi->
lpBi->
hData,(LPBITMAPINFO)lpBi,
(a)LENA原图
(b)平滑后的效果图
图三
中值或均值平滑有时处理图像的效果并不是很好,它虽然去除了一定的噪声,但同时使图像中的边缘变的模糊,这主要和所选取的窗口大小有关,为此下面介绍了一种既能保持边缘清晰又能消除噪声的方法,其算法如图四所示:
(a)
(b)
(c)
图四图像平滑模板
上图的含义是在图像中取5*5的区域,包含点(i,j)的五边形和六边形各四个,3*3的区域一个,计算这九个区域的标准差和灰度的平均值,取标准差最小区域的灰度平均值作为点(i,j)的灰度。
由于该算法的实现代码和上述代码大同小异,所以代码部分就不再赘述。
3.图像锐化
图像平滑往往使图像中的边界、轮廓变的模糊,为了减少这类不利效果的影响,这就需要利用图像鋭化技术,使图像的边缘变的清晰。
图像銳化处理的目的是为了使图像的边缘、轮廓线以及图像的细节变的清晰,经过平滑的图像变得模糊的根本原因是因为图像受到了平均或积分运算,因此可以对其进行逆运算(如微分运算)就可以使图像变的清晰。
从频率域来考虑,图像模糊的实质是因为其高频分量被衰减,因此可以用高通滤波器来使图像清晰。
为了要把图像中间任何方向伸展的的边缘和轮廓线变得清晰,我们希望对图像的某种运算是各向同性的。
可以证明偏导平方和的运算是各向同性的,既:
式中(
)是图像旋转前的坐标,(
)是图像旋转后的坐标。
梯度运算就是在这个式子的基础上开方得到的。
图像(x,y)点的梯度值:
为了突出物体的边缘,常常采用梯度值的改进算法,将图像各个点的梯度值与某一阈值作比较,如果大于阈值,该像素点的灰度用梯度值表示,否则用一个固定的灰度值表示。
我们在对图像增强的过程中,采用的是一种简单的高频滤波增强方法:
式中f,g分别为锐化前后的图像,
是与扩散效应有关的系数。
表示对图像f进行二次微分的拉普拉斯算子。
这表明不模糊的图像可以由模糊的图像减去乘上系数的模糊图像拉普拉斯算子来得到。
可以用下面的模板H={{1,4,1},{4,-20,4},{1,4,1}}来近似。
在具体实现时,上述模板H中的各个系数可以改变,
这个系数的选择也很重要,太大了会使图像的轮廓过冲,太小了则图像锐化不明显。
实验表明,
选取2-8之间往往可以达到比较满意的效果。
下面给出
等于4的情况下的实现代码和效果图:
OnMenuitem32785()
CClientDCpDC(this);
HDChDC=pDC.GetSafeHdc();
SetStretchBltMode(hDC,COLORONCOLOR);
CDibDoc*pDoc=GetDocument();
HDIBhdib;
hdib=pDoc->
BITMAPINFOHEADER*lpDIBHdr;
BYTE*lpD