OpenCV3入门(十一)图像直方图
1、直方图的概念
灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像元的个数。确定图像像素的灰度值范围,以适当的灰度间隔为单位将其划分为若干等级,以横轴表示灰度级,以纵轴表示每一灰度级具有的像素数或该像素占总像元数的比例值,做出的条形统计图即为灰度直方图。灰度直方图:横坐标是灰度,纵坐标是该灰度在图像中出现的次数。
图像直方图可以表示图像中亮度分布,能借助直方图了解需要如何调整亮度分布,直方图中左侧表示黑色、较暗的区域,右侧表示白色、较亮的区域。计算机视觉领域常借助直方图来实现图像的二值化。
2、OpenCV直方图
OpenCV使用calcHist函数实现直方图计算,函数原型如下图。
CV_EXPORTS void calcHist( const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform = true, bool accumulate = false );
参数详解:
onst Mat* images:输入图像组
int nimages:输入图像的个数
const int* channels:需要统计直方图的第几通道
InputArray mask:掩膜,计算掩膜内的直方图
OutputArray hist:输出的直方图的数组
int dims:直方图的维度,需要统计直方图通道的个数
const int* histSize:指的是直方图分成多少个区间,就是 bin的个数
const float** ranges: 统计像素值的区间,每个维度数值的取值范围
bool uniform=true:是否对得到的直方图数组进行归一化处理
bool accumulate=false:在多个图像时,是否累计计算像素值得个数
测试代码如下:
Mat src = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\img1.bmp"); imshow("原图", src); MatND dstHist; int dims = 1; float hranges[] = { 0,255 }; const float *ranges[]= { hranges }; int size = 256; int channels = 0; calcHist(&src, 1, &channels, Mat(), dstHist, dims, &size, ranges); double maxVal = 0; double minVal = 0; cv::minMaxLoc(dstHist, &minVal, &maxVal, 0, 0); Mat histImg(size, size, CV_8U, cv::Scalar(0)); int hpt = static_cast<int>(0.9*size); for (int h = 0; h < 256; h++) { float binVal = dstHist.at<float>(h); int intensity = static_cast<int>(binVal * hpt / maxVal); cv::line(histImg, Point(h, size-1), Point(h+1, size-1 - intensity), Scalar::all(255)); } imshow("直方图", histImg); waitKey(0);
输出结果为:
如果是彩色图像,则可以计算RGB通道各自的直方图。
测试代码如下:
Mat src = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic5.bmp"); imshow("原图", src); int histsize = 256; float range[] = { 0,256 }; const float*histRanges = { range }; vector<Mat>bgr_planes; split(src, bgr_planes); Mat b_hist, g_hist, r_hist; calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histsize, &histRanges, true, false); calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histsize, &histRanges, true, false); calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histsize, &histRanges, true, false); Mat histImg = Mat::zeros(256, 256*3, CV_8UC3); for (int h = 0; h < 256; h++) { float binVal_r = r_hist.at<float>(h); float binVal_g = g_hist.at<float>(h); float binVal_b = b_hist.at<float>(h); rectangle(histImg, Point(h, 256 - 1), Point(h + 1, 256 - binVal_r), Scalar(255, 0, 0)); rectangle(histImg, Point(h+255, 256 - 1), Point(h +255+ 1, 256 - binVal_g), Scalar(0, 255, 0)); rectangle(histImg, Point(h+510, 256 - 1), Point(h + 510+ 1, 256 - binVal_b), Scalar(0, 0, 255)); } imshow("直方图", histImg);
输出结果为:
3、直方图均衡化
直方图均衡化即灰度均衡化,通过灰度映射,使输入图像的灰度转换为在每一级灰度上都有近似相同的点数分布,这样输出的直方图就是均匀的,图像获得较高的对比度和较大的动态范围。直方图均衡化对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。使用直方图均衡化技术来处理图像,能扩展图像的动态范围,扩宽灰度等级范围,提高对比度。
直方图均衡化可以调整较暗的图片,图片较暗,动态范围低,直方图灰度等级偏暗,均衡化后灰度基本平均分布。。
使用直方图均衡化,在处理较暗的图像时特别有效,如下测试。
Mat blue, green, red, dst; blue = bgr_planes[0]; green = bgr_planes[1]; red = bgr_planes[2]; equalizeHist(blue, blue); equalizeHist(green, green); equalizeHist(red, red); merge(bgr_planes, 3, dst); imshow("均衡化图", dst); vector<Mat> bgr_planes2; split(dst, bgr_planes2); calcHist(&bgr_planes2[0], 1, 0, Mat(), b_hist, 1, &histsize, &histRanges, true, false); calcHist(&bgr_planes2[1], 1, 0, Mat(), g_hist, 1, &histsize, &histRanges, true, false); calcHist(&bgr_planes2[2], 1, 0, Mat(), r_hist, 1, &histsize, &histRanges, true, false); histImg = Mat::zeros(256, 256 * 3, CV_8UC3); for (int h = 0; h < 256; h++) { float binVal_r = r_hist.at<float>(h); float binVal_g = g_hist.at<float>(h); float binVal_b = b_hist.at<float>(h); rectangle(histImg, Point(h, 256 - 1), Point(h + 1, 256 - binVal_r), Scalar(255, 0, 0)); rectangle(histImg, Point(h + 255, 256 - 1), Point(h + 255 + 1, 256 - binVal_g), Scalar(0, 255, 0)); rectangle(histImg, Point(h + 510, 256 - 1), Point(h + 510 + 1, 256 - binVal_b), Scalar(0, 0, 255)); }
输出图像对比:
处理后的图片亮度提高,动态范围扩大,这里有一个问题,由于是全局处理,车牌由于反光材料本来就属于最亮的区域,均衡化后更亮了,导致车牌亮度过曝反而更加难识别了,所以需要特定的直方图处理。
对比直方图:
5、参考文献
1、《OpenCV3 编程入门》,电子工业出版社,毛星雨著
2、《学习OpenCV》,清华大学出版社,Gary Bradski, Adrian kaehler著
3、OpenCV图像直方图
https://blog.csdn.net/leonardohaig/article/details/88240112
4、图像处理基础(8):图像的灰度直方图、直方图均衡化、直方图规定化(匹配)
https://www.cnblogs.com/wangguchangqing/p/7098213.html
5、OpenCV实现图像的直方图处理
https://www.cnblogs.com/noticeable/p/10449867.html
6、【OpenCV学习笔记】之直方图(Histogram)
https://blog.csdn.net/zhu_hongji/article/details/81663161
技术博客,转载请注明。