VC下通过直方图变换对图像进行有效增强

 

摘自:http://www.builder.com.cn/2007/1016/558561.shtml

摘要:本文介绍了一种通过对图像的直方图进行变换操作而使图像得到有效增强的程序算法,并从数学的角度对程序算法的实现原理做了较为详细的描述。

  关键词:图像处理;灰度直方图;直方图均衡化;直方图规定化;单映射规则;组映射规则;统计概率

  前言

  图像增强处理技术一直是图像处理领域一类非常重要的基本图像处理技术。通过采取适当的增强处理可以使原本模糊不清甚至根本无法分辨的原始图片处理成清楚、明晰的富含大量有用信息的可使用目标图像,因此此类图像处理技术在医学、遥感、微生物、刑侦以及军事等诸多科研和应用领域对原始图像的模式识别、目标检测等起着重要作用。本文将从空间域的角度对图像的灰度直方图增强处理方法做详细的介绍。

  图像的灰度直方图处理技术

  在空域对图像进行增强处理的方式有许多种,如增强对比度和动态范围压缩等等,但这些处理方式都是针对原始图像的每一个像素直接对其灰度进行处理的,其处理过程主要是通过增强函数对像素的灰度级进行运算并将运算结果作为该像素的新灰度值来实现的。通过改变选用增强函数的解析表达式就可以得到不同的处理效果,这类处理方法比较灵活方便,处理效果也比较不错,但对于某些灰度分布很密集或对比度很弱的图像虽然也能起到一定的增强效果但并不明显。对于这种情况就需要用本文提出的灰度直方图变换方法将原始图像密集的灰度分布变的比较疏散,从而拉大了图像的对比度并在视觉上达到明显增强的效果,使一些原本不易观察到的细节能变的清晰可辩。

  图像的灰度变换处理是通过改变原始图像各像素在各灰度级上的概率分布来实现的。通过对图像的灰度值进行统计可以得到一个一维离散的图像灰度统计直方图函数p(sk)=nk/n (k=0,1,2,……,L-1)。该式表达了在第k个灰度级上的像素的个数nk占全部像素总数n的比例,p(sk)则给出了对sk出现概率的1个估计。因此该直方图函数实际是图像的各灰度级的分布情况的反映,换句话说也就是给出了该幅图像所有灰度值的整体描述。通过该函数可以清楚地了解到图像对应的动态范围情况,可以了解到图像灰度的主要集中范围。因此可以通过图像增强程序的干预来改变直方图的灰度分布状况,使灰度均匀的或是按预期目标分布与整个灰度范围空间,从而达到增强图像对比度的效果。这种方法是基于数理统计和概率论的,比直接在空域对原始图像采取对比度增强效果要好的多。在实际应用中直方图的变换主要有均衡变换和规定变换两种,而后者又根据灰度级映射规则的不同分单映射规则和组映射规则两种。

  直方图均衡化处理

  直方图均衡化处理的中心思想是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。对图像空域点的增强过程是通过增强函数t=EH(s)来完成的,t、s分别为目标图像和原始图像上的像素点(x,y),在进行均衡化处理时对增强函数EH需要满足两个条件:增强函数EH(s)在0≤s≤L-1的范围内是一个单调递增函数,这个条件保证了在增强处理时没有打乱原始图像的灰度排列次序。另一个需要满足的条件是对于0≤s≤L-1应当有0≤EH(s)≤L-1,它保证了变换过程灰度值的动态范围的一致。同样的,对于反变换过程s=EH-1(t),在0≤t≤1时也必须满足上述两个条件。累计分布函数(cumulative distribution function,CDF)就是满足上述条件的一种,通过该函数可以完成s到t 的均匀分布转换。此时的增强转换方程为:

tk = EH(sk) = ∑(ni/n) = ∑ps(si) ,(k=0,1,2,……,L-1)

  上述求和区间为0到k,根据该方程可以由源图像的各像素灰度值直接得到直方图均衡化后各像素的灰度值。在实际处理变换时,一般先对原始图像的灰度情况进行统计分析,并计算出原始直方图分布,然后根据计算出的累计直方图分布tk按式tk=[(N-1)* tk+0.5]对其取整并得出源灰度sk到tk的灰度映射关系,其中N为灰度的级数。在重复上述步骤得到所有的源图像各灰度级到目标图像各灰度级的映射关系后按照新的映射关系对源图像各点像素进行灰度转换即可完成对源图的直方图均衡化。下面是按照上述算法实现的部分主要程序代码:

  首先对原始图像的各像素点的灰度情况进行统计计算。对于24位BMP图像,图像阵列是从第54字节起始的,每像素按R、G、B的顺序占3个字节。

