灰度图像--图像增强 直方图均衡化(Histogram equalization)

转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不满意。有些网站转载了我的博文,很开心的是自己写的东西被更多人看到了,但不开心的是这段话被去掉了,也没标明转载来源,虽然这并没有版权保护,但感觉还是不太好,出于尊重文章作者的劳动,转载请标明出处!!!!

文章代码已托管,欢迎共同开发:https://github.com/Tony-Tan/DIPpro

开篇废话

 
        废话开始,图像处理这些代码已经有三千多行了,不多,但是感觉多加练习以后对算法理解和写代码的能力上都有很大提高,毕竟对于算法来说想明白了一定要用一下才会真正掌握,但不能靠记忆去记住一个算法,这就需要我们懒人的天性,不愿意记住完整的公式,更愿意记住一个简单的起始,通过自己的理解和数学推导算法,这是个很不错的 方法,而写代码属于一种技术工作,熟能生巧,要多加练习,并且也要思考其中的技术细节,总之,做一切事情思考下还是不错的。
       废话完成,说说直方图均衡,在冈萨雷斯的书里面直方图均衡化在第三章提出,因为之前想按照书上目录上的顺序来写着一些列的博客,后来发现还是自己总结下的学习思路,按照自己理解的知识网络来走,所以刚要写直方图均衡的时候就是转向自己的节奏开始按照二值图像,灰度图像,彩色图像的知识结构介绍。
       直方图均衡的目的和前面灰度变换一样,为了增强对比度,使图像的灰度分布在整个灰度范围内更加均衡,其中直方图需要来解释下,直方图是个统计概念,比如我们有十种颜色的球,每种颜色的球有不同的数量,假设颜色分布为a0~a9,数量为n(x)(x取值为a0~a9)那么直方图就是以a0~a9为横坐标,n为纵坐标的统计直方图:
       如果将上图中的数据归一化(每个分量除以球数总和),也就是使得各分量总和为1,各个分量就表示这种颜色的球出现的频率,就得到频率直方图。
       如果将各种颜色换成各灰度值,球的个数等效的换成具有该灰度的像素数量,或者换成该灰度出现的频率,就成了图像的直方图,对于彩色图像和灰度图像,直方图具有重要的统计意义,而对于二值图像来说,该意义不大,因为二值图像就两个灰度,所以其只能反映黑白面积比例。
       直方图均衡的目的是为了使灰度分布的更广泛,从而来拉伸对比度:
       事实表明当灰度的直方图范围从上面的左边变换成右边后,图像对比度得到提升,也就达到了我们增强图像的目的--更便于观察,更容易区分不同灰度间细节。
 

数学原理

 
     直方图变换的最终操作和前面提到的灰度操作是一样的,即:
      这是一种从灰度到灰度的映射,并且该映射与前面伽马变换对数变换的映射不同的是,它不具有确定的表达公式,而是根据原始图像的灰度分布不同而“自适应”的产生映射,并且必须具有以下两个性质:
  1. 该函数必须单调递增(因为要从s反射回r所以该函数必须是严格的单调递增,即r和s为一对一的关系)
  2. 0<=r<=L-1时,必须满足0<=s<=L-1
      这是两点约束,即我们找到的T必须使得上面成立,而且还要达到均衡直方图的目的。即完成下面的转化:
上面的是直方图的原始分布和目标分布,下面是响应的T。
推导过程:
       先提出一个概率密度函数pdf的概念,就是每个灰度值对应出现的概率,用p表示,pr(r)表示原始灰度r出现的概率,其计算是用灰度值为r的像素总个数除以图像的像素总个数。同理变换后的ps(s)表示变换后灰度为s的像素的概率。
  1. r到s是一对一的映射,所以若r0映射到s0那么pr(r0)=ps(s0)这个式子是因为像素个数不会改变,只是对应的灰度值改变了,这个就是我们接下来要用到的最基本的原理。
  2. 我们的目标灰度分布是均匀分布,也就是上图右上的概率分布图,因为绿色部分面积必然为1,所以,ps的目标分布为:                                          
根据上述的基本原理和假设存在:
根据积分定理,w为积分假变量,那么:
所以:
将上面离散化:
上面为大概的公式推导,如有不严谨之处还请指出。
所以我们将按照上面得出的结论进行编程:
 
 

