均衡化指的是把一个分布 (给定的直方图) 映射 到另一个分布 (一个更宽更统一的强度值分布), 所以强度值分布会在整个范围内展开.
要想实现均衡化的效果, 映射函数应该是一个 累积分布函数 (cdf) (更多细节, 参考*学习OpenCV*). 对于直方图 , 它的 累积分布
是:
要使用其作为映射函数, 我们必须对最大值为255 (或者用图像的最大强度值) 的累积分布 进行归一化. 同上例, 累积分布函数为:
最后, 我们使用一个简单的映射过程来获得均衡化后像素的强度值:
咋个例程是用来干嘛的?
下载例程: 点击 这里
例程一瞥:
#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";
/// 加载源图像
src = imread( argv[1], 1 );
if( !src.data )
{ cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;
return -1;}
/// 转为灰度图
cvtColor( src, src, CV_BGR2GRAY );
/// 应用直方图均衡化
equalizeHist( src, dst );
/// 显示结果
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
namedWindow( equalized_window, CV_WINDOW_AUTOSIZE );
imshow( source_window, src );
imshow( equalized_window, dst );
/// 等待用户按键退出程序
waitKey(0);
return 0;
}
声明原图和目标图以及窗体名称:
Mat src, dst;
char* source_window = "Source image";
char* equalized_window = "Equalized Image";
加载源图像:
src = imread( argv[1], 1 );
if( !src.data )
{ cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;
return -1;}
转为灰度图:
cvtColor( src, src, CV_BGR2GRAY );
利用函数 equalizeHist 对上面灰度图做直方图均衡化:
equalizeHist( src, dst );
可以看到, 这个操作的参数只有源图像和目标 (均衡化后) 图像.
显示这两个图像 (源图像和均衡化后图像) :
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
namedWindow( equalized_window, CV_WINDOW_AUTOSIZE );
imshow( source_window, src );
imshow( equalized_window, dst );
等待用户案件退出程序
waitKey(0);
return 0;
为了更好地观察直方图均衡化的效果, 我们使用一张对比度不强的图片作为源图像输入, 如下图:
它的直方图为:
注意到像素大多集中在直方图中间的强度上.
使用例程进行均衡化后, 我们得到下面的结果:
这幅图片显然对比度更强. 再验证一下均衡化后图片的直方图:
注意到现在像素在整个强度范围内均衡分布.
Note
你们想知道上面的直方图是怎样绘制出来的吗? 请关注接下来的教程!
zhlifly@ OpenCV中文网站 <zhlifly@gmail.com>