for(DWORD i=54;i<m_dwFileLen;i++)
{
 ns_r[m_cpBuffer[i]]++; //ns_r[k]为k灰度级像素数,m_cpBuffer[i]为当前的灰度值
 i++;
 ns_g[m_cpBuffer[i]]++;//ns_g为G分量的统计记数
 i++;
 ns_b[m_cpBuffer[i]]++;//ns_b为B分量的统计记数
}
for(i=0;i<256;i++) //计算R、G、B三分量的直方图分布
{
 ps_r[i]=ns_r[i]/((m_dwFileLen-54)/3.0f); //ps_r[i]为R分量中i灰度级出现的概率
 ps_g[i]=ns_g[i]/((m_dwFileLen-54)/3.0f); //ps_b[i]为G分量中i灰度级出现的概率
 ps_b[i]=ns_b[i]/((m_dwFileLen-54)/3.0f); //ps_b[i]为B分量中i灰度级出现的概率
}

  然后计算R、G、B三分量各灰度级的累计直方图分布,并对其进行取整以得出源和目标图像灰度之间的映射关系:

for(i=0;i<256;i++)
{
 //计算累计直方图分布
 temp_r[i]=temp_r[i-1]+ps_r[i];
 temp_g[i]=temp_g[i-1]+ps_g[i];
 temp_b[i]=temp_b[i-1]+ps_b[i];
 //累计分布取整,ns_r[]、ns_g[]、ns_b[]保存有计算出来的灰度映射关系
 ns_r[i]=(int)(255.0f*temp_r[i]+0.5f);
 ns_g[i]=(int)(255.0f*temp_g[i]+0.5f);
 ns_b[i]=(int)(255.0f*temp_b[i]+0.5f);
}

  最后按照计算出来的映射关系把原图的原始灰度值映射到经过均衡化的新灰度级上,完成最后的处理,下图就是原图像和用本程序得出的经过直方图均衡化处理的目标图像,从实验结果可以看出原始图像太暗根本看不清细节,而处理过的图像则非常清晰:

for(i=54;i<m_dwFileLen;i++)
{
 m_cpBuffer[i]=ns_r[m_cpBuffer[i]]; //对R分量进行灰度映射(均衡化)
 i++;
 m_cpBuffer[i]=ns_g[m_cpBuffer[i]]; //对G分量进行灰度映射(均衡化)
 i++;
 m_cpBuffer[i]=ns_b[m_cpBuffer[i]]; //对B分量进行灰度映射(均衡化)
}

 

 

采取单映射规则的直方图规定化处理

  前面介绍的直方图均衡化处理方法从实验效果看还是很不错的,从实现算法上也可以看出其优点主要在于能自动增强整幅图像的对比度,但具体的增强效果也因此不易控制,只能得到全局均衡化处理的直方图。而在科研和工程应用中往往根据不同的需要而希望得到特定形状的直方图分布以有选择的对某灰度范围进行局部的对比度增强。象这种情况可以采取对直方图的规定化处理,通过选择合适的规定化函数可以取得期望的效果。对于灰度级数分别为M和N(满足M≥N)的原始图和规定图,一般仍先按均衡化对原始图进行处理:

tk = EHs(si) = ∑ps(si) ,(k=0,1,2,……,M-1)

  然后规定需要的直方图,并计算出能使规定的直方图均衡化的变换:

vl = EHu(uj) = ∑pu(ui) ,(l=0,1,2,……,N-1)

  最后将第一步得到的变换反转过去,即把原始直方图对应映射到规定的直方图,也就是把所有的ps(si)映射到pu(uj)中去。由于映射是在离散空间进行的,而且在取整时不可避免会引入误差,因此采取何种对应规则是一个很重要的问题。比较常用的一种方法是Gonzalez在1987年提出的单映射规则(single mapping law,SML):首先寻找能满足 |∑ps(si) - ∑pu(uj)| 最小的k和l(ps()和pu()的求和上限),然后把ps(si)映射到pu(uj)中去。

VC下通过直方图变换对图像进行有效增强_第1张图片

  本文针对原始图像比较暗的特点,采取如下的规定直方图,以使高亮度像素能得到充分的加强:

float a=1.0f/(32.0f*63.0f); //64个灰度级,a为步长
for(int i=0;i<64;i++)

  接下来的对原始图和规定直方图计算累计直方图同前面的直方图均衡化基本一样,在此不在赘述。重点是根据SML规则把ps(si)映射到pu(uj)中去:

for(i=0;i<256;i++)
{
 ……
 for(int j=0;j<64;j++)
 {
  float now_value=0.0f;
  //计算R分量的两累计直方图的绝对差值,并找到满足最小的灰度级
  if(ps_r[i]-pu[j]>=0.0f)
   now_value=ps_r[i]-pu[j];
  else
   now_value=pu[j]-ps_r[i];
  if(now_value<min_value_r)
  
  ……
  //对G和B分量的代码与R分量类似,在此省略
  ……
 }
 //建立灰度映射关系
 ns_r[i]=nu[m_r];
 ns_g[i]=nu[m_g];
 ns_b[i]=nu[m_b];
}

VC下通过直方图变换对图像进行有效增强_第2张图片

  在得到ps(si)到pu(uj)的映射关系后按照该映射关系把原图的原始灰度值映射到经过均衡化的新灰度级上,完成最后的处理。上图为实验得到的按单映射规则对直方图规定化后的效果,同直方图均衡化处理效果相比可以看出高亮度部分得到了充分的增强。
 
采取组映射规则的直方图规定化处理

  单映射规则虽然实现起来比较简单直观,但在实际处理时仍存在不可忽视的取整误差,因此在一定程度上还不能很好的实现规定直方图的意图。可以通过在规定化直方图时选取适当的对应规则来改善,一种比较好的对应规则是组映射规则(group mapping law,GML)。这种规则的约定如下:

  存在一维离散整数函数I(a),(a=0,1,2……N-1),而且满足0≤I(0) ≤I(1) ≤……≤I(a) ≤……≤I(N-1) ≤M-1。寻找能使 |∑ps(si) - ∑pu(uj)| 达到最小的I(a),其中ps(si)的求和区间为[0,I(a)];pu(uj)的求和区间仍为[0,a]。a=0时将介于0和I(0)之间的ps(si)都映射到pu(u0)中;1≤a≤N-1时,将介于I(a-1)+1和I(a)之间的ps(si)都映射到pu(uj)中去。

  由于同单映射规则相比只是对应规则作了变化,因此编码部分只需将对应规则部分的代码根据上面介绍的组映射规则做必要修改即可:

for(i=0;i<64;i++) //对规定直方图的灰度级进行枚举
{
 ……
 for(int j=0;j<256;j++) //对原图的灰度级进行枚举
 {
  float now_value=0.0f;
  //寻找对于R变量能满足差值最小的I(a),保存于A2_r
  if(ps_r[j]-pu[i]>=0.0f)
   now_value=ps_r[j]-pu[i];
  else
   now_value=pu[i]-ps_r[j];
   if(now_value<min_value_r)
   
   for(int k=A1_r;k<=A2_r;k++)//建立R分量的映射规则
    ns_r[k]=nu[i];
    A1_r=A2_r+1;
    ……
    //对于G、B分量的处理与上类似,在此省略。
   ……
}

  对原始图像应用本算法,实验得出的按组映射规则对原图做直方图规定化后的效果图如下图所示:

VC下通过直方图变换对图像进行有效增强_第3张图片

  该图同单映射规则处理图像相比虽无太大变化,但在直方图分布和图像细节上更能体现出规定直方图的意图。而且通过下面的分析也可以看出组映射规则的误差要小的多:

  在ps(si)映射到pu(uj)时,采取SML规则的映射方法由于取整误差的影响可能产生的最大误差是pu(uj)/2,而采用GML规则的映射方法可能出现的误差为ps(si)/2,由于M≥N,所以一定成立 pu(uj)/2≥ps(si)/2,也就是说SML映射规则的期望误差一定不会小于GML映射规则的期望误差。而且从算法实现上也可以看出,SML映射规则是一种有偏的映射规则,某些范围的灰度级会被有偏地映射到接近开始计算的灰度级;而GML映射规则是统计无偏的,从根本上就避免了上述问题的出现。通过分析可以看出GML映射规则总会比SML映射规则更能体现规定直方图的意图,而且通常产生的误差只有SML映射规则的十几分之一。

  结论

  本文从理论上讲述了直方图变换处理中常用的直方图均衡化、采取单映射和组映射规则的直方图规定化变换方法,通过程序算法实现了上述图像增强过程并给出了通过三种算法实验得出的处理图像。实验表明本文介绍的方法对于暗、弱信号的原始图像的目标识别和图像增强等有着良好的处理效果,尤其是通过组映射规则的直方图规定化变换方法结合设计良好的规定直方图可以得到更佳的图像处理效果。本文给出的程序代码在Windows 2000 Professional 下由Microsoft Visual C++ 6.0编译通过。

你可能感兴趣的:(windows,算法,function,Microsoft,float,图像处理)