代码

 
  1. /********************************************************************************************
  2. 直方图基本操作
  3. *******************************************************************************************/
  4. void InitMappingTable(void * arry,int size,int Data_type){
  5. if(Data_type==TABLE_INT)
  6. for(int i=0;i<size;i++)
  7. ((int*)arry)[i]=0;
  8. else if(Data_type==TABLE_CHAR)
  9. for(int i=0;i<size;i++)
  10. ((char*)arry)[i]=0;
  11. else if(Data_type==TABLE_DOUBLE)
  12. for(int i=0;i<size;i++)
  13. ((double*)arry)[i]=0;
  14. }
  15. void InitHistogram(int *hist){
  16. for(int i=0;i<GRAY_LEVEL;i++)
  17. hist[i]=0;
  18. }
  19. void setHistogram(double *src,int *hist,int width,int height){
  20. InitHistogram(hist);
  21. for(int j=0;j<height;j++)
  22. for(int i=0;i<width;i++){
  23. int tempv=src[j*width+i];
  24. hist[tempv]++;
  25. }
  26. }
  27. int findHistogramMax(int *hist){
  28. for(int i=GRAY_LEVEL-1;i>=0;i--){
  29. if(hist[i]!=0)
  30. return i;
  31. }
  32. return -1;
  33. }
  34. int findHistogramMin(int *hist){
  35. for(int i=0;i<GRAY_LEVEL;i++){
  36. if(hist[i]!=0)
  37. return i;
  38. }
  39. return -1;
  40. }
  41. void fillMaptable(double * map){
  42. for(int i=1;i<GRAY_LEVEL;i++){
  43. if(map[i]==0)
  44. map[i]=map[i-1];
  45. }
  46. }
  47. /********************************************************************************************
  48. 直方图均衡
  49. *******************************************************************************************/
  50. //均衡直方图,将原图直方图,经过公式得到目标直方图
  51. void EqualizationHist(int *src_hist,double *dst_map){
  52. int temphist[GRAY_LEVEL];
  53. InitHistogram(temphist);
  54. int max=findHistogramMax(src_hist);
  55. int min=findHistogramMin(src_hist);
  56. temphist[min]=src_hist[min];
  57. for(int i=min+1;i<=max;i++)
  58. temphist[i]=temphist[i-1]+src_hist[i];
  59. for(int i=min;i<=max;i++)
  60. temphist[i]-=temphist[min];
  61. int total=temphist[max];
  62. for(int i=min;i<=max;i++){
  63. dst_map[i]=((double)GRAY_LEVEL-1.0)*temphist[i]/total;
  64. }
  65. }
  66. //直方图均很,用输入图像得到输出图像
  67. void HistogramEqualization(double *src,double *dst,int width,int height){
  68. int hist[GRAY_LEVEL];
  69. setHistogram(src, hist, width, height);
  70. double GrayMappingTable[GRAY_LEVEL];
  71. InitMappingTable(GrayMappingTable,GRAY_LEVEL,TABLE_DOUBLE);
  72. EqualizationHist(hist, GrayMappingTable);
  73. for(int i=0;i<width;i++)
  74. for(int j=0;j<height;j++)
  75. dst[j*width+i]=GrayMappingTable[(int)src[j*width+i]];
  76. }
 

结果

 
原图:
原图直方图:
直方图均衡后图片:
直方图均衡后直方图:
 

总结

 
        上面给出的结果为经典结果,很多文章都使用的这幅图片,值得解释的是,虽然我们从r到s的映射是一对一的,但r和s是离散的整数,如果s被映射到非整数,将就近取整,所以有些灰度值会被合并。
        直方图运算速度快,效果好,应用范围很广,故总结如上。
        待续。。。
 
 
 
 
 
直方图均衡化算法实现
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://qianqing13579.blog.51cto.com/5255432/1559162

直方图

直方图(histogram)是灰度级的函数,它表示图像中具有每种灰度级的像素的个数,

反映原图中各种灰度值分布的情况。

如下图所示,灰度直方图的横坐标是灰度级,纵坐标是该灰度级出现的频率,是图像的最基本的统计特征。

上面的是标准直方图

灰度统计累计直方图:

H(k)= ∑ni(i<=k)

累积直方图中第k列的高度是图像中所有灰度值<=k的像素的个数

灰度直方图的求取算法实现

1
2
3
4
5
6
7
8
9
10
11
12
void GetHistogram(BYTE *image_Src, int width, int height, unsigned long *histogram)
{
    int pixelCount = width*height;//imageSize->pixelCount
    memset(histogram, 0, 256*4);//注意最后一个参数是数组的大小(单位是字节)
    for (int i = 0; i <= pixelCount - 1; ++i)
    {
        int gray = image_Src[0];
        histogram[gray]++;
        //下一个像素
        image_Src+=1;
    }
}

直方图的特点

直方图具有很多的优点,直方图能反映图像的概貌,

  • 图像中有几类目标,目标和背景的分布如何;

  • 通过直方图可以直接计算图像中的最大亮度、最小亮度、平均亮度、对比度以及中间亮度等。

  • 使用直方图可以完成图像分割、目标检索等。因为不同的目标具有不同的颜色分布。使用归一化直方图作目标匹配,还不易受到目标翻转和目标大小变化的影响。

  • 在图像查询的系统中,直方图有很大的应用,用它存储目标的特征占有空间小,且执行速度快。

  • 其缺点:因其没有记录位置信息,不同的图像会具有相同或相近的直方图。一幅图像旋转、翻转后的直方图是相同的;放大、缩小后的直方是相近的。

直方图均衡化

原理

为了增强图像整体的对比效果,增加灰度值的动态范围

由图像点运算可知,图像增强的公式可以表示为

G(x,y)=F(g(x,y))

这里,由于要增强对比效果,所以
这里假设原图灰度级范围位为采用归一化的[0,1]

  • F()在整个灰度级范围[0,1]内是递增函数(因为要增强对比)

  • F()的值域也是[0,1]

可以证明累计分布函数满足上面的变换函数要求,而图像中,这个累计分布函数,就是原始图像的累计直方图。
F()通常都是作为查找表LUT出现的,因为是离散的,所以累计直方图也是可以作为LUT出现

实际上:累计分布直方图作为图像变换函数(本质为LUT)。从而将增强了原图像的对比效果。而通常图像变换函数是离散的,通过LUT实现,所以通过累计分布直方图作就可以实现直方图均衡化。

也可以用熵的原理来解释均衡化原理:

熵(Entropy):是信息量的度量,其定义为:

其中, pi是符号 i出现的概率。  在图像中,pr是灰度级r 出现的概率。

可以证明,当p0=p1=p2=…=p255=1/256时,H取最大值,即图像信息量最大。

根据熵理论可知,直方图中,当H[0],H[1]…,H[n-1]相等时,图像信息量最大-》均衡化的目的是使每个Hi都相等,即把原始图的直方图变换为均匀分布的形式,这样就增加了象素值的范围,增强了图像的对比效果。

对于熵这个概念,我也是费了好大的劲才大概能够明白他的意思:

熵越大,系统的不确定性越大,系统越混乱,从而信息量也就越大。

   对于单个信息,可以理解为发生的概率越小  ,熵越大

对于一个系统,如果系统由多个部分组成,则可以理解为各个部分发生概率基本相等时熵最大

关于熵的概念,大家可以参考吴军老师的《数学之美》中关于熵的解释,比较通俗易懂。

直方图均衡化算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void GetHistogramEqualize(BYTE *image_Src,BYTE *image_Dst, int width, int height)
{
    //-------step 1.求灰度直方图
    unsigned long historgam[256];
    GetHistogram(image_Src, width, height, historgam);
 
    //------step 2.求累计分布直方图(灰度变换函数,LUT)
    //累计分布直方图符合增强对比度函数的要求
    int LUT[256];
    LUT[0] = historgam[0];
    int sum = historgam[0];
    for (int i = 1; i <= 255; ++i)
    {
        sum += historgam[i];
        LUT[i] =255* sum / (width*height);
    }
 
    //----step 3.对原图像做图像增强
    int pixelCount = width*height;
    for (int i = 0; i <= pixelCount - 1; ++i)
    {
        int gray = image_Src[i];
        image_Dst[i] = LUT[gray];
         
    }
}

效果图(借助了Opencv来显示图片)

灰度图像--图像增强 直方图均衡化(Histogram equalization)的更多相关文章

  1. 灰度图的直方图均衡化(Histogram Equalization)原理与 Python 实现

    原理 直方图均衡化是一种通过使用图像直方图,调整对比度的图像处理方法:通过对图像的强度(intensity)进行某种非线性变换,使得变换后的图像直方图为近似均匀分布,从而,达到提高图像对比度和增强图片 ...

  2. 灰度图像--图像增强 直方图匹配(规定化)Histogram Specification

    学习DIP第39天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不 ...

  3. 数学之路-python计算实战(14)-机器视觉-图像增强(直方图均衡化)

    我们来看一个灰度图像,让表示灰度出现的次数,这样图像中灰度为 的像素的出现概率是  是图像中全部的灰度数, 是图像中全部的像素数,  实际上是图像的直方图,归一化到 . 把  作为相应于  的累计概率 ...

  4. 直方图均衡化与Matlab代码实现

    昨天说了,今天要好好的来解释说明一下直方图均衡化.并且通过不调用histeq函数来实现直方图的均衡化. 一.直方图均衡化概述 直方图均衡化(Histogram Equalization) 又称直方图平 ...

  5. 图像处理之直方图均衡化及C源码实现

    1 直方图均衡化(Histogram Equalization)简介 图像对比度增强的方法可以分成两类:一类是直接对比度增强方法;另一类是间接对比度增强方法.直方图拉伸和直方图均衡化是两种最常见的间接 ...

  6. OpenCV图像增强算法实现(直方图均衡化、拉普拉斯、Log、Gamma)

    http://blog.csdn.net/dcrmg/article/details/53677739 1. 基于直方图均衡化的图像增强   直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶 ...

  7. python——直方图均衡化

    from PIL import Image from pylab import * from numpy import * def histeq(im,nbr_bins = 256): "& ...

  8. 图像增强 | CLAHE 限制对比度自适应直方图均衡化

    1 基本概述 CLAHE是一个比较有意思的图像增强的方法,主要用在医学图像上面.之前的比赛中,用到了这个,但是对其算法原理不甚了解.在这里做一个复盘. CLAHE起到的作用简单来说就是增强图像的对比度 ...

  9. 【图像增强】CLAHE 限制对比度自适应直方图均衡化

    文章目录: 目录 1 基本概述 2 竞赛中的CLAHE实现 3 openCV绘制直方图 4 对比度Contrast 5 Contrast Stretching 6 Histogram Equaliza ...

随机推荐

  1. C# 操作数据库的几种方式(数据库使用SQL SERVER2008)

    一:通过常规 T-SQL 语句 (只写删除操作,其他同理) string strConn = ConfigurationManager.ConnectionStrings["SiteConn ...

  2. c语言学习之基础知识点介绍(十八):几个修饰关键字和内存分区

    一.几个修饰关键字 全局变量: 全局变量跟函数一样也分为声明和实现.如果是全局变量,实现在它调用之后,那么需要在调用之前进行声明.注意:全局变量的声明只能写在函数外,写在函数就不是全局变量了而是局部变 ...

  3. IOS开发之KVC与KVO简述

    KVC:Key-Value Coding KVO:Key-Value Observing Person.m #import <Foundation/Foundation.h> @inter ...

  4. ECMAScript 6 中的一些新特性

    1.箭头函数,直接写出来v =>看不出来什么,但是跟传统写法一比较,很直观地就能看出v =>是代替了匿名函数 function(v)的写法,{}与逻辑照旧,但是要注意,=与>之间不能 ...

  5. Library string Type

    The string type supports variable-length character strings.The library takes cares of managing memor ...

  6. bzoj1004:[HNOI2008]Cards

    思路:由于题目给出了置换,又要求本质不同的方案数,考虑使用Burnside引理,Burnside引理即通过所有置换和原来相同的方案数之和除以方案数总数,而对于某一个置换要使置换后得到的与原来的相同,就 ...

  7. 桶排序之python实现源码

    tmp = [] def bucket_sort(old): for i in range(len(old)): tmp.append([]) for i in old: tmp[int( i * l ...

  8. [Caffe] ubuntu14.04下使用OpenBLAS加速Caffe

    一.apt安装 sudo apt-get install libopenblas-dev 二.手动从source安装 1. 下载OpenBLAS并编译 git clone https://github ...

  9. [Computer Vision] SIFT特征学习笔记

    SIFT(Scale Invariant Feature Transform),尺度空间不变特征,目前手工设计的最好vision特征. 以下是学习http://blog.csdn.net/zddblo ...

  10. (转载)StringGrid常用属性和常用操作

    Delphi StringGrid常用属性和常用操作 StringGrid组件用于建立显示字符串的网格,与电子表格相似.它可使表格中的字符串和相关对象操作简单化.StringGrid组件提供了许多可控 ...