直方图均衡化图像管理程序设计.doc

上传人:小** 文档编号:3032189 上传时间:2020-06-23 格式:DOC 页数:33 大小:293.67KB
返回 下载 相关 举报
直方图均衡化图像管理程序设计.doc_第1页
第1页 / 共33页
直方图均衡化图像管理程序设计.doc_第2页
第2页 / 共33页
点击查看更多>>
资源描述

《直方图均衡化图像管理程序设计.doc》由会员分享,可在线阅读,更多相关《直方图均衡化图像管理程序设计.doc(33页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、.-目录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,这个条件保证了变换前后灰度值动态范围的一致性。 累积分布函数(cumulativ

6、e 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,新建工程MFC APP Wizardexe

8、.定义工程名称VC,确定在选择单文档模式完成,实现出单文档项目的建立。步骤2:主框架菜单的添加在VC的工作空间下方点Resources找到VC资源目录,从中看到Menu菜单项,点击打开。然后看到主框架,双击一项或查看属性在标明里面可以修改显示字符。按此次设计要求,在主框架一项上修改为图像处理,在其弹出打上勾,在弹出框里一次编辑“显示原图像”、“显示直方图”、“显示均衡化后直方图”、“显示直方图均衡化后的图像”。ID定义留到依次设计此command功能的定义,以防弄混。实现主框架菜单的添加。步骤3:BMP图像的打开在主框架菜单第一项中,系统有一默认的文件,其下拉框有打开,对其进行类向导,选择在C

9、Vcview下,可观察到工作空间的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下添加cpp和h文件。完成tools的

10、添加。此时需注意在程序开头打入include“tools.h”.从而实现图像BMP文件的打开。步骤4:显示原图像的功能实现在Menu中找到显示原图像这一command,首先定义ID为ID_XIAN_SHI,对其建立类向导如FileOpen。然后再其中写入代码。先可用MessageBox(“ok”)进行操作检验。成功后,建立dlg,在Resources中Dialog里插入对话框。将属性中标题改为显示原图,并建立类向导,生成新的class,定义名为XianShi,在其中添加OnPaint,OnInitDillog.此时对CVcview下的OnXianShi和XianShi下的onPaint 和on

11、InitdDalog分别写入代码,实现原图像的显示功能。步骤5:原图直方图的显示操作步骤如同步骤四,详细见后续代码。步骤6:均衡化后的直方图显示操作步骤如同步骤四,详细见后续代码。步骤7:显示均衡化之后的图像操作步骤如同步骤四,详细见后续代码。3 部分主要程序代码 (1) BMP图像文件的打开程序代码void CVCView:OnFileOpen() / TODO: Add your command handler code herechar filt220;strcpy(filt,BMP Files(*.bmp)|*.bmp;|);CFileDialog fd(true,bmp, NULL,

12、 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,0xffffffff);/每次打开之前都要用白色刷一遍mdr-write_v

13、ideo(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 hereif(mdc=NULL) mdc=new CClientDC(this);if(mdr=NULL) mdr=new mdraw(0,0,1000,600,mdc);else mdr-swap();/ Do

14、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(fname1,dx,dy,buf);Dlg.filename = fname1;Dlg.buf

15、 = 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); m_bitmap.Attach (hBitmap);CDC dcImage;if(!dcImage.C

16、reateCompatibleDC (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) 显示直方图程序代码void CVCView:OnShowHist() / TODO: Add your command

17、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;public:ShowHist(CWnd* pParent = NULL); / standard constructorint m_nHist256

18、;UINT *buf;CString filename;BOOL ShowHist:OnInitDialog() CDialog:OnInitDialog();/ TODO: Add extra initialization hereCString str;int i,j,dx,dy;unsigned char * lpSrc;CString fname = this-filename;/MessageBox(fname);i=GetBmpSize(fname,&dx,&dy);/str.Format(dx=%d,dy=%d,dx,dy);/MessageBox(str);/成功得到图片的宽高

19、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-Rectangle(0, 0, 400, 203);/画一个矩形从而当做画直方图的区域/ 创建画笔对象CPen* pPenRed = new CPen;/ 创建红色画笔(用于绘制坐标轴)pPen

20、Red-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, 180);/ 绘制X轴刻度值,x=20276+30,y=20180CString strTemp;strTemp.Format(0);pDC-TextOut(20, 184, strTemp);strTemp.For

21、mat(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, 184, strTemp);strTemp.Format(255);pDC-TextOut(270, 184, strTemp);/ 绘制X轴刻度for (i = 0; i MoveTo(i + 20, 180);pDC-LineTo(i + 2

22、0, 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(345,185);/ 绘制Y轴箭头pDC-MoveTo(20,20);pDC-LineTo(25,25);pDC-MoveTo(20,20);pDC-LineTo(15,25);/ 直方图中最大计数值LONG lMaxCount = 0;/ 计算最大计数值for (i =

23、 0; i lMaxCount)/ 更新最大值lMaxCount = m_nHisti;/ 输出最大计数值pDC-MoveTo(20, 25);pDC-LineTo(14, 25);strTemp.Format(%d, lMaxCount);pDC-TextOut(11, 26, strTemp);/ 声名画笔对象CPen* pPenBlue = new CPen;/ 创建蓝色画笔(用于绘制直方图)pPenBlue-CreatePen(PS_SOLID, 1, RGB(0,0,255);/ 选入蓝色画笔pDC-SelectObject(pPenBlue);CString str;/str.Fo

24、rmat(lMaxCount=%d,lMaxCount);/MessageBox(str);/ 判断是否存在计数值/str.Format(%d,%d, m_nHist100,m_nHist200);/MessageBox(str);/成功得到图片的宽高if(lMaxCount 0)/ 绘制直方图for (i = 0; i MoveTo(i + 20, 180);pDC-LineTo(i + 20, 180 - (int) (m_nHisti * 160 / lMaxCount);/ 恢复以前的画笔pDC-SelectObject(pOldPen);/ 删除新的画笔delete pPenRed;

25、delete pPenBlue;/ Do not call CDialog:OnPaint() for painting messages(4) 显示均衡化后的直方图程序代码ShowBalanHist dlg;void CVCView:OnShowBalanHist() / 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

26、,dx,dy,buf);dlg.filename = fname1;dlg.buf = buf;dlg.DoModal();delete buf;class ShowBalanHist : public CDialog/ Constructionstruct Old_DlgBal int k;/灰度级int n;/各个灰度级的像素个数float p;/当前的灰度级出现的概率float s;/当前的灰度级的累积概率int t;/映射关系;struct New_DlgBal int k;/新的灰度级int n;/相应的像素点个数float p;/新的灰度出现的概率;public:ShowBalan

27、Hist(CWnd* pParent = NULL); / standard constructorCString filename;/打开的图像的文件名UINT *buf;/内存缓冲区Old_DlgBal m_oldHist256;/旧的256个灰度值New_DlgBal m_newHist256;/新的256个灰度值 . .剩余部分系统已有省略.BOOL ShowBalanHist:OnInitDialog() CDialog:OnInitDialog();/ TODO: Add extra initialization hereCString str;int i,j,dx,dy;unsi

28、gned char * lpSrc;CString fname = this-filename;/MessageBox(fname);i = 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);int m_Hist256;for(i=0; i256; i+) m_Histi = 0;/统计各个灰度值的像素

29、,统计概率,累积概率,确定映射关系,直到获得新的直方统计图float N = dx * dy;/像素总数int N_ =256;/灰度级最大数for(i=0; idx; i+) for(j=0; jdy; j+) lpSrc = (unsigned char *)(buf + dx * j + i) ;/ 计数加1m_Hist*(lpSrc + 1 )+;int sum=0;for(i=0; i256; i+) sum+=m_Histi;/str.Format(%d, sum);/注:以上没有错/MessageBox(str);/str.Format(dx*dy=%d, dx*dy);/注:以

30、上没有错/MessageBox(str);m_oldHist0.n = m_Hist0;m_oldHist0.p = m_Hist0 / N; m_oldHist0.s = m_oldHist0.p;m_oldHist0.t = (int)(m_oldHist0.s * (N_ - 1) + 0.5);for(i=1; i=255; i+) m_oldHisti.n = m_Histi;/统计某个灰度级像素个数m_oldHisti.p = m_Histi / N;/某个灰度级的像素频率m_oldHisti.s = m_oldHisti.p + m_oldHisti-1.s;/累积概率m_old

31、Histi.t = (int)(m_oldHisti.s * (N_ - 1) + 0.5); /映射关系/根据映射关系计算新的灰度级对应的像素个数for(i=0; iGetDC();pWnd-Invalidate();pWnd-UpdateWindow();pDC-Rectangle(0, 0, 400, 203);/画一个矩形从而当做画直方图的区域/ 创建画笔对象CPen* pPenRed = new CPen;/ 创建红色画笔(用于绘制坐标轴)pPenRed-CreatePen(PS_SOLID, 1, RGB(255,0,0);/ 选入红色画笔,并保存以前的画笔CPen* pOldPe

32、n = pDC-SelectObject(pPenRed);/画直方图的坐标/ 绘制y轴pDC-MoveTo(20,20);pDC-LineTo(20, 180);/ 绘制x轴pDC-MoveTo(20,180);pDC-LineTo(350, 180);/ 绘制X轴刻度值,x=20276+30,y=20180CString strTemp;strTemp.Format(0);pDC-TextOut(20, 184, strTemp);strTemp.Format(50);pDC-TextOut(70, 184, strTemp);strTemp.Format(100);pDC-TextOut

33、(120, 184, strTemp);strTemp.Format(150);pDC-TextOut(170, 184, strTemp);strTemp.Format(200);pDC-TextOut(220, 184, 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, 18

34、2); /画横纵坐标的箭头 / 绘制X轴箭头pDC-MoveTo(350, 180);pDC-LineTo(345,175);pDC-MoveTo(350, 180);pDC-LineTo(345,185);/ 绘制Y轴箭头pDC-MoveTo(20,20);pDC-LineTo(25,25);pDC-MoveTo(20,20);pDC-LineTo(15,25);/ 直方图中最大计数值LONG lMaxCount = 0;/ 计算最大计数值/ 输出最大计数值pDC-MoveTo(20, 25);pDC-LineTo(14, 25);/ 声名画笔对象CPen* pPenBlue = new C

35、Pen;/ 创建蓝色画笔(用于绘制直方图)pPenBlue-CreatePen(PS_SOLID, 1, RGB(0,0,255);/ 选入蓝色画笔pDC-SelectObject(pPenBlue);CString str;/ 判断是否存在计数值/在此处画均衡化后的直方图/ 计算最大计数值for (i = 0; i lMaxCount)/ 更新最大值lMaxCount = m_newHisti.n;strTemp.Format(%d, lMaxCount);pDC-TextOut(11, 26, strTemp);/str.Format(lMaxCount=%d,lMaxCount);/Me

36、ssageBox(str);if(lMaxCount 0)/ 绘制直方图for (i = 0; i MoveTo(i + 20, 180);pDC-LineTo(i + 20, 180 - (int) (m_newHisti.n * 160 / lMaxCount);/ 恢复以前的画笔pDC-SelectObject(pOldPen);/ 删除新的画笔delete pPenRed;delete pPenBlue;/ Do not call CDialog:OnPaint() for painting messages(5) 显示直方图均衡化后图像void CVCView:OnHistBalan

37、() / TODO: Add your command handler code hereint i,j;int dx, dy;if(dlg.filename = ) MessageBox(请先对其进行直方图均衡化);return;i=GetBmpSize(fname1,&dx,&dy);if(i=0) return;UINT *buf=new UINTdx*dy;ReadBmp(fname1,dx,dy,buf);grade(buf,dx,dy);BYTE *gray;/指向像素的灰度级for(i=0; idx-1; i+) /一个像素一个像素的转换for(j=0; jwrite_video(0,0,dx,dy,buf);/显示图片mdr-swap();de

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 其他杂项

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com