直方图均衡化 图像处理程序设计vc_第1页
直方图均衡化 图像处理程序设计vc_第2页
直方图均衡化 图像处理程序设计vc_第3页
直方图均衡化 图像处理程序设计vc_第4页
直方图均衡化 图像处理程序设计vc_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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

6、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图像的打开在主框架菜单第一项中,系统有一默认的文件,其下拉框有打开,对其进行类向导,选择在CVc

9、view下,可观察到工作空间的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 和onIn

11、itdDalog分别写入代码,实现原图像的显示功能。步骤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,

12、"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,0xff

13、ffffff);/每次打开之前都要用白色刷一遍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 hereif(mdc=NULL) mdc=new CClientDC(this);if(mdr=NULL) mdr=new mdr

14、aw(0,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;R

15、eadBmp(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, SW

17、P_NOMOVE);(3) 显示直方图程序代码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.Do

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

19、eBox(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);for(i=0; i<255; i+) m_nHisti = 0;int k;for(i=0; i<dx; i+) for(j=0; j<dy; j+) lpSrc = (

20、unsigned char *)(buf + dx * j + i) ;/ 计数加1m_nHist*(lpSrc + 1 )+;return TRUE; / return TRUE unlessyou set the focus to a control / EXCEPTION: OCX Property Pages should return FALSEvoid ShowHist:OnPaint() CPaintDC dc(this); / device context for painting/ TODO: Add your message handler code here/ 循环变量i

21、nt i;/ 获取绘制直方图文本框的标签CWnd* pWnd = GetDlgItem(IDC_Show_Hist);/获得控件的句柄/ 获取设备上下文CDC* pDC = pWnd->GetDC();pWnd->Invalidate();pWnd->UpdateWindow();pDC->Rectangle(0, 0, 400, 203);/画一个矩形从而当做画直方图的区域/ 创建画笔对象CPen* pPenRed = new CPen;/ 创建红色画笔(用于绘制坐标轴)pPenRed->CreatePen(PS_SOLID, 1, RGB(255,0,0);/

22、 选入红色画笔,并保存以前的画笔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.Format(&

23、quot;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(27

24、0, 184, strTemp);/ 绘制X轴刻度for (i = 0; i < 256; i += 5)if (i & 1) = 0)/偶数,即10的倍数pDC->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,

25、 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 = 0; i <= 255; i +)/ 判断是否大于当前最大值if (m_nHisti > lMaxCount)/ 更新最大值lMaxCount = m_nHisti;/ 输出最大计数值pDC->MoveTo(20, 25);pDC-&

26、gt;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.Format("lMaxCount=%d",lMaxCount);/Message

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

28、e pPenRed;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 *bu

29、f=new UINTdx*dy;ReadBmp(fname1,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

30、 p;/新的灰度出现的概率;public:ShowBalanHist(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 here

31、CString 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);/成功得到图片的宽高if(i=0) return false;UINT *buf = new UINTdx*dy;ReadBmp(fname,dx,dy,buf);grade(buf,dx,dy);in

32、t m_Hist256;for(i=0; i<256; i+) m_Histi = 0;/统计各个灰度值的像素,统计概率,累积概率,确定映射关系,直到获得新的直方统计图float N = dx * dy;/像素总数int N_ =256;/灰度级最大数for(i=0; i<dx; i+) for(j=0; j<dy; j+) lpSrc = (unsigned char *)(buf + dx * j + i) ;/ 计数加1m_Hist*(lpSrc + 1 )+;int sum=0;for(i=0; i<256; i+) sum+=m_Histi;/str.Form

33、at("%d", sum);/注:以上没有错/MessageBox(str);/str.Format("dx*dy=%d", dx*dy);/注:以上没有错/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;/统计某个灰度

34、级像素个数m_oldHisti.p = m_Histi / N;/某个灰度级的像素频率m_oldHisti.s = m_oldHisti.p + m_oldHisti-1.s;/累积概率m_oldHisti.t = (int)(m_oldHisti.s * (N_ - 1) + 0.5); /映射关系/根据映射关系计算新的灰度级对应的像素个数for(i=0; i<=255; i+) m_newHistm_oldHisti.t.n += m_oldHisti.n;/新的灰度级对应的像素的个数m_newHistm_oldHisti.t.p += m_oldHisti.p;/新的灰度级对应的像

35、素频率return TRUE; / return TRUE unless you set the focus to a control / EXCEPTION: OCX Property Pages should return FALSEvoid ShowBalanHist:OnPaint() CPaintDC dc(this); / device context for painting/ TODO: Add your message handler code here/ 循环变量int i;/ 获取绘制直方图文本框的标签CWnd* pWnd = GetDlgItem(IDC_SHOW_NE

36、W_HIST);/获得控件的句柄/ 获取设备上下文CDC* pDC = pWnd->GetDC();pWnd->Invalidate();pWnd->UpdateWindow();pDC->Rectangle(0, 0, 400, 203);/画一个矩形从而当做画直方图的区域/ 创建画笔对象CPen* pPenRed = new CPen;/ 创建红色画笔(用于绘制坐标轴)pPenRed->CreatePen(PS_SOLID, 1, RGB(255,0,0);/ 选入红色画笔,并保存以前的画笔CPen* pOldPen = pDC->SelectObjec

37、t(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);st

38、rTemp.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 < 256; i

39、+= 5)if (i & 1) = 0)/偶数,即10的倍数pDC->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(345,185);/ 绘制Y轴箭头pDC->MoveT

40、o(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 CPen;/ 创建蓝色画笔(用于绘制直方图)pPenBlue->CreatePen(PS_SOLID, 1, RGB(0,0,255);/ 选入蓝色画笔pDC->SelectObject(pP

41、enBlue);CString str;/ 判断是否存在计数值/在此处画均衡化后的直方图/ 计算最大计数值for (i = 0; i <= 255; i +)/ 判断是否大于当前最大值if (m_newHisti.n > lMaxCount)/ 更新最大值lMaxCount = m_newHisti.n;strTemp.Format("%d", lMaxCount);pDC->TextOut(11, 26, strTemp);/str.Format("lMaxCount=%d",lMaxCount);/MessageBox(str);if(lMaxCount > 0)/ 绘制直方图for (i = 0; i <= 255; i +)pDC->MoveTo(i + 20, 180);pDC->LineTo(i + 20, 180 - (int) (m_

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论