文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏
参与翻译: magiaPants (2), toypipi (1), CY2 (1)

目标

在此教程中你会学习到:

  • 什么是图像直方图和为什么它是有用的
  • 用OpenCV函数 equalizeHist 对图像进行直方图均衡化

原理

图像的直方图是什么?

  • 直方图是图像中像素强度分布的图形表达方式.
  • 它统计了每一个强度值所具有的像素个数.

直方图均衡化是什么?

  • 直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法.
  • 说得更清楚一些, 以上面的直方图为例, 你可以看到像素主要集中在中间的一些强度值上. 直方图均衡化要做的就是 拉伸 这个范围. 见下面左图: 绿圈圈出了 少有像素分布其上的强度值. 对其应用均衡化后, 得到了中间图所示的直方图. 均衡化的图像见下面右图.
第 1 段(可获 2 积分)

它是如何工作的?

  • 均衡化指的是把一个分布 (给定的直方图) 映射 到另一个分布 (一个更宽更统一的强度值分布), 所以强度值分布会在整个范围内展开.

  • 要想实现均衡化的效果, 映射函数应该是一个 累积分布函数 (cdf)(更多细节, 参考Learning OpenCV一书).。对于直方图 H(i),它的 累积分布H^{'}(i) 是:

    H^{'}(i) = \sum_{0 \le j < i} H(j)

    要使用其作为映射函数, 我们必须对最大值为255 (或者用图像的最大强度值) 的累积分布 H^{'}(i) 进行归一化. 同上例, 累积分布函数为:

    ../../../../../_images/Histogram_Equalization_Theory_2.jpg
  • 最后, 我们使用一个简单的映射过程来获得均衡化后像素的强度值:

    equalized( x, y ) = H^{'}( src(x,y) )

第 2 段(可获 2 积分)

代码

  • 程序的功能?

    • 加载图片
    • 将原图转成灰度图
    • 使用 OpenCV 的函数 EqualizeHist 直方均衡化处理
    • 在窗口中显示原图和处理后的图像
  • 下载代码请点击 这里

  • 完整代码

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

/**  @function main */
int main( int argc, char** argv )
{
  Mat src, dst;

  char* source_window = "Source image";
  char* equalized_window = "Equalized Image";

  /// Load image
  src = imread( argv[1], 1 );

  if( !src.data )
    { cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;
      return -1;}

  /// Convert to grayscale
  cvtColor( src, src, CV_BGR2GRAY );

  /// Apply Histogram Equalization
  equalizeHist( src, dst );

  /// Display results
  namedWindow( source_window, CV_WINDOW_AUTOSIZE );
  namedWindow( equalized_window, CV_WINDOW_AUTOSIZE );

  imshow( source_window, src );
  imshow( equalized_window, dst );

  /// Wait until user exits the program
  waitKey(0);

  return 0;
}
第 3 段(可获 2 积分)

说明

  1. 声明原图和目标图以及窗体名称:

    Mat src, dst;
    
    char* source_window = "Source image";
    char* equalized_window = "Equalized Image";
    
  2. 加载源图像:

    src = imread( argv[1], 1 );
    
    if( !src.data )
      { cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;
        return -1;}
    
  3. 转为灰度图:

    cvtColor( src, src, CV_BGR2GRAY );
    
  4. 利用函数 equalizeHist 对上面灰度图做直方图均衡化:

    equalizeHist( src, dst );
    

    可以看到, 这个操作的参数只有源图像和目标 (均衡化后) 图像.

  5. 显示这两个图像 (源图像和均衡化后图像) :

    namedWindow( source_window, CV_WINDOW_AUTOSIZE );
    namedWindow( equalized_window, CV_WINDOW_AUTOSIZE );
    
    imshow( source_window, src );
    imshow( equalized_window, dst );
    
  6. 等待用户案件退出程序

    waitKey(0);
    return 0;
    

结果

  1. 为了更好地观察直方图均衡化的效果, 我们使用一张对比度不强的图片作为源图像输入, 如下图:

    ../../../../../_images/Histogram_Equalization_Original_Image.jpg

    它的直方图为:

    ../../../../../_images/Histogram_Equalization_Original_Histogram.jpg

    注意到像素大多集中在直方图中间的强度上.

  2. 使用例程进行均衡化后, 我们得到下面的结果:

    ../../../../../_images/Histogram_Equalization_Equalized_Image.jpg

    使用例程进行均衡化后, 我们得到下面的结果:

    ../../../../../_images/Histogram_Equalization_Equalized_Histogram.jpg

    注意到现在像素在整个强度范围内均衡分布.

 

你们想知道上面的直方图是怎样绘制出来的吗? 请关注接下来的教程!

第 4 段(可获 2 积分)

文章评论