基于直方图处理的图像的增强方法研究
中文摘要
通过直方图均衡算法,使输出图像直方图近似服从均匀分布,在此算法基础上利用小波变换,对图像进行二维小波分解,突出图像中的有用信息,消减图像中的无用信息,使图像中特定信息得倒增强,并提高图像的对比度,提高图像质量。直方图规定化是基于自适应直方图规定化函数引导的动态分层图像增强算法,在对比指纹图像的灰度直方图增强的技术的基础上,针对均衡化算法的不足和现有直方图规定化算法中映射规则计算量大的情形,提出一种改进的规定化算法。直方图规定化可以将图像的直方图转化为需要的形状,有目的地增加某个灰度区间的图像,使用户获得感兴趣的信息。
关键词:图像增强,直方图均衡化,小波变换,直方图规定化
Abstract
Through the histogram equalization algorithm, make the output image histogram approximation obey uniform distribution. Based on the algorithm,using the imagine of the two dimensional wavelet decomposition, highlight the useful information and cut the useless information in the imagine. The imagine of a specific information will be enhanced, and the contrast of imagine will be improved , then the imagine quality will be improved.
Key words: imagine enhancement; histogram equalization; wavelet transform 一:引言
图像变换是数字图像处理中的一种综合变换,如直方图变换。使用C语言对位图文件的头信息进行读取,从而对图像进行直方图均衡化处理和灰度变换。大多数原始的遥感图像由于其灰度分布集中在较窄的范围内,使图像的细节不够清晰,对比度较低。为了使图像的灰度范围拉开或使灰度均匀分布,从而增大反差,使图像细节清晰,以达到增强的目的,通常采用直方图均衡化及直方图规定化两种变换。 二:原理与方法
直方图均衡化(Histogram Equalization)又称直方图平坦化,实质上是对图像进行非线性拉伸,重新分配图像象元值,使一定灰度范围内象元值的数量大致相等。这样,原来直方图中间的峰顶部分对比度得到增强,而两侧的谷底部分对比度降低,输出图像的直方图是一个较平的分段直方图:如果输出数据分段值较小的话,会产生粗略分类的视觉效果。
直方图均衡化理论
假设灰度级为归一化至范围[0,1]内的连续量,并令Pr (r)表示某给定图像中的灰度级的概率密度函数(PDF),其下标用来区分输入图像和输出图像的PDF。假设我们对输入灰度级执行如下变换,得到(处理后的)输出灰度级s:
S=T(r)=∫0 rPr(w)dw
式中w 是积分的哑变量。可以看出,输出灰度级的概率密度函数是均匀的,即 a.当0≤s≤1 时,Ps(s)=1 b.当s 为其他时,Ps(s)=0
换言之,前述变换生成一幅图像,该图像的灰度级较为均衡化,且覆盖了整个范围[0,1]。灰度级均衡化处理的最终结果是一幅扩展了动态范围的图像,它具有较高的对比度。该变换函数只不过是一个累积分布函数(CDF)。
直方图均衡化算法
直方图均衡化算法将原图像的直方图改变为在整个灰度范围内基本均匀地分布的形式,由此扩大了像素灰度的动态范围,从而增强了图像的对比度。直方图均衡化算法步骤为:
1) 给出原始图像的所有灰度级Sk(k=0,1,…,L-1)。 2) 统计原始图像各灰度级的像素数nk。
3) 根据原图像,计算灰度直方图:
nP(Sk)k (k=0,1,…,L-1)
n式中,n为总像素数,nk为灰度级Sk的像素数。
4) 计算原始图像的累积直方图:
knitEEH(Sk)Ps(Si) (0Sk1,k=0,1,…,L-1)
i0ni0k5) 取整计算:
Ukint[(N1)tkk] N6) 确定映射关系:
SkUk
7) 统计新直方图各灰度级Uk的像素数目nk。 8) 计算新的直方图:
可以用概率密度函数pr(r)来表示一幅图象的灰度分布。其中,r为灰度值,pr(r)的值为概率密度。
实验要将原始图象R通过转换函数V(x)转换为具有规定概率密度函数pg(g)最终增强图象G。设原图象的概率密度函数为pr(r)。
变换后的图象的概率密度函数=规定的概率密度函数。 由随机变量函数的概率密度公式可以得到:
pr[V1(r)](V1)'(r)pg(r)
x0pr[V1(r)](V1)'(r)drpg(r)dr
0x设 Pr(x)x0pr(r)dr, Pg(x)pg(g)dg
0xr0x则有 Pr[V(r)]1Pg(r)xr0
Pr[V1(x)]Pg(x) V1(x)Pr[Pg(x)] V(x)Pg[Pr(x)]
所求得的V(x)就是从原始图象到最终增强图象的转换函数。
上述推导得到的V(x)的表达式适用于在灰度级和空间上都连续的图象。为达到数字图象处理的目的,必须对上述表达式进行近似,这种离散形式的近似可以导致图象灰度级的丢失。设图象有256灰度级,该近似方法如下:
xnrpr(r), Pr(x)p(r)
nr011其中,nr为灰度值为r的像素总数,n为总像素数。r=1,2,…,255。
Pg(x)的计算方法相同。
V(x)Pg[转为Pg值域内最为接近的值(Pr(x))], x1,2,,255
在附录所给出的源代码中,转换函数V(x)由数组SG[256]实现。
PSNR值,即峰值信噪比,可以作为衡量输出图象的客观保真度的标准。设图象有256
灰度级,则它的计算公式如下:
12552图象总像素数 PSNR10log[g(x,y)f(x,y)]2g(x,y)和f(x,y)分别代表处理后的图象和原始图象。
显然,PSNR值越大,图象的保真度越高。 整个过程的处理框图:
读入原始图象 计算原始图象的直方图pr(r)n存入H[256]并将数据输出 计算原始图象的均衡直方图Pr(x)255存入S[256]并将数据输出 生成并保存均衡图象 计算原始图象至均衡图象的PSNR值 计算规定的直方图pg(x)255存入G[256] 计算规定的直方图的均衡直方图Pg(x)255存入GS[256]并将数据输出 计算从原始图象到最终增强图象的转换函数V(x) 生成并保存最终增强图象 计算最终增强图象的直方图GR[256]并将数据输出 计算原始图象至最终增强图象的PSNR值 三:仿真实验 1 直方图均衡化实验过程及结果
5、主要代码
voidCImageView::OnDraw(CDC* pDC) {
CImageDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc);
// TODO: add draw code for native data here if(m_dib.m_bLoaded==true) //判断是否加载图像 {
//获取图像宽和高
intnw=m_dib.GetDIBWidth();
intnh=m_dib.GetDIBHeight(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here
if(m_dib.m_bLoaded==true) {
intnw=m_dib.GetDIBWidth(); intnh=m_dib.GetDIBHeight();
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();
int i;
// 绘制坐标轴
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); str.Format(\"原图直方图归一化\"); pDC->TextOut(100, nh+230+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);
int max=0;
for(i=0;i<256;i++)
if(m_yuantu[i]>max)
max=m_yuantu[i]; for(i=0;i<256;i++) {
pDC->MoveTo(10+i,nh+200);
pDC->LineTo(10+i,nh+200-(m_yuantu[i]*160/max)); } }
/********* *********/
//TEST 第二个直方图 if(m_bHist==true) {
//绘画直方图 CStringstr;
intnh=m_dib.GetDIBHeight(); int i;
// 绘制坐标轴
pDC->MoveTo(160+nw,nh+20); //(10,nh+20 )是直方图的左上角坐标
// 垂直轴
pDC->LineTo(160+nw,nh+200);//(10,nh+200 )是直方图的左下角坐标
// 水平轴
pDC->LineTo(460+nw,nh+200);//(310,nh+200 )是直方图的右下角坐标
// 写X轴刻度值 str.Format(\"0\");
pDC->TextOut(415, nh+200+10, str); str.Format(\"50\");
pDC->TextOut(465, nh+200+10, str); str.Format(\"100\");
pDC->TextOut(515, nh+200+10, str); str.Format(\"150\");
pDC->TextOut(565, nh+200+10, str); str.Format(\"200\");
pDC->TextOut(615, nh+200+10, str); str.Format(\"255\");
pDC->TextOut(670, nh+200+10, str); str.Format(\"直方图均衡化后归一化\"); pDC->TextOut(505, nh+230+10, str); // 绘制X轴刻度
for ( i = 0; i < 256; i += 25) {
if ((i & 1) == 0) {
// 10的倍数
pDC->MoveTo(i + 420, nh+200-2); pDC->LineTo(i + 415, nh+200+2); } else {
// 10的倍数
pDC->MoveTo(i + 420, nh+200-2); pDC->LineTo(i + 420, nh+200+2); } }
// 绘制X轴箭头
pDC->MoveTo(710,nh+200-5); pDC->LineTo(715,nh+200); pDC->LineTo(710,nh+200+5);
// 绘制y轴箭头
pDC->MoveTo(415,nh+20); pDC->LineTo(410,nh+20+5); pDC->MoveTo(415,nh+20); pDC->LineTo(420,nh+20+5); int max=0;
for(i=0;i<256;i++) if(m_hist[i]>max)
max=m_hist[i]; for(i=0;i<256;i++) {
pDC->MoveTo(415+i,nh+200);
pDC->LineTo(415+i,nh+200-(m_hist[i]*160/max)); } } /****** *******/
// 显示图像(具体的参数见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);
} }
直方图均衡化及直方图归一化坐标轴赋值程序
voidCImageView::OnZhifangtu() {
//判断图像是否打开,没打开,则弹出提示框并退出函数 if(!m_dib.m_bLoaded) {
AfxMessageBox(\"图像还打开,请先打开图像!\"); return; }
//获取图像宽和高及定义成员变量 intnw=m_dib.GetDIBWidth(); intnh=m_dib.GetDIBHeight(); inti,j;
int *arr=new int [nw*nh]; int n[256]={0};
float p[256]={0.0},c[256]={0.0}; BYTE* pdata=m_dib.m_pdata;
for(i=0;i<256;i++) //初始化直方图数组 m_yuantu[i]=0;
if(1)//m_dib.m_nImType==24) {
for(j=0;j m_bHist=true; //直方图归一化计算 for(i=0;i for(i=0;i<256;i++) { (float)p[i]=(float)n[i]/(float)(nw*nh); } //归一化后累计计算 for(i=0;i<256;i++) { for(j=0;j<=i;j++) { c[i]+=p[j]; } } //找到灰度值最大值最小值 int max=m_dib.m_pdata[0],min=m_dib.m_pdata[0]; for(i=0;i else if(min>m_dib.m_pdata[i*nw+j]) { min=m_dib.m_pdata[i*nw+j]; } } } //套公式直方图均衡化计算赋值给arr[]一维数组 for(i=0;i //一维数组arr[]赋值给新图像 for( j=0;j //将修改的m_pdata的数据赋值给m_pDIBData,以显示修改的结果 m_dib.UpdateData(); //刷新屏幕 Invalidate(); } for(i=0;i<256;i++) //初始化直方图数组 m_hist[i]=0; if(1)//m_dib.m_nImType==24) { for(j=0;j m_bHist=true; // TODO: Add your command handler code here 2 直方图规定化实验过程及结果 计数6000500030025020015010050011937557391109127145163181199217235s40003000200010000r253r1305988117146175204233 原图象直方图H: 直方图H的均衡直方图S: 原始图象R s 均衡图象S PSNR=10.954935 300250200150100500G1275379105131157183209235 目标直方图G 目标直方图G的均衡直方图 6000500040003000200010000计数G1305988117146175204233 最终增强图象直方图 最终增强图象G PSNR=11.947287 附录: 源程序 #include #include #ifndef HXLBMPFILE #define HXLBMPFILE class BMPFILE {public: RGBQUAD palette[256]; BITMAPFILEHEADER imagefh; BITMAPINFOHEADER imageih; intimagew,imageh; UCHAR *imagedata; UCHAR *GetByteatH(int height); BOOL AllocateMem(); BOOL bIsOk; voidLoadBMPFILE(char *fname); voidSaveBMPFILE(char *fname); BMPFILE(); ~BMPFILE(); }; #endif void main() { BMPFILE bmpfile; bmpfile.LoadBMPFILE (\"实验图象1.bmp\"); if(!bmpfile.bIsOk) { printf(\"Error loading image.\\n\"); return; } // do other processing with the imagedata int H[256]; //原始图象直方图 memset(H,0,sizeof(H)); int S[256]; //变换映射-均衡直方图S double psnr; //峰值信噪比 int i; int f; for(i=0;i ; for(i=0;i<256;i++) S[i]=S[i]*255/(bmpfile.imageh*bmpfile.imagew); for(i=0;i for(i=1;i<256;i++) printf(\"%d \printf(\"\\n\"); //原图象(直方图H)的均衡直方图 printf(\"S: \"); for(i=1;i<256;i++) printf(\"%d \printf(\"\\n\"); //均衡图象 bmpfile.SaveBMPFILE (\"实验图象1-均衡图象.bmp\"); //PSNR值 psnr=0; for(i=0;i<255;i++) psnr+=(S[i]-i)*(S[i]-i)*H[i]; psnr=10*log10(double(bmpfile.imageh)*bmpfile.imagew*255*255/psnr)printf(\"PSNR: %f\\n\//目标直方图G的均衡直方图 int G[256]; //规定直方图 int GS[256]; //规定直方图的均衡直方图 for(i=0;i<=127;i++) G[i]=i; for(i=128;i<=255;i++) G[i]=(255-i); GS[0]=G[0]; for(i=1;i<256;i++) GS[i]=GS[i-1]+G[i]; f=GS[255]/255+1; for(i=0;i<256;i++) GS[i]/=f; printf(\"GS: \"); for(i=1;i<256;i++) printf(\"%d \printf(\"\\n\"); //最终增强图象 int i2; intminNumber; int SG[256]; //从原图象的均衡图象到最终增强图象的映射 memset(SG,0,sizeof(SG)); for(i=0;i<256;i++) ; } { minNumber=255; for(i2=0;i2<256;i2++) if(abs(S[i]-GS[i2]) for(i=0;i memset(GR,0,sizeof(GR)); for(i=1;i<256;i++) GR[SG[S[i]]]+=H[i]; printf(\"GR: \"); for(i=1;i<256;i++) printf(\"%d \printf(\"\\n\"); //最终增强图象的PSNR值 psnr=0; for(i=0;i<255;i++) psnr+=(SG[S[i]]-i)*(SG[S[i]]-i)*GR[i]; psnr=10*log10(double(bmpfile.imageh)*bmpfile.imagew*255*255/psnr)printf(\"PSNR of the destination image: %f\\n\ 四总结与展望 通过本次作业,让我学会了从问题的高度来考虑设计的方方面面,对程序的设计和研究有了更深刻的体会;让我了解到程序的设计是建立在对理论知识了解的基础上的,特别是对直方图均衡化的原理要有较为详细的了解,此外对直方图均衡化算法也要进行了解;在编写程序时,进行模块化设计,以严谨的态度进行编程,避免出现低级错误,养成为程序添加注释和说明的好习惯,以便自己的修改和阅读者轻松的了解程序的各部分及整体的功能。 直方图均衡化的实质就是通过减少图象的灰度级以换取对比度的加大。以下是变化前后的图像。 数字图像处理论文 年级:专业:通信工程班级:学号:姓名:陈佳敏级 班 2011220112420202 因篇幅问题不能全部显示,请点此查看更多更全内容