25 二维直方图

25 二维直方图

opencv知识点:

  • 计算直方图数据 - calcHist
  • 四舍五入浮点数 - cvRound
  • 寻找最小/最大值 - minMaxLoc

本课所解决的问题:

  • 如何绘制HSV图像的二维直方图?

1.二维直方图

上节课中,我们学习了一维直方图的绘制,那我们该如何绘制二维直方图呢?

关于二维直方图的绘制,我们通常选择HSV模式下的图像

我们回顾HSV的知识,可以发现

  • H(色调)范围是[0,180]

  • S(饱和度)范围是[0,255]

  • V(明度)范围是[0,255]

即HS两个通道就可以表示颜色,非常方便二维直方图的绘制

opencv中,如果我们想绘制二维维直方图,要用到三个API

  • calcHist
  • cvRound
  • minMaxLoc

介绍如下

calcHist#

calcHist
	计算一维数组的直方图(输入图像可以有多通道)
10个参数
1个参数 图像数组
2个参数 输入图像数量
3个参数 通道数组
4个参数 可选mask
			
5个参数 输出直方图数据(值与对应频次)的n维数组
6个参数 直方图维数

					当通道为1个时,我们选择维度为1维,此时直方图数据就为一维数组
					当维度为2个时,我们选择维度为2维,此时直方图数据就为二维数组
					………………
					最大支持32					
					也就是说,n张图像 每张图像m个通道 可以计算出相应的直方图数据
					
					但对于绘制来说,一般都只绘制到2维,3维及以上就很复杂了

7个参数 histSize( bins数组,x轴长度)
8个参数 ranges(取值范围数组)
			
			//以下参数暂时用不到
9个参数 指示直方图bin间隔是否一致
						默认为true,即等间隔取值
						如果为false,则range不能写{0,255}这种,就要写{1,1,……,1}这种
								
10个参数 累计标志(默认为false				    	当多张图像的时候,
				    		如果为true,则绘制直每张方图的时候,不会从头清空
				    		会在前者直方图的基础上继续

cvRound#

cvRound
	将浮点数四舍五入到最近的整数
1个参数
1个参数 要处理的浮点数

minMaxLoc#

minMaxLoc
	寻找最小/最大值
5个参数 
1个参数 输入
2个参数 输出的最小值
3个参数 输出的最大值
4个参数 最小值下标
5个参数 最大值下标

2.绘制二维直方图

本课中计算的直方图维数为2维,采取方式为

  • 先转换色彩空间为HSV
  • 然后进行每个通道的直方图数据计算,得到二维数组
  • 最后利用直方图二维数组绘制直方图

我们先来输出一下得到的直方图数据

//函数定义
void histogram_2d_demo(Mat& image);

//函数实现
void QuickDemo::histogram_2d_demo(Mat& image) {
	
	// 2D 直方图
	Mat hsv, hs_hist;
	cvtColor(image, hsv, COLOR_BGR2HSV);

	int hbins = 30;
	int sbins = 32;
	int hist_bins[] = { hbins, sbins };
	
	float h_range[] = { 0, 180 };
	float s_range[] = { 0, 256 };
	const float* hs_ranges[] = { h_range, s_range };
	
	int hs_channels[] = { 0, 1 };
	
	calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges);

	std::cout << hs_hist;
}

可以看见,不同于上一课的256 * 1的列矩阵,这里变成了30 * 32的二维矩阵

465a41698861441ebe8a8a89549f3193

接下来,我们开始绘制二维直方图

//函数实现
void QuickDemo::histogram_2d_demo(Mat& image) {
	
	// 2D 直方图
	Mat hsv, hs_hist;
	cvtColor(image, hsv, COLOR_BGR2HSV);


	int hbins = 30;
	int sbins = 32;
	int hist_bins[] = { hbins, sbins };
	
	float h_range[] = { 0, 180 };
	float s_range[] = { 0, 256 };
	const float* hs_ranges[] = { h_range, s_range };
	
	int hs_channels[] = { 0, 1 };
	
	calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges);

	std::cout << hs_hist;

	double maxVal = 0;//寻找直方图数据中的最大值
	minMaxLoc(hs_hist, 0, &maxVal, 0, 0);


	int scale = 10;
	//行320 列300
	Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3);

	//h30行,s32列,一行一行的绘制矩形
	for (int h = 0; h < hbins; h++) {
		for (int s = 0; s < sbins; s++)
		{
			float binVal = hs_hist.at<float>(h, s);//位于横h,列s处的频次

			int intensity = cvRound(binVal * 255 / maxVal);//白色的强度,频次越大,小矩形越接近白色

			Point p1(h * scale, s * scale);
			/*
				矩形左上角的点
			*/
			Point p2((h + 1) * scale - 1, (s + 1) * scale - 1);
			/*
				矩形右下角的点
				-1只是为了不与其他矩形的左上角重合,不-1差异也不大
			*/

			rectangle(hist2d_image, p1, p2, Scalar::all(intensity), -1);
		}
	}

	//灰色的图像不容看出差异,这里我们转换色彩风格
	applyColorMap(hist2d_image, hist2d_image,COLORMAP_DEEPGREEN);

	imshow("H-S Histogram", hist2d_image);

}

cb0cfdba4d364e7d9bb53283bdb71570

本课所用API查阅

calcHist#

cvRound#

minMaxLoc#

posted @   L707  阅读(251)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
主题色彩