概述
C++OpenCV下绘制直方图
直方图的定义:灰度直方图是对一幅灰度图像素分布的统计。对于一幅8Bit量化的图像来说。就是统计在0~255各个灰度级上,像素点的个数或者密度。
在OpenCV库提供了
calcHist()方法用于得到图像的直方图。
具体函数的调用方法如下:
void cv::calcHist(const Mat*images,int nimages,const int *channels,InputArrary mask,OutputArrary hist,int dims,const int* histSize,const float **ranges,bool uniform=true,bool accumulate=false)
//参数说明
//images:带统计直方图的图像数组
//nimages:输入图像的数目
//channels:需要统计的通道索引数组 一般灰度图就是0通道
//mask:掩码 一般填Mat()
//hist:输出的统计直方图结果,是一个dims维度的数组。不过用OpenCV中Mat类型的变量存储
//dims:hist的列数、需要计算直方图的维度
//histSize:存放每个维度直方图数组的尺寸
//ranges:每个通道灰度值的取值范围
根据以上参数,设计了一个获取直方图Mat数组Hist的函数
//@para gray:需要统计的图 Hist:用于存放统计数据
void GetHist(Mat gray,Mat &Hist) //统计8Bit量化图像的灰度直方图
{
const int channels[1] = { 0 }; //通道索引
float inRanges[2] = { 0,255 }; //像素范围
const float* ranges[1] = {inRanges};//像素灰度级范围
const int bins[1] = { 256 }; //直方图的维度
calcHist(&gray, 1, channels,Mat(), Hist,1, bins, ranges);
}
这里得gray为测试灰度图。看下运行完calcHist函数后,Hist的维数。
可以看到Hist就是一个256行1列Mat类型的变量,可以看做一个数组索引。
这样我们就可以根据这个Hist画图。
这里设计一个ShowHist函数,主要的步骤就是申请一块背景为纯黑的图像,再根据Hist的值转化为点坐标从而画出一个个白色的矩形以完成直方图的绘制。
void ShowHist(Mat &Hist)
{
//准备绘制直方图
int hist_w = 512;
int hist_h = 400;
int width = 2;
Mat histImage = Mat::zeros(hist_h,hist_w,CV_8UC3); //准备histImage为全黑背景色,大小为512*400
for (int i = 0; i < Hist.rows; i++)
{
rectangle(histImage,Point(width*(i),hist_h-1),Point(width*(i+1),hist_h-cvRound(Hist.at<float>(i)/20)),
Scalar(255,255,255),-1);
}
namedWindow("histImage", WINDOW_AUTOSIZE);
imshow("histImage", histImage);
//waitKey(0);
}
首先准备一幅512*400的全黑背景图histImage,接下来通过Hist.rows遍历每个灰度级的像素个数。通过Rectangle函数画出白色的矩形。最后的-1代表绘制的矩形是填充矩形。对于Rectangle,重点分析下两个Point的含义。
@param pt1 Vertex of the rectangle.
@param pt2 Vertex of the rectangle opposite to pt1 .
上面是官方给出的注释,pt1为矩形的一个顶点,pt2为矩形对角线上的另一个顶点。
首先看横坐标,一个矩形的横坐标长度应该为一个像素级所占的长度,这里我们假定一个像素级占长度为width=2。pt1的横坐标值为width*(i),pt2的横坐标值为width*(i+1);
再看纵坐标,首先需要明白图像的坐标系,它是这样的:
pt1的纵坐标为:hist_h-1相当于图像最下面,也就是矩形的左下角。pt2的纵坐标应该是矩形的右上角才对,hist_h-cvRound(Hist.at<float>(i)/20),cvRound是4舍5入,Hist.at<float>(i)取出在该像素级上像素点的个数,这个数字可能远远大于hist_h(512),因为直方图我们只希望看到图像像素级分布的大致,所以我们除以一个20保证不会超出图像的边界。
最后给出我主函数的调用:
int main(int argc,char *argv)
{
Mat src,gray,hist; //hist用于统计gray的直方图
src=imread("2.jpg");
cvtColor(src,gray,CV_BGR2GRAY);
GetHist(gray,hist);
ShowHist(hist);
namedWindow("gray");
imshow("gray",gray);
waitKey(0);
return 0;
}
结果:
总结分析:其实图像的直方图只能告诉我们图像像素级别的分布如何,可以定性的帮助我们判断图像对比度,以及亮度的分布情况,如果想通过直方图进行操作,还是得借助calcHist得到的Hist数组对其进行定量的操作。
最后
以上就是舒心小猫咪为你收集整理的C++OpenCV下绘制灰度直方图的全部内容,希望文章能够帮你解决C++OpenCV下绘制灰度直方图所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复