直方图均衡化

  图像对比度增强的方法可以分成两类:一类是直接对比度增强方法;另一类是间接对比度增强方法。直方图拉伸和直方图均衡化是两种最常见的间接对比度增强方法。直方图拉伸是通过对比度拉伸对直方图进行调整,从而“扩大”前景和背景灰度的差别,以达到增强对比度的目的,这种方法可以利用线性或非线性的方法来实现;直方图均衡化则通过使用累积函数对灰度值进行“调整”以实现对比度的增强。

  直方图均衡化的英文名称是Histogram Equalization.

  直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法。这种方法通常用来增加许多图像的局部对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。

基本思想

  直方图均衡化处理的“中心思想”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。

  直方图均衡化的基本思想是把原始图的直方图变换为均匀分布的形式,这样就增加了象素灰度值的动态范围从而可达到增强图像整体对比度的效果。设原始图像在(x,y)处的灰度为f,而改变后的图像为g,则对图像增强的方法可表述为将在(x,y)处的灰度f映射为g。在灰度直方图均衡化处理中对图像的映射函数可定义为:g = EQ (f),这个映射函数EQ(f)必须满足两个条件(其中L为图像的灰度级数):

  (1)EQ(f)在0≤f≤L-1范围内是一个单值单增函数。这是为了保证增强处理没有打乱原始图像的灰度排列次序,原图各灰度级在变换后仍保持从黑到白(或从白到黑)的排列。

  (2)对于0≤f≤L-1有0≤g≤L-1,这个条件保证了变换前后灰度值动态范围的一致性。

  累积分布函数(cumulative distribution function,CDF)即可以满足上述两个条件,并且通过该函数可以完成将原图像f的分布转换成g的均匀分布。此时的直方图均衡化映射函数为:

  gk = EQ(fk) = (ni/n) = pf(fi) ,

  (k=0,1,2,……,L-1)

  上述求和区间为0到k,根据该方程可以由源图像的各像素灰度值直接得到直方图均衡化后各像素的灰度值。在实际处理变换时,一般先对原始图像的灰度情况进行统计分析,并计算出原始直方图分布,然后根据计算出的累计直方图分布求出fk到gk的灰度映射关系。在重复上述步骤得到源图像所有灰度级到目标图像灰度级的映射关系后,按照这个映射关系对源图像各点像素进行灰度转换,即可完成对源图的直方图均衡化。

 

 图像直方图变换的基本原理

设变量r代表图像中像素的灰度级,直方图变换就是假定一个变换式:

                            (1-1)

也就是,通过上述变换,每个原始图像的像素灰度级r都会产生一个s值。变换函数T(r)应满足以下条件:

(1)       T(r)在区间中为单值且单调递增;

(2)       当 时,,即T(r)的取值范围与r相同。

2. 直方图均衡化:

对于离散值,我们处理其概率与求和,而不是概率密度函数与积分。一幅图像中灰度级rk出现的概率近似为

                                                (1-2)

其中,n是图像中像素的总和, 是灰度级 的像素个数,L为图像中可能的灰度级总数。

                                               (1-3)

         上式中变换函数的离散形式为:    

                                             (1-4)

         式(1-4)给出的变换(映射)称为直方图均衡化或直方图线性化。

 

优缺点

  这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。

  这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景杂讯的对比度并且降低有用信号的对比度;变换后图像的灰度级减少,某些细节消失;某些图像,如直方图有高峰,经处理后对比度不自然的过分增强。

 

/*************************************************************************

 *

 * 函数名称:

 * InteEqualize()

*

* 参数:

* LPSTR lpDIBBits - 指向源DIB图像指针

 * LONG lWidth - 源图像宽度(象素数)

* LONG lHeight - 源图像高度(象素数)

 *

* 返回值:

* BOOL - 成功返回TRUE,否则返回FALSE。

*

* 说明:

* 该函数用来对图像进行直方图均衡。

 *

 ************************************************************************/

BOOL WINAPI InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)

