本文已参与「新人创作礼」活动,一起开启掘金创作之路
一、直方图均衡化数学原理介绍
首先介绍图像直方图的概念,图像的直方图指的是以图像的灰度值(划分)为横轴,图像中所有像素中对应该灰度值(划分)出现的数目(也可归一化)作为纵轴,所构建出的一种直方图,它所描述的是图片整体范围内灰度值的分布情况。如果一张图片的灰度分布过于的集中,呈现出的对比度就较低,人眼难以分辨出,所以我们需要进行直方图均衡化,使得图像的灰度值更加均匀的分布在色彩空间内,大致实现方式则是将像素数目多且更亮的灰度值进行扩展,让它变得更亮;对于那些像素数目少并且不那么亮的灰度值进行归并,让它更暗。
前后对比图如下:
直方图均衡化的数学推导较为复杂,具体过程可见参考文献,现不加证明的给出均衡化前后灰度值变换公式:
设一副图像的像素数目为,共有个灰度划分,代表灰度值处于第个划分的像素数目,像素空间深度为(通常就是255),则第个灰度划分出现的概率为:
变换后的灰度值可表示为:
二、直方图均衡化使用实例
opencv中给出了直方图均衡化函数原型如下:
void equalizeHist( InputArray src, OutputArray dst );
参数即为输入输出图像,应该为8位单通道图像,具有相同大小和类型。
使用实例如下:
int main()
{
Mat src = imread("E:\\material\\lowcontrast.jpg",0);
Mat dst;
if (src.empty())
{
cout << "not found the picture";
return -1;
}
Mat hist1, hist2;
imshow("原图", src);
int histSize = 256;
float range[] = { 0,256 };
const float* histRanges = { range };
calcHist(&src,1,0,Mat(),hist1,1,&histSize,&histRanges);
equalizeHist(src, dst);
calcHist(&dst, 1, 0, Mat(), hist2, 1, &histSize, &histRanges);
imshow("处理后的图", dst);
//创建直方图画布并归一化处理
int hist_h = 600;
int hist_w = 800;
int bin_w = hist_w / histSize;
Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
normalize(hist1, hist1, 0, hist_h, NORM_MINMAX, -1, Mat());
normalize(hist2, hist2, 0, hist_h, NORM_MINMAX, -1, Mat());
//render histogram chart 在直方图画布上画出直方图
for (int i = 1; i < histSize; i++)
{
line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(hist1.at<float>(i - 1))),
Point((i)* bin_w, hist_h - cvRound(hist1.at<float>(i))), Scalar(255, 0, 0));
line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(hist2.at<float>(i - 1))),
Point((i)* bin_w, hist_h - cvRound(hist2.at<float>(i))), Scalar(0, 255, 0));
}
imshow("hist", histImage);
waitKey(0);
}
参考文献