当前位置:   article > 正文

直方图均衡化算法原理与c++实现_直方图均衡算法和那个算法合起来一起用

直方图均衡算法和那个算法合起来一起用

写在前面

直方图均衡是图像增强的基础算法,本质上是一种非线性拉伸,使图像的灰度级分布变得较为均匀,从而增强图像的对比度,使这些不够明显的图像细节清晰可见。掌握一种算法,必须要弄清楚它的优势和缺点,要知道它的适用场合,这样才能灵活的运用这些算法。

直方图均衡算法的优势:对于背景和前景都太亮或者太暗的图像非常有用,计算量不大,完全可以满足实时。并且是可逆操作,也就是说如果已知均衡化函数,那么就可以恢复原始的直方图。放张图片吧:

                                                                  

 直方图均衡算法的缺点:它也有缺陷,它对数据的处理是不加选择的,也就是说,它可能会增加背景噪声的对比度并且降低有用信号的对比度。所以对于特征提取要求比较高的场合慎用,看下图:

                                        

 

算法原理

直方图均衡的目标是要让图像的灰度级分布均匀,但是同时需要保证输出的灰度级不少于相应的输入灰度级(少了就丢失信息了),且保证输出的灰度范围与输入灰度范围相同,因此对于变换函数f(x)需要满足如下条件:

  1. f(x)在0<=x<=L−1上单调递增,其中L表示灰度级数量(例如8bit图L=256)
  2. f(x)的范围是[0,L−1]

那么根据冈萨雷斯的书中介绍,在图像处理中,有一个重要的函数,能够满足上面的条件: 

                                           

那么为什么经过它变换后的直方图是均匀的呢,这就涉及了概率论的知识,具体的推导可以看这篇:

https://blog.csdn.net/qianqing13579/article/details/52422364

我们注意到,图像是离散的,可以使用求和代替积分,差分代替微分,所以上述的变换函数就是:

                                          

其中h(xi)表示直方图中每个灰度级像素的个数, ww和 hh分别表示图像的宽和高。

上式就被称为直方图均衡化。

 

代码实现

  1. #include <iostream>
  2. #include <opencv2/core.hpp>
  3. #include <opencv2/highgui.hpp>
  4. #include <opencv2/imgproc.hpp>
  5. void Histogram_equalization(cv::Mat& src, cv::Mat& dst){
  6. CV_Assert(src.depth() == CV_8U);
  7. src.copyTo(dst);
  8. int nr = src.rows;
  9. int nc = src.cols;
  10. int pixnum = nr*nc;
  11. if (src.channels() == 1){
  12. //统计直方图
  13. int gray[256] = { 0 };
  14. for (int i = 1; i < nr; ++i){
  15. const uchar* ptr = src.ptr<uchar>(i);
  16. for (int j = 0; j < nc; ++j){
  17. gray[ptr[j]]++;
  18. }
  19. }
  20. //计算分布函数
  21. int LUT[256];
  22. int sum = 0;
  23. for (int k = 0; k < 256; k++){
  24. sum = sum + gray[k];
  25. LUT[k] = 255 * sum / pixnum;
  26. }
  27. //灰度变换(赋值)
  28. for (int i = 1; i < nr; ++i){
  29. const uchar* ptr_src = src.ptr<uchar>(i);
  30. uchar* ptr_dst = dst.ptr<uchar>(i);
  31. for (int j = 0; j < nc; ++j){
  32. ptr_dst[j] = LUT[ptr_src[j]];
  33. }
  34. }
  35. }
  36. else{
  37. //统计直方图
  38. int B[256] = { 0 };
  39. int G[256] = { 0 };
  40. int R[256] = { 0 };
  41. for (int i = 0; i < nr; ++i){
  42. for (int j = 0; j < nc; ++j){
  43. B[src.at<cv::Vec3b>(i, j)[0]]++;
  44. G[src.at<cv::Vec3b>(i, j)[1]]++;
  45. R[src.at<cv::Vec3b>(i, j)[2]]++;
  46. }
  47. }
  48. //计算分布函数
  49. int LUT_B[256], LUT_G[256], LUT_R[256];
  50. int sum_B = 0, sum_G = 0, sum_R = 0;
  51. for (int k = 0; k < 256; k++){
  52. sum_B = sum_B + B[k];
  53. sum_G = sum_G + G[k];
  54. sum_R = sum_R + R[k];
  55. LUT_B[k] = 255 * sum_B / pixnum;
  56. LUT_G[k] = 255 * sum_G / pixnum;
  57. LUT_R[k] = 255 * sum_R / pixnum;
  58. }
  59. //灰度变换(赋值)
  60. for (int i = 0; i < nr; ++i){
  61. for (int j = 0; j < nc; ++j){
  62. dst.at<cv::Vec3b>(i, j)[0] = LUT_B[src.at<cv::Vec3b>(i, j)[0]];
  63. dst.at<cv::Vec3b>(i, j)[1] = LUT_G[src.at<cv::Vec3b>(i, j)[1]];
  64. dst.at<cv::Vec3b>(i, j)[2] = LUT_R[src.at<cv::Vec3b>(i, j)[2]];
  65. }
  66. }
  67. }
  68. }
  69. int main(){
  70. cv::Mat src = cv::imread("..../art.jpg");
  71. if (src.empty()){
  72. return -1;
  73. }
  74. cvtColor(src, src, CV_RGB2GRAY);
  75. cv::Mat dst;
  76. Histogram_equalization(src, dst);//直方图均衡
  77. cv::namedWindow("src");
  78. cv::imshow("src", src);
  79. cv::namedWindow("dst");
  80. cv::imshow("dst", dst);
  81. cv::waitKey(0);
  82. }

效果: 

原图
输出
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/78942
推荐阅读
相关标签
  

闽ICP备14008679号