数字图像处理实验报告 直方图均衡化.docx
《数字图像处理实验报告 直方图均衡化.docx》由会员分享,可在线阅读,更多相关《数字图像处理实验报告 直方图均衡化.docx(15页珍藏版)》请在冰点文库上搜索。
数字图像处理实验报告直方图均衡化
课程设计
课程名称数字图像处理
题目名称直方图均衡化
学生学院信息工程学院
专业班级08级电信2班
学号3208002664
学生姓名陈慕仪
指导教师曹江中
2011年7月1日
设计题目:
直方图均衡化
1、直方图的理论基础:
(1)直方图概念:
灰度直方图表示图像中每种灰度出现的频率。
(2)直方图的作用:
反映一幅图像的灰度分布特性
(3)直方图的计算:
式中:
nk为图像中出现rk级灰度的像素数,n是图像像素总数,而nk/n即为频数。
2、设计目的:
产生一幅灰度级分布具有均匀概率密度的图像,扩展像素取值的动态范围,达到了图象增强的目的。
3、直方图均衡化的效果:
1)变换后直方图趋向平坦,灰级减少,灰度合并。
2)原始象含有象素数多的几个灰级间隔被拉大了,压缩的只是象素数少的几个灰度级,实际视觉能够接收的信息量大大地增强了,增加了图象的反差。
同时,也增加了图象的可视粒度。
4、离散情况下的直方图均衡化的算法:
A、列出原始图像的灰度级
B、统计各灰度级的像素数目
C、计算原始图像直方图各灰度级的频数
D、计算累积分布函数
F、应用以下公式计算映射后的输出图像的灰度级,P为输出图像灰度级的个数,其中INT为取整符号:
G、用的映射关系修改原始图像的灰度级,从而获得直方图近似为均匀分布的输出图像。
3、源程序代码
//cqxhistView.cpp:
implementationoftheCCqxhistViewclass
#include"stdafx.h"
#include"cqxhist.h"
#include"cqxhistDoc.h"
#include"cqxhistView.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//CCqxhistView
IMPLEMENT_DYNCREATE(CCqxhistView,CView)
BEGIN_MESSAGE_MAP(CCqxhistView,CView)
//{{AFX_MSG_MAP(CCqxhistView)
ON_COMMAND(ID_OPEN_IMAGE,OnOpenImage)
ON_COMMAND(ID_HIST_IMAGE,OnHistImage)
//}}AFX_MSG_MAP
//Standardprintingcommands
ON_COMMAND(ID_FILE_PRINT,CView:
:
OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT,CView:
:
OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW,CView:
:
OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CCqxhistViewconstruction/destruction
CCqxhistView:
:
CCqxhistView()
{
//TODO:
addconstructioncodehere
}
CCqxhistView:
:
~CCqxhistView()
{
}
BOOLCCqxhistView:
:
PreCreateWindow(CREATESTRUCT&cs)
{
//TODO:
ModifytheWindowclassorstylesherebymodifying
//theCREATESTRUCTcs
returnCView:
:
PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
//CCqxhistViewdrawing
voidCCqxhistView:
:
OnDraw(CDC*pDC)
{
CCqxhistDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
if(m_dib.m_bLoaded==true)//判断是否加载图像
{
//获取图像宽和高
intnw=m_dib.GetDIBWidth();
intnh=m_dib.GetDIBHeight();
//显示图像(具体的参数见CDIB类的该函数说明)
m_dib.ShowDIB(pDC,10,10,nw,nh,m_dib.m_pDIBData,m_dib.m_pBMI);
m_dib.ShowDIB(pDC,400,10,nw,nh,m_dib.m_pDumpDIBData,m_dib.m_pBMI);
}
if(m_bHist==true)
{
//绘制原图像的直方图
CStringstr;
intnh=m_dib.GetDIBHeight();
inti;
//画坐标轴
//绘制坐标轴
pDC->MoveTo(410,nh+20);//(410,nh+20)是直方图的左上角坐标
//垂直轴
pDC->LineTo(410,nh+200);//(410,nh+200)是直方图的左下角坐标
//水平轴
pDC->LineTo(710,nh+200);//(710,nh+200)是直方图的右下角坐标
//写X轴刻度值
str.Format("0");
pDC->TextOut(410,nh+200+10,str);
str.Format("50");
pDC->TextOut(460,nh+200+10,str);
str.Format("100");
pDC->TextOut(510,nh+200+10,str);
str.Format("150");
pDC->TextOut(560,nh+200+10,str);
str.Format("200");
pDC->TextOut(610,nh+200+10,str);
str.Format("255");
pDC->TextOut(665,nh+200+10,str);
//绘制X轴刻度
for(i=0;i<256;i+=25)
{
if((i&1)==0)
{
//10的倍数
pDC->MoveTo(i+10,nh+200-2);
pDC->LineTo(i+10,nh+200+2);
}
else
{
//10的倍数
pDC->MoveTo(i+10,nh+200-2);
pDC->LineTo(i+10,nh+200+2);
}
}
//绘制X轴箭头
pDC->MoveTo(705,nh+200-5);
pDC->LineTo(710,nh+200);
pDC->LineTo(705,nh+200+5);
//绘制y轴箭头
pDC->MoveTo(410,nh+20);
pDC->LineTo(405,nh+20+5);
pDC->MoveTo(410,nh+20);
pDC->LineTo(415,nh+20+5);
intmax=0;
for(i=0;i<256;i++)
if(m_yuan[i]>max)
max=m_yuan[i];
for(i=0;i<256;i++)
{
pDC->MoveTo(410+i,nh+200);
pDC->LineTo(410+i,nh+200-(m_yuan[i]*160/max));
}
}
if(m_bHist==true)
{
//绘画直方图
CStringstr;
intnh=m_dib.GetDIBHeight();
inti;
//画坐标轴
//绘制坐标轴
pDC->MoveTo(10,nh+20);//(10,nh+20)是直方图的左上角坐标
//垂直轴
pDC->LineTo(10,nh+200);//(10,nh+200)是直方图的左下角坐标
//水平轴
pDC->LineTo(310,nh+200);//(310,nh+200)是直方图的右下角坐标
//写X轴刻度值
str.Format("0");
pDC->TextOut(10,nh+200+10,str);
str.Format("50");
pDC->TextOut(60,nh+200+10,str);
str.Format("100");
pDC->TextOut(110,nh+200+10,str);
str.Format("150");
pDC->TextOut(160,nh+200+10,str);
str.Format("200");
pDC->TextOut(210,nh+200+10,str);
str.Format("255");
pDC->TextOut(265,nh+200+10,str);
//绘制X轴刻度
for(i=0;i<256;i+=25)
{
if((i&1)==0)
{
//10的倍数
pDC->MoveTo(i+10,nh+200-2);
pDC->LineTo(i+10,nh+200+2);
}
else
{
//10的倍数
pDC->MoveTo(i+10,nh+200-2);
pDC->LineTo(i+10,nh+200+2);
}
}
//绘制X轴箭头
pDC->MoveTo(305,nh+200-5);
pDC->LineTo(310,nh+200);
pDC->LineTo(305,nh+200+5);
//绘制y轴箭头
pDC->MoveTo(10,nh+20);
pDC->LineTo(5,nh+20+5);
pDC->MoveTo(10,nh+20);
pDC->LineTo(15,nh+20+5);
intmax=0;
for(i=0;i<256;i++)
if(m_hist[i]>max)
max=m_hist[i];
for(i=0;i<256;i++)
{
pDC->MoveTo(10+i,nh+200);
pDC->LineTo(10+i,nh+200-(m_hist[i]*160/max));
}
}
}
/////////////////////////////////////////////////////////////////////////////
//CCqxhistViewprinting
BOOLCCqxhistView:
:
OnPreparePrinting(CPrintInfo*pInfo)
{
//defaultpreparation
returnDoPreparePrinting(pInfo);
}
voidCCqxhistView:
:
OnBeginPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{
//TODO:
addextrainitializationbeforeprinting
}
voidCCqxhistView:
:
OnEndPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{
//TODO:
addcleanupafterprinting
}
/////////////////////////////////////////////////////////////////////////////
//CCqxhistViewdiagnostics
#ifdef_DEBUG
voidCCqxhistView:
:
AssertValid()const
{
CView:
:
AssertValid();
}
voidCCqxhistView:
:
Dump(CDumpContext&dc)const
{
CView:
:
Dump(dc);
}
CCqxhistDoc*CCqxhistView:
:
GetDocument()//non-debugversionisinline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCqxhistDoc)));
return(CCqxhistDoc*)m_pDocument;
}
#endif//_DEBUG
/////////////////////////////////////////////////////////////////////////////
//CCqxhistViewmessagehandlers
voidCCqxhistView:
:
OnOpenImage()
{
//TODO:
Addyourcommandhandlercodehere
//TODO:
Addyourcommandhandlercodehere
staticcharszFilter[]="BMP文件(*.bmp)|*.bmp||";//定义过滤文件的类型
CFileDialogdlg(TRUE,"bmp",NULL,
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter);//定义文件对话框对象
CStringfilename;
intret=dlg.DoModal();//运行打开文件对方框
if(ret==IDOK)
{
filename=dlg.GetFileName();//获取所选择图像的路径
m_dib.LoadFromFile(filename);//加载图像
if(!
m_dib.m_bLoaded)//判断是否加载图像成功
{
AfxMessageBox("图像打不开");
return;
}
for(inti=0;i<256;i++)//初始化直方图数组
{m_hist[i]=0;
m_yuan[i]=0;
}
m_bHist=false;
}
{
intnw=m_dib.GetDIBWidth();
intnh=m_dib.GetDIBHeight();
for(intj=0;jfor(inti=0;i{
BYTEtemp=m_dib.m_pdata[j*nw+i];
m_yuan[temp]++;
}
}
Invalidate
(1);//刷新屏幕
}
voidCCqxhistView:
:
OnHistImage()
{
//TODO:
Addyourcommandhandlercodehere
//功能:
实现直方图均衡化
//////////////////////////
//判断图像是否打开,没打开,则弹出提示框并退出函数
if(!
m_dib.m_bLoaded)
{
AfxMessageBox("图像还打开,请先打开图像!
");
return;
}
//获取图像宽和高
intnw=m_dib.GetDIBWidth();
intnh=m_dib.GetDIBHeight();
inti,j,k;
intcount[256]={0};//定义一个数组,用于存放灰度级个数
floatp[256];//定义一个数组,用于存放灰度级出现频率
//对图像进行直方图均衡化处理
for(i=0;ifor(j=0;j{
k=m_dib.m_pdata[i*nw+j];//计算灰度级个数
count[k]++;
}
for(k=0;k<256;k++)
p[k]=count[k]/(nw*nh*1.0f);
floatc[256]={0};
floatsum=0.0;
intngray[256];//新的灰度级
for(k=0;k<256;k++)//计算累积频率
{
sum+=p[k];
c[k]=sum;
ngray[k]=(int)(255.0*c[k]+0.5);
}
for(i=0;ifor(j=0;j{
k=m_dib.m_pdata[i*nw+j];
m_dib.m_pdata[i*nw+j]=ngray[k];
}
{
intnw=m_dib.GetDIBWidth();
intnh=m_dib.GetDIBHeight();
for(intj=0;jfor(inti=0;i{
BYTEtemp=m_dib.m_pdata[j*nw+i];
m_hist[temp]++;
}
}
//将修改的m_pdata的数据赋值给m_pDIBData,以显示修改的结果
m_dib.UpdateData();
m_bHist=true;
//将修改的m_pdata的数据赋值给m_pDIBData,以显示修改的结果
m_dib.UpdateData();
//刷新屏幕
Invalidate();
}4、实验结果
C++编程结果: