1、直方图均衡化 图像处理程序的设计vc+目录1 图像直方图均衡化设计11.1 设计要求11.2 基本原理11.3 设计方案及实现功能32 实现步骤33 部分主要程序代码44 运行结果及分析205 心得体会22参考文献231 图像直方图均衡化设计1.1 设计要求要求用VC+实现如下功能:(1)建立一个单文档的应用项目。(2)在主框架添加菜单“图像处理”,并在此菜单下添加如下子菜单“显示原图像”、“显示原图像的直方图”、“图像直方图均衡化”、“显示均衡化处理后的直方图”。(3)实现“显示原图像”功能,并以对话框的形式显示。(4)实现“显示原图像直方图”功能,并以对话框的形式显示。(5)实现“图像直方
2、图均衡化”功能、实现“显示均衡化处理后的直方图”功能,并以对话框的形式显示。1.2 基本原理 图像的直方图包含了丰富的图像信息,描述了图像的灰度级内容,反映了图像的灰度分布情况。图像直方图是图像处理中一种十分重要的图像分析工具,具有简单实用的特点,通过对图像的灰度值进行统计,可以得到一个一维离散的图像灰度统计、直方图函数。 直方图均衡化:图像对比度增强的方法可以分成两类:一类是直接对比度增强方法;另一类是间接对比度增强方法。直方图拉伸和直方图均衡化是两种最常见的间接对比度增强方法。直方图拉伸是通过对比度拉伸对直方图进行调整,从而“扩大”前景和背景灰度的差别,以达到增强对比度的目的,这种方法可以
3、利用线性或非线性的方法来实现;直方图均衡化则通过使用累积函数对灰度值进行“调整”以实现对比度的增强。 直方图均衡化处理的“中心思想”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。 缺点: 1)变换后图像的灰度级减少,某些细节消失; 2)某些图像,如直方图有高峰,经处理后对比度不自然的过分增强。 直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法。 这种方法通常用来增加许多图像的局部对比度
4、,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。 这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景杂讯的对比度并且降低有用信号的对比度。 直方图均衡化的基本思想是把原始
5、图的直方图变换为均匀分布的形式,这样就增加了象素灰度值的动态范围从而可达到增强图像整体对比度的效果。设原始图像在(x,y)处的灰度为f,而改变后的图像为g,则对图像增强的方法可表述为将在(x,y)处的灰度f映射为g。在灰度直方图均衡化处理中对图像的映射函数可定义为:g = EQ (f),这个映射函数EQ(f)必须满足两个条件(其中L为图像的灰度级数): (1)EQ(f)在0fL-1范围内是一个单值单增函数。这是为了保证增强处理没有打乱原始图像的灰度排列次序,原图各灰度级在变换后仍保持从黑到白(或从白到黑)的排列。 (2)对于0fL-1有0gL-1,这个条件保证了变换前后灰度值动态范围的一致性。
6、 累积分布函数(cumulative distribution function,CDF)即可以满足上述两个条件,并且通过该函数可以完成将原图像f的分布转换成g的均匀分布。此时的直方图均衡化映射函数为: gk = EQ(fk) = (ni/n) = pf(fi) , (k=0,1,2,L-1) 上述求和区间为0到k,根据该方程可以由源图像的各像素灰度值直接得到直方图均衡化后各像素的灰度值。在实际处理变换时,一般先对原始图像的灰度情况进行统计分析,并计算出原始直方图分布,然后根据计算出的累计直方图分布求出fk到gk的灰度映射关系。在重复上述步骤得到源图像所有灰度级到目标图像灰度级的映射关系后,按
7、照这个映射关系对源图像各点像素进行灰度转换,即可完成对源图的直方图均衡化。 1.3 设计方案及实现功能 利用Visual C+中提供的MFC框架设计一个简单的应用程序框架,具有图像显示,图像直方图均衡,直方图均衡后图像等菜单栏,再利用C+具有面向对象程序设计的性质,编写程序代码实现MFC框架中对应菜单栏中的图像处理的功能,即可得到一个简易的图像处理系统,达到课程考核题目的要求。本次课程考核设计了一个简单的图片处理系统,主要具有以对话框的形式显示原始图片(bmp格式)、显示原图像的直方图、图像直方图均衡化、显示均衡化处理后的直方图的功能。2 实现步骤步骤1:创建单文档应用项目 启动VC,新建工程
8、MFC APP Wizardexe.定义工程名称VC,确定在选择单文档模式完成,实现出单文档项目的建立。步骤2:主框架菜单的添加在VC的工作空间下方点Resources找到VC资源目录,从中看到Menu菜单项,点击打开。然后看到主框架,双击一项或查看属性在标明里面可以修改显示字符。按此次设计要求,在主框架一项上修改为图像处理,在其弹出打上勾,在弹出框里一次编辑“显示原图像”、“显示直方图”、“显示均衡化后直方图”、“显示直方图均衡化后的图像”。ID定义留到依次设计此command功能的定义,以防弄混。实现主框架菜单的添加。步骤3:BMP图像的打开在主框架菜单第一项中,系统有一默认的文件,其下拉
9、框有打开,对其进行类向导,选择在CVcview下,可观察到工作空间的class view中的CVcview下会出现ONFileOpend的类,由于应用OnPaint,此时在CVcview出点右键,Add windows Messsages Hander然后选择WM_PAINT,添加On paint,此时可对ONFileOpen和Onpaint写入代码实现BMP图像文件的打开。在完成写入代码的操作以后需将tools这一工具函数文件的、引入到工程中,先将tools,cpp与tool.h粘贴进入工程目录下,然后在工作空间中选择FileView一栏分别在SourcesFile和HeaderFile下添
10、加cpp和h文件。完成tools的添加。此时需注意在程序开头打入include“tools.h”.从而实现图像BMP文件的打开。步骤4:显示原图像的功能实现在Menu中找到显示原图像这一command,首先定义ID为ID_XIAN_SHI,对其建立类向导如FileOpen。然后再其中写入代码。先可用MessageBox(“ok”)进行操作检验。成功后,建立dlg,在Resources中Dialog里插入对话框。将属性中标题改为显示原图,并建立类向导,生成新的class,定义名为XianShi,在其中添加OnPaint,OnInitDillog.此时对CVcview下的OnXianShi和Xia
11、nShi下的onPaint 和onInitdDalog分别写入代码,实现原图像的显示功能。步骤5:原图直方图的显示操作步骤如同步骤四,详细见后续代码。步骤6:均衡化后的直方图显示操作步骤如同步骤四,详细见后续代码。步骤7:显示均衡化之后的图像操作步骤如同步骤四,详细见后续代码。3 部分主要程序代码 (1) BMP图像文件的打开程序代码void CVCView:OnFileOpen() / TODO: Add your command handler code here char filt220; strcpy(filt,BMP Files(*.bmp)|*.bmp;|); CFileDialo
12、g fd(true,bmp, NULL, OFN_FILEMUSTEXIST,filt,this); if(fd.DoModal()!=IDOK)return; CString fname=fd.GetPathName(); fname1 = fname; fname.MakeUpper(); int i,dx,dy; i=GetBmpSize(fname,&dx,&dy); if(i=0) return; UINT *buf=new UINTdx*dy; ReadBmp(fname,dx,dy,buf);/显示图 mdr-overlay_rect(0,0,1000,1000,0xffffff
13、ff); /每次打开之前都要用白色刷一遍 mdr-write_video(0,0,dx,dy,buf); mdr-swap(); delete buf; / TODO: Add your command handler code herevoid CVCView:OnPaint() CPaintDC dc(this); / device context for painting / TODO: Add your message handler code here if(mdc=NULL) mdc=new CClientDC(this); if(mdr=NULL) mdr=new mdraw(0
14、,0,1000,600,mdc); else mdr-swap(); / Do not call CView:OnPaint() for painting messages(2) 显示原图像程序代码void CVCView:OnXianShi() / TODO: Add your command handler code here /Dlg.DoModal(); XianShi Dlg;CString str; int i,dx,dy; i=GetBmpSize(fname1,&dx,&dy); if(i=0) return; UINT *buf=new UINTdx*dy; ReadBmp(
15、fname1,dx,dy,buf); Dlg.filename = fname1; Dlg.buf = buf; Dlg.DoModal(); delete buf;void XianShi:OnPaint() CPaintDC dc(this); CClientDC* pDC=new CClientDC(this); CBitmap m_bitmap; HBITMAP hBitmap=(HBITMAP)LoadImage(NULL,_T(filename),IMAGE_BITMAP, 0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE
16、); m_bitmap.Attach (hBitmap); CDC dcImage; if(!dcImage.CreateCompatibleDC (pDC) return; BITMAP bm; m_bitmap.GetBitmap (&bm); dcImage.SelectObject (&m_bitmap); pDC-BitBlt (0,0,bm.bmWidth ,bm.bmHeight ,&dcImage,0,0,SRCCOPY); this-SetWindowPos(NULL,NULL,NULL,bm.bmWidth+7,bm.bmHeight+30, SWP_NOMOVE);(3)
17、 显示直方图程序代码void CVCView:OnShowHist() / TODO: Add your command handler code here /MessageBox(ok); ShowHist Dlg; CString str; int i,dx,dy; i=GetBmpSize(fname1,&dx,&dy); if(i=0) return; UINT *buf=new UINTdx*dy; ReadBmp(fname1,dx,dy,buf); Dlg.filename = fname1; Dlg.buf = buf; Dlg.DoModal(); delete buf;pu
18、blic: ShowHist(CWnd* pParent = NULL); / standard constructor int m_nHist256; UINT *buf; CString filename;BOOL ShowHist:OnInitDialog() CDialog:OnInitDialog(); / TODO: Add extra initialization here CString str; int i,j,dx,dy; unsigned char * lpSrc; CString fname = this-filename; /MessageBox(fname); i=
19、GetBmpSize(fname,&dx,&dy); /str.Format(dx=%d,dy=%d,dx,dy); /MessageBox(str); /成功得到图片的宽高 if(i=0) return false; UINT *buf=new UINTdx*dy; ReadBmp(fname,dx,dy,buf); grade(buf,dx,dy); for(i=0; i255; i+) m_nHisti = 0; int k; for(i=0; idx; i+) for(j=0; jGetDC(); pWnd-Invalidate(); pWnd-UpdateWindow(); pDC-
20、Rectangle(0, 0, 400, 203); /画一个矩形从而当做画直方图的区域 / 创建画笔对象 CPen* pPenRed = new CPen; / 创建红色画笔(用于绘制坐标轴) pPenRed-CreatePen(PS_SOLID, 1, RGB(255,0,0); / 选入红色画笔,并保存以前的画笔 CPen* pOldPen = pDC-SelectObject(pPenRed);/画直方图的坐标 / 绘制y轴 pDC-MoveTo(20,20); pDC-LineTo(20, 180); / 绘制x轴 pDC-MoveTo(20,180); pDC-LineTo(350
21、, 180);/ 绘制X轴刻度值,x=20276+30,y=20180 CString strTemp; strTemp.Format(0); pDC-TextOut(20, 184, strTemp); strTemp.Format(50); pDC-TextOut(70, 184, strTemp); strTemp.Format(100); pDC-TextOut(120, 184, strTemp); strTemp.Format(150); pDC-TextOut(170, 184, strTemp); strTemp.Format(200); pDC-TextOut(220, 18
22、4, strTemp); strTemp.Format(255); pDC-TextOut(270, 184, strTemp); / 绘制X轴刻度 for (i = 0; i MoveTo(i + 20, 180); pDC-LineTo(i + 20, 184); else /奇数,即 5的奇数倍数 pDC-MoveTo(i + 20, 180); pDC-LineTo(i + 20, 182); /画横纵坐标的箭头 / 绘制X轴箭头 pDC-MoveTo(350, 180); pDC-LineTo(345,175); pDC-MoveTo(350, 180); pDC-LineTo(34
23、5,185); / 绘制Y轴箭头 pDC-MoveTo(20,20); pDC-LineTo(25,25); pDC-MoveTo(20,20); pDC-LineTo(15,25); / 直方图中最大计数值 LONG lMaxCount = 0; / 计算最大计数值 for (i = 0; i lMaxCount) / 更新最大值 lMaxCount = m_nHisti; / 输出最大计数值 pDC-MoveTo(20, 25); pDC-LineTo(14, 25); strTemp.Format(%d, lMaxCount); pDC-TextOut(11, 26, strTemp);
24、 / 声名画笔对象 CPen* pPenBlue = new CPen; / 创建蓝色画笔(用于绘制直方图) pPenBlue-CreatePen(PS_SOLID, 1, RGB(0,0,255); / 选入蓝色画笔 pDC-SelectObject(pPenBlue); CString str;/str.Format(lMaxCount=%d,lMaxCount); /MessageBox(str); / 判断是否存在计数值 /str.Format(%d,%d, m_nHist100,m_nHist200); /MessageBox(str); /成功得到图片的宽高 if(lMaxCoun
25、t 0) / 绘制直方图 for (i = 0; i MoveTo(i + 20, 180); pDC-LineTo(i + 20, 180 - (int) (m_nHisti * 160 / lMaxCount); / 恢复以前的画笔 pDC-SelectObject(pOldPen); / 删除新的画笔 delete pPenRed; delete pPenBlue; / Do not call CDialog:OnPaint() for painting messages(4) 显示均衡化后的直方图程序代码ShowBalanHist dlg;void CVCView:OnShowBala
26、nHist() / TODO: Add your command handler code here /MessageBox(ok); CString str; int i,dx,dy; i=GetBmpSize(fname1,&dx,&dy); if(i=0) return; UINT *buf=new UINTdx*dy; ReadBmp(fname1,dx,dy,buf); dlg.filename = fname1; dlg.buf = buf; dlg.DoModal(); delete buf;class ShowBalanHist : public CDialog/ Constr
27、uction struct Old_DlgBal int k; /灰度级 int n; /各个灰度级的像素个数 float p; /当前的灰度级出现的概率 float s; /当前的灰度级的累积概率 int t; /映射关系;struct New_DlgBal int k; /新的灰度级 int n; /相应的像素点个数 float p; /新的灰度出现的概率;public: ShowBalanHist(CWnd* pParent = NULL); / standard constructor CString filename; /打开的图像的文件名 UINT *buf; /内存缓冲区 Old_DlgBal m_oldHist256; /旧的256个灰度值 New_DlgBal m_newHist256; /新的256个灰度值
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1