OpenCV学习---绘制直方图(一维、H-S、RGB)

直方图

简单的说,直方图就是对数据进行统计,将统计值组织到一系列的事先定义好的的 bin 中, bin 的数据是从数据中计算出的特征统计量,这些数据可以是梯度,方向,色彩,或者其它特征。无论如何,直方图获得的是数据分布的统计图。我们最常见的是灰度直方图,也就是统计一副图片中,灰度值的分布情况。

假设有如下的矩阵包含一张8位的灰度图像(0-255)


我们可以对矩阵中的灰度值分布进行统计。首先,我们需要把0-255分成 17 个 区域(bin),如下图所示:


我们对每个范围中的灰度值进行统计排序,做出如下的表格:


我们是以图像的灰度为例子说明这个直方图,当然直方图不仅仅用于灰度特种统计排序,还可以用于图像的梯度、方向等特征。

在以上的过程中,我们使用到一些重要的参数,理解这些参数帮助我们更好的使用API函数。

dims:需要统计的特征的数目,我们上面只统计了 灰度值这个特征,所以, dims =1;

bin :每个特征子区段的数目,上面我们是分成17 个子区段,每个是16个数目,所以,bin =16;

range:每个特征的范围,在上面的例子中,range =  [0, 255];

对于多维的情况,我们下边会举例说明,我们先从一维的开始说起。

直方图计算 calcHist()函数

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 );

绘制图像的一维直方图

int main()
{
	//Load and show image
	Mat src;
	src = imread("D:/Lena.jpg");
	if (!src.data)
	{
		cout<<"Picture loading failed !"<<endl;
		return  -1;
	}
	//Transform gray scale image
	cvtColor(src,src,COLOR_BGR2GRAY);
	// define parameter
	int channels = 0;
	Mat histImage;
	int dims =1;
	float hrange[] = {0,255};
	const float *range[] = {hrange};
	int size = 256;

	calcHist(&src,1,&channels,Mat(),histImage,dims,&size,range,true,false);
	Mat dstImage(size,size,CV_8UC3,Scalar(0,0,0));
	// get minimum
	double maxValue =0;
	minMaxLoc(histImage,0,&maxValue,0,0);
	for (int i=1;i<size;i++)
	{
		float binValue = histImage.at<float>(i);
		//直方图的背景图像的高度是256,但是图像显示一般是在北京的中间比较好,
		//所以把图像的像素归一化为 cvRound(250*0.9) = 230;
		//这样,最大灰度值得统计数目也在就是在(256-230)位置,在图像的中心上下,
		int value = cvRound(binValue*256*0.9/maxValue);

		rectangle(dstImage,Point((i-1),size-1),Point(i, size-value),Scalar(255));
	}
	namedWindow("Win2");
	imshow("Win2",dstImage);
	waitKey(0);
	return 0;
}








绘制图像的H-S直方图



绘制图像的RGB通道直方图

int main()
{	
	//------------------------读取图像------------------------//
	Mat src, dst;
	src = imread("D:/mogu.jpg");
	if (!src.data)
	{
	cout<<"Picture loading failed !"<<endl;
	return  -1;
	}
	namedWindow("Win1");
	imshow("Win1",src);
	//------------------------图像通道的分隔------------------------//
	vector<Mat> rgb_channel;
	split(src, rgb_channel);

	//------------------------计算直方图----------------------------//
	int histsize =256;
	float range[] = {0,256};
	const float* histRange = {range};
	Mat r_Hist,g_Hist,b_Hist;
	calcHist(&rgb_channel[0],1,0,Mat(),b_Hist,1,&histsize,&histRange,true,false);
	calcHist(&rgb_channel[1],1,0,Mat(),g_Hist,1,&histsize,&histRange,true,false);
	calcHist(&rgb_channel[2],1,0,Mat(),r_Hist,1,&histsize,&histRange,true,false);
	namedWindow("Win3");
	imshow("Win3",b_Hist);
	//------------------------归一化----------------------------//
	int hist_h = 400;
	int hist_w = 768;
	int bin_w =hist_w / histsize;
	normalize(b_Hist,b_Hist,0,hist_h,NORM_MINMAX,-1,Mat());
	normalize(g_Hist,g_Hist,0,hist_h,NORM_MINMAX,-1,Mat());
	normalize(r_Hist,r_Hist,0,hist_h,NORM_MINMAX,-1,Mat());
	//------------------------画直方图----------------------------//
	Mat histImage(hist_h,hist_w,CV_8UC3,Scalar(0,0,0));
	for (int i = 1; i<histsize; i++)
	{

		// draw rectangle
		rectangle(histImage, Point(((i-1)*bin_w),hist_h),Point((i*bin_w),hist_h - cvRound(b_Hist.at<float>(i))), Scalar(255,0,0));
		rectangle(histImage, Point(((i-1)*bin_w),hist_h),Point((i*bin_w),hist_h - cvRound(g_Hist.at<float>(i))), Scalar(0,255,0));
		rectangle(histImage, Point(((i-1)*bin_w),hist_h),Point((i*bin_w),hist_h - cvRound(r_Hist.at<float>(i))), Scalar(0,0,255));
	}
	namedWindow("Win2");
	imshow("Win2",histImage);
	waitKey(0);
	return 0;
}








  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值