{

        // 指向源图像的指针

       unsigned char* lpSrc;

       // 临时变量

        LONG lTemp;

       // 循环变量

        LONG i; LONG j;

        // 灰度映射表

       BYTE bMap[256];

       // 灰度映射表

        LONG lCount[256];

       // 图像每行的字节数

       LONG lLineBytes;

        // 计算图像每行的字节数

        lLineBytes = WIDTHBYTES(lWidth * 8);

        // 重置计数为0

        for (i = 0; i < 256; i ++)

        {

              // 清零

               lCount[i] = 0;

       }

       // 计算各个灰度值的计数

        for (i = 0; i < lHeight; i ++)

       {

              for (j = 0; j < lWidth; j ++)

              {

                     lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;

                      // 计数加1 l

                     Count[*(lpSrc)]++;

              }

       }

       / / 计算灰度映射表

       lTemp = 0;

       for (i = 0; i < 256; i++)

       {                          

               lTemp += lCount[j];

                // 计算对应的新灰度值

               bMap[i] = (BYTE) (lTemp * 255 / lHeight / lWidth);

        }

         // 每行

        for(i = 0; i < lHeight; i++)

        {

                // 每列

                for(j = 0; j < lWidth; j++)

                 {

                         // 指向DIB第i行,第j个象素的指针

                         lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;

                         // 计算新的灰度值

                        *lpSrc = bMap[*lpSrc];

                 }

        }

        // 返回

        return TRUE;

        }

 

 

Split
分割多通道数组成几个单通道数组或者从数组中提取一个通道

void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1,
CvArr* dst2, CvArr* dst3 );
#define cvCvtPixToPlane cvSplit
src
原数组.
dst0...dst3
目标通道
函数 cvSplit 分割多通道数组成分离的单通道数组d。可获得两种操作模式 . 如果原数组有N通道且前N输出数组非NULL, 所有的通道都会被从原数组中提取,如果前N个通道只有一个通道非NULL函数只提取该指定通道,否则会产生一个错误,馀下的通道(超过前N个通道的以上的)必须被设置成NULL,对于设置了COI的IplImage 结使用cvCopy 也可以从图像中提取单通道。

 

opencv多通道融合:Merge

Merge
从几个单通道数组组合成多通道数组或插入一个单通道数组

void cvMerge( const CvArr* src0, const CvArr* src1,
const CvArr* src2, const CvArr* src3, CvArr* dst );
#define cvCvtPlaneToPix cvMerge
src0... src3
输入的通道.
dst
输出数组.
函数cvMerge 是前一个函数的反向操作。如果输出数组有N个通道并且前N个输入通道非NULL,就拷贝所有通道到输出数组,如果在前N个通道中只有一个单通道非NULL ,只拷贝这个通道到输出数组,否则 就会产生错误。除前N通道以外的馀下的通道必须置NULL。对于设置了COI的 IplImage结构使用 cvCopy也可以实现向图像中插入一个通道 。

 

EqualizeHist

灰度图象直方图均衡化

void cvEqualizeHist( const CvArr* src, CvArr* dst );

src

输入的 8-比特 单信道图像

dst

输出的图像与输入图像大小与数据类型相同

函数 cvEqualizeHist 采用如下法则对输入图像进行直方图均衡化:


1. 计算输入图像的直方图 H

2.  直方图归一化,因此直方块和为255

3. 计算直方图积分: 

4. 采用H'作为查询表:dst(x,y)=H'(src(x,y))进行图像变换。

该方法归一化图像亮度和增强对比度。

 ----------------------------------------------------------------------------------------------

#include <highgui.h>
#include <cv.h>

int main(int argc, char** argv)
{
         int i;
         IplImage* src = cvLoadImage( argv[1], 1 );
         IplImage* imgChannel[4] = { 0, 0, 0, 0 };
         IplImage* dst = cvCreateImage( cvGetSize( src ), IPL_DEPTH_8U, 3 );

         if( src )
         {
                 for( i = 0; i < src -> nChannels; i++ )
                  {
                           imgChannel[i] = cvCreateImage( cvGetSize( src ), IPL_DEPTH_8U, 1 );  //要求单通道图像才能直方图均衡化
                  }
                   //通道分离
                   cvSplit( src, imgChannel[0], imgChannel[1], imgChannel[2], imgChannel[3] );
                   for( i = 0; i < dst -> nChannels; i++ )
                   {
                    //直方图均衡化,原始图像和目标图像必须是单通道
                    cvEqualizeHist( imgChannel[i], imgChannel[i] );
                   }

                   //通道组合
                   cvMerge( imgChannel[0], imgChannel[1], imgChannel[2], imgChannel[3], dst );
                   cvNamedWindow( "src", 1 );
                   cvShowImage( "src", src );
                   cvNamedWindow( "Equalize", 1 );
                   cvShowImage( "Equalize", dst );

                   cvWaitKey(0);
                   //释放资源
                   for( i = 0; i < src -> nChannels; i++ )
                   {
                             if( imgChannel[i] )
                             {
                                      cvReleaseImage( &imgChannel[i] );
                                      //imgChannel[i] = 0;
                             }
                   }
                   cvReleaseImage( &dst );
          }

          return 0;
}

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值