直方图均衡化(Histogram
Equalization)

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

直方图均衡化的主要过程

  • 统计每一个灰度值的像素点数和所占的百分比
  • 累加每一个灰度值的百分比
  • 利用新的灰度值的百分比,重新计算每一个灰度值的变化
  • 将新的的对应的关系映射到新的图像中

一个简单的例子


首先需要说明的是,如果你说的是一道完整的题目,则这道题目没有唯一解,因为题目中没有说明原始图像的灰度级数(比如原始图像是16个灰度级的,或者是32个灰度级的,等等)。为了给你提供一个解题思路,现在人为假设原始图像是16个灰度级的,其它灰度级的解法类似。

1、图像的灰度直方图求法为:

(1)先计算图像中各个灰度级的出现频率,用h(i)表示灰度级i的出现频率,其值等于灰度级出现次数/图像像素个数:

h(0)=2/16

h(1)=1/16

h(2)=3/16

h(3)=2/16

h(4)=0/16

h(5)=1/16

h(6)=4/16

h(7)=1/16

h(8)=1/16

h(9)=1/16

h(10)=h(11)=h(12)=h(13)=h(14)=h(15)=0/16。

然后以灰度级i为横轴,出现频率h(i)为纵轴即可绘制出图像对应的直方图。

(2)图像进行直方图均衡化处理的过程为:

先计算累积分布,用r(i)表示灰度级i的累积分布:

r(0)=h(0)=2/16

r(1)=r(0)+h(1)=2/16+1/16=3/16

r(2)=r(1)+h(2)=3/16+3/16=6/16

r(3)=r(2)+h(3)=6/16+2/16=8/16

r(4)=r(3)+h(4)=8/16+0/16=8/16

r(5)=r(4)+h(5)=8/16+1/16=9/16

r(6)=r(5)+h(6)=9/16+4/16=13/16

r(7)=r(6)+h(7)=13/16+1/16=14/16

r(8)=r(7)+h(8)=14/16+1/16=15/16

r(9)=r(8)+h(9)=15/16+1/16=16/16=1

r(10)=r(11)=r(12)=r(13)=r(14)=r(15)=1

将累积分布进行量化(量化时需要用到原始图像的灰度级数,这也是为什么前面需要说明的原因),量化后的灰度级用rq(i)表示,量化公式为rq(i)=ROUND(r(i)*15),(说明:量化公式中的15等于原始图像灰度级数减1),可得:

rq(0)=ROUND(r(0)*15)=2

rq(1)=ROUND(r(1)*15)=3

rq(2)=ROUND(r(2)*15)=6

rq(3)=ROUND(r(3)*15)=8

rq(4)=ROUND(r(4)*15)=8

rq(5)=ROUND(r(5)*15)=8

rq(6)=ROUND(r(6)*15)=12

rq(7)=ROUND(r(7)*15)=13

rq(8)=ROUND(r(8)*15)=14

rq(9)=ROUND(r(9)*15)=15

rq(10)=ROUND(r(10)*15)=15

rq(11)=ROUND(r(11)*15)=15

rq(12)=ROUND(r(12)*15)=15

rq(13)=ROUND(r(13)*15)=15

rq(14)=ROUND(r(14)*15)=15

rq(15)=ROUND(r(15)*15)=15

因此,原始图像中的灰度级和均化后图像中的灰度级之间的对应关系为:

0->2

1->3

2->6

3->8

4->8

5->8

6->12

7->13

8->14

9->15

10->15

11->15

12->15

13->15

14->15

15->15

将原始图像中对应的灰度值安装上述对应关系替换成相应的灰度值,即可得到均化图像,结果如下:

3  8  13  8

6  12  2  12

14  6  12  8

15  6  12  2

关键的代码实现

[cpp] view
plain
 copy

  1. </pre><pre name="code" class="cpp"><span style="white-space:pre"> </span>Mat src,dest;
  2. <span style="white-space:pre">    </span>Src.copyTo(src);
  3. if (src.channels() > 1)
  4. {
  5. cvtColor(src, src, CV_BGR2GRAY);
  6. }
  7. MatND  hist;
  8. const int histSize = 256;
  9. float range[] = { 0, 255 };
  10. const float *ranges[] = { range };
  11. const int channels = 0;
  12. cv::calcHist(&src, 1, &channels, Mat(), hist, 1, &histSize, ranges);
  13. float total = src.size().width* src.size().height;
  14. float bins[histSize] = { 0 };
  15. float binsAcc[histSize] = { 0 };
  16. Mat lut(1, 256, CV_8U);
  17. vector<float> vectorBins;
  18. vector<float> maxBins;
  19. float sumBins = 0.0;
  20. int countMax = 0;
  21. float TValue = 0;
  22. // Find the mapping table
  23. for (int i = 0; i<histSize; i++)
  24. {
  25. float bin_val = hist.at<float>(i); // 第i灰度级上的数
  26. bins[i] = bin_val / total;
  27. if (bins[i] > 0)
  28. {
  29. vectorBins.push_back(bins[i]);
  30. }
  31. if (i>0)
  32. {
  33. binsAcc[i] =binsAcc[i-1] + bins[i];
  34. }
  35. else
  36. {
  37. binsAcc[0] = bins[0];
  38. }
  39. lut.at<uchar>(i) = static_cast<uchar>(cvRound(binsAcc[i] * 255));
  40. }
利用openCV中均衡化的代码只要一句话:
[cpp] view
plain
 copy

  1. Mat dest2;
  2. equalizeHist(src, dest2);
  3. imshow("equlization2", dest2);


平台直方图及均衡化

平台直方图的概念

这种方法是基于直方图均衡算法的改进算法,它是通过在直方图分布中设计一个阈值T来 对原来直方图进行改造。
这种方法的思路是:如果原直方图中某些灰度级对应的值大于阈值T,就将该处的值设置为T。要是该处的值不大于T时,那么该处的值保持不变。



其中 Pt(k)是平台直方图, Pr(k)是原来的直方图
和直方图均衡类似,对平台直方图进行累加计算,得到累积函数
然后通过均衡化把原图灰度值改为新的灰度值

在这种方法中T的确定是最主要的任务,它的确定方法介绍如下

平台阈值的确定

关键代码实现

[cpp] view
plain
 copy

  1. Mat src,dest;
  2. Src.copyTo(src);
  3. if (src.channels() > 1)
  4. {
  5. cvtColor(src, src, CV_BGR2GRAY);
  6. }
  7. MatND  hist;
  8. const int histSize = 256;
  9. float range[] = { 0, 255 };
  10. const float *ranges[] = { range };
  11. const int channels = 0;
  12. cv::calcHist(&src, 1, &channels, Mat(), hist, 1, &histSize, ranges);
  13. float total = src.size().width* src.size().height;
  14. float bins[histSize] = { 0 };
  15. float binsAcc[histSize] = { 0 };
  16. Mat lut(1, 256, CV_8U);
  17. vector<float> vectorBins;
  18. vector<float> maxBins;
  19. float sumBins = 0.0;
  20. int countMax = 0;
  21. float TValue = 0;
  22. // Find the mapping table
  23. for (int i = 0; i<histSize; i++)
  24. {
  25. float bin_val = hist.at<float>(i); // 第i灰度级上的数
  26. bins[i] = bin_val / total;
  27. if (bins[i] > 0)
  28. {
  29. vectorBins.push_back(bins[i]);
  30. }
  31. }
  32. // Calculate the Meadin value by 3 sapce
  33. for (int i = 1; i < vectorBins.size() - 1; i++)
  34. {
  35. if (vectorBins[i] < vectorBins[i - 1] && vectorBins[i - 1] < vectorBins[i + 1] || vectorBins[i] > vectorBins[i - 1] && vectorBins[i - 1]  > vectorBins[i + 1])
  36. {
  37. vectorBins[i] = vectorBins[i - 1];
  38. }
  39. else if (vectorBins[i] < vectorBins[i + 1] && vectorBins[i + 1] < vectorBins[i - 1] || vectorBins[i] > vectorBins[i + 1] && vectorBins[i + 1] > vectorBins[i - 1])
  40. {
  41. vectorBins[i] = vectorBins[i + 1];
  42. }
  43. }
  44. // Calculate the max peak value
  45. for (int i = 1; i < vectorBins.size() - 1; i++)
  46. {
  47. if (vectorBins[i] - vectorBins[i - 1] >= 0 && vectorBins[i+1] - vectorBins[i] <= 0)
  48. {
  49. maxBins.push_back(vectorBins[i]);
  50. sumBins += vectorBins[i];
  51. countMax++;
  52. }
  53. }
  54. TValue = sumBins / countMax;
  55. // Find the mapping table
  56. for (int i = 0; i<histSize; i++)
  57. {
  58. if (bins[i] > TValue)
  59. {
  60. bins[i] = TValue;
  61. }
  62. if (i>0)
  63. {
  64. binsAcc[i] = binsAcc[i - 1] + bins[i];
  65. }
  66. else
  67. {
  68. binsAcc[0] = bins[0];
  69. }
  70. }
  71. for (int i = 0; i < histSize; i++)
  72. {
  73. lut.at<uchar>(i) = static_cast<uchar>(cvRound(binsAcc[i] * 255 / binsAcc[255]));
  74. }
  75. LUT(src, lut, dest);
  76. imshow("src", src);
  77. imshow("equlization", dest);

欢迎转载,请注明本文的出处:http://blog.csdn.net/fioletfly/article/details/51011399  谢谢!


【VS开发】【图像处理】直方图均衡与平台直方图的更多相关文章

  1. 基于C#和Asp.NET MVC开发GPS部标监控平台

    基于交通部796标准开发部标监控平台,选择开发语言和技术也是团队要思考的因素,其实这由团队自己擅长的技术来决定,如果擅长C#和Asp.NET, 当然开发效率就高很多.当然了技术选型一定要选用当前主流的 ...

  2. 【原创】开发Kafka通用数据平台中间件

    开发Kafka通用数据平台中间件 (含本次项目全部代码及资源) 目录: 一. Kafka概述 二. Kafka启动命令 三.我们为什么使用Kafka 四. Kafka数据平台中间件设计及代码解析 五. ...

  3. 目前网络上大部分的网站都是由ASP或PHP开发,并且java平台的软件购买成本不适合中小企业客户,一般适用于银行、国家安全等行业领域

    目前网络上大部分的网站都是由ASP或PHP开发,并且java平台的软件购买成本不适合中小企业客户,一般适用于银行.国家安全等行业领域. 要求建设开发大型复杂的网站,但仅有一个idea,不能够提供网站详 ...

  4. C#开发微信公众化平台

     C#开发微信公众化平台 写在前面 服务号和订阅号 URL配置 创建菜单 查询.删除菜单 接受消息 发送消息(图文.菜单事件响应) 示例Demo下载 后记 最近公司在做微信开发,其实就是接口开发,网上 ...

  5. Arduino可穿戴开发入门教程Windows平台下安装Arduino IDE

    Arduino可穿戴开发入门教程Windows平台下安装Arduino IDE Windows平台下安装Arduino IDE Windows操作系统下可以使用安装向导和压缩包形式安装.下面详细讲解这 ...

  6. Win8 Metro(C#)数字图像处理--3.3图像直方图计算

    原文:Win8 Metro(C#)数字图像处理--3.3图像直方图计算 /// <summary> /// Get the array of histrgram. /// </sum ...

  7. .NET Core开发的iNeuOS物联网平台部署树霉派,从网关到云端整体解决方案。助力2019中国.NET峰会。

    2019 中国.NET 开发者峰会正式启动 目       录 1.      概述... 2 2.      树莓派硬件配置... 2 3.      软件信息... 3 4.      Raspb ...

  8. [视频演示].NET Core开发的iNeuOS物联网平台,实现从设备&PLC、云平台、移动APP数据链路闭环

    目       录 1.      概述... 1 2.      登陆信息... 2 3.      设备驱动... 3 4.      组态建模... 3 5.      手机APP. 5 6.  ...

  9. .NET Core开发的iNeuOS物联网平台部署树霉派(raspbian),从网关到云端整体解决方案。助力2019中国.NET峰会。

    2019 中国.NET 开发者峰会正式启动 目       录 1.      概述... 2 2.      树莓派硬件配置... 2 3.      软件信息... 3 4.      Raspb ...

随机推荐

  1. webpack编译sass报错找不到module /css-loader/index.js... || 安装node-sass报错

    今天无论在家还是在公司,安装node-sass总是失败,或安装成功了,使用webpack编译sass报错,说找不到module,按照提示的错误我找了node_modules下的css-loader,发 ...

  2. 【leetcode】1286. Iterator for Combination

    题目如下: Design an Iterator class, which has: A constructor that takes a string characters of sorted di ...

  3. 【leetcode】1275. Find Winner on a Tic Tac Toe Game

    题目如下: Tic-tac-toe is played by two players A and B on a 3 x 3 grid. Here are the rules of Tic-Tac-To ...

  4. CSS3—HSL与HSLA属性

    ㈠HSL(H,S,L) ⑴通过对色相(H).饱和度(S).明度(L)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色 ⑵取值 H:Hue(色调).0(或360)表示红色,120表示绿色,2 ...

  5. MessagePack Java 0.6.X 可选字段

    你可添加一个新的字段来保持可用性.在新字段中使用 @Optional 注解. @Message public static class MyMessage {     public String na ...

  6. Codeforces 979 D. Kuro and GCD and XOR and SUM(异或和,01字典树)

    Codeforces 979 D. Kuro and GCD and XOR and SUM 题目大意:有两种操作:①给一个数v,加入数组a中②给出三个数x,k,s:从当前数组a中找出一个数u满足 u ...

  7. Python + cx_Orcale 连接Oracle数据库

    这是我在使用python连接Oracle数据库时遇到的问题.在此做一下总结. 1.pip install cx_Oracle 2.然后还需要在下载一个数据库客户端工具instantclient-bas ...

  8. Centos系统下载

    在学习或者工作当中,难免会用到不同版本的CentOS镜像,下面就简单的介绍一下如何正确并快速的下载所需要的CentOS镜像. 一.官网下载 官网地址:https://www.centos.org/此种 ...

  9. Linux用户以及组的添加与删除

    查看centos中的用户和用户组 1.用户列表文件:/etc/passwd/ 2.用户组列表文件:/etc/group 3.查看系统中有哪些用户: cut -d : -f 1 /etc/passwd ...

  10. PHP-异常-1

    PHP 错误处理 在 PHP 中,默认的错误处理很简单.一条消息会被发送到浏览器,这条消息带有文件名.行号以及一条描述错误的消息. 在创建脚本和 web 应用程序时,错误处理是一个重要的部分.如果您的 ...