【OpenCV】calcHist() 计算直方图 (一维直方图、二维直方图)

OpenCV 2.4.13

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 );
//1.输入的图像数组   2.输入数组的个数             3.通道数              4.掩码                5.直方图         
//6.直方图维度       7.直方图每个维度的尺寸数组   8.每一维数组的范围    9.直方图是否是均匀   10.累加标志

 

1.图像数组 

2.图像数组个数

3.图像的通道数

4.图像掩码

5.计算得到的直方图

6.直方图的维度(灰度直方图为1维)

7.直方图每一维度上的数组个数(bin 的个数)

8.每一维进行直方图统计的数组的范围  范围如 0~256 表示统计 0~255的数组 这里注意 (0,256) 包含0而不包含256 包含的是256-1

9.是否均匀的统计(个人理解为是否统计的每个bin包含相同的灰度级 可能理解有误)

10.累加标志   在多幅图像输入时,对其中数据进行累加,单幅图像不进行累计所以例子中为false

以下做个了计算直方图的例子 并进行直方图的显示

​
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

int main()
{
	

	//////////////////////////////////////////////////////////////////////////////////////
	//	1.一维直方图(以灰度直方图为例)				
	//////////////////////////////////////////////////////////////////////////////////////
	
	//以灰度读取图像 得到的图像即为灰度图像
	//cv::Mat sourceImage = cv::imread("1.bmp", cv::IMREAD_GRAYSCALE);	
	
	cv::Mat sourceImage1 = cv::imread("fruits.bmp",cv::IMREAD_COLOR);   //读取彩色图像
	cv::namedWindow("Source Image 1");                                  //显示窗口
	cv::imshow("Source Image 1", sourceImage1);                         //显示原始图像

	cv::Mat grayImage;                                                  //灰度图像
	cv::cvtColor(sourceImage1, grayImage, cv::COLOR_BGR2GRAY);          //将BGR图像转换为HSV格式

	///定义函数需要的一些变量
	int grayImgNum = 1;                                 //图像数
	int grayChannels = 0 ;                              //需要计算的通道号 单通道只有 通道号为0
	cv::Mat grayHist;                                   //灰度图输出直方图
	const int grayHistDim = 1;                          //直方图维数
	const int grayHistSize = 256 ;                      //直方图每一维度bin个数
	float grayRanges[2] = { 0, 255 };                   //灰度值的统计范围
	const float *grayHistRanges[1] = { grayRanges };    //灰度值统计范围指针
	bool grayUniform = true;                            //是否均匀
	bool grayAccumulate = false;                        //是否累积

	//计算灰度图像的直方图
	cv::calcHist( &grayImage, 
                  grayImgNum, 
                  &grayChannels, 
                  cv::Mat(), 
                  grayHist, 
                  grayHistDim, 
                  &grayHistSize, 
                  grayHistRanges, 
                  grayUniform, 
                  grayAccumulate );

	int grayScale = 2;                              //控制图像的宽大小
	int histHeight = 400;                           //直方图显示图像高度
	int binHeight = histHeight-50;                  //绘制时,bin的最大高度

	//直方图的图片,初始全像素值为0
	cv::Mat grayHistImg(histHeight, grayHistSize* grayScale, CV_8UC1, cv::Scalar(0));
	
	//找到最大值和最小值
	double grayMaxValue = 0;
	double grayMinValue = 0;
	cv::minMaxLoc(grayHist, &grayMinValue, &grayMaxValue, NULL, NULL);

	//输出最大值和最小值
	std::cout << "最小值:" << grayMinValue << std::endl;
	std::cout << "最大值:" << grayMaxValue << std::endl;

	

	//进行直方图的绘制
	for (size_t i = 0; i < grayHistSize; i++)
	{
		float bin_val = grayHist.at<float>(i);
		//cvRound返回跟参数最接近的整数值,即四舍五入
		int intensity = cvRound( bin_val * binHeight / grayMaxValue);
		
		// 绘制直线 这里用每scale条竖向直线代表一个bin
		for (size_t j = 0; j < grayScale; j++)
		{
			cv::line( grayHistImg, 
                      cv::Point(i*grayScale + j, histHeight - intensity),
                      cv::Point(i*grayScale + j, histHeight - 1),
                      255 );
		}
		
	}

	cv::namedWindow("grayHistImg");
	cv::imshow("grayHistImg", grayHistImg);
	//cv::waitKey(0);
	//cv::destroyAllWindows();
	
	//////////////////////////////////////////////////////////////////////////////////////
	//	2.二维直方图(以HSV空间的 h,s通道为例)										
	//////////////////////////////////////////////////////////////////////////////////////

	cv::Mat sourceImage2 = cv::imread("flowers.bmp", cv::IMREAD_COLOR);     //读取彩色图像
	cv::namedWindow("Source Image 2");                                      //显示窗口
	cv::imshow("Source Image 2", sourceImage2);                             //显示原始图像

	cv::Mat hsvImage;                                           //hsv图像
	cv::cvtColor(sourceImage2, hsvImage, cv::COLOR_RGB2HSV);    //将R、G、B图像转换为HSV格式

	int hsvImgNum = 1;                                          //图像数
	int hsvChannels[2] = { 0 , 1 };                             //需要计算的通道号 hsv的 0通道和1通道
	cv::Mat hsvHist;                                            //hsv图像的二维直方图
	const int hsvHistDim = 2;                                   //直方图维数
	
	int hBins = 30, sBins = 30;
	const int hsvHistSize[2] = { hBins,sBins };                 //存放每个维度直方图尺寸(bin数量)的数组histSize
	
	float hRanges[2] = { 0,256 };                               //hue的值得统计范围      0-179
	float sRanges[2] = { 0,256 };                               //saturation的统计范围   0-255
	const float *hsvHistRanges[2] = { hRanges , sRanges };      //hsv统计范围的指针
	
	bool hsvUniform = true;                                     //是否均匀
	bool hsvAccumulate = false;                                 //是否累积

	//计算HSV图像的hst通道的二维直方图
	cv::calcHist( &hsvImage,
                  hsvImgNum,
                  hsvChannels,
                  cv::Mat(),
                  hsvHist,
                  hsvHistDim,
                  hsvHistSize,
                  hsvHistRanges,
                  hsvUniform,
                  hsvAccumulate);

	double hsvMaxVal = 0;
	double hsvMinVal = 0;
	minMaxLoc(hsvHist, &hsvMinVal, &hsvMaxVal, 0, 0); //找到直方图矩阵hist中的最大值
	
	int hsvScale = 15;

	//创建直方图画布,画布矩阵中同行的saturation值相同,同列的hue值相同
	cv::Mat hsvHistImage = cv::Mat::zeros(sBins*hsvScale, hBins*hsvScale, CV_8UC3);


	//扫描直方图,填充画布
	for (int i = 0; i<sBins; i++)
	{
		for (int j = 0; j < hBins; j++)
		{
			float binValue = hsvHist.at<float>(i, j);
			//将直方图中的值归一化到0到255
			int intensity = cvRound(binValue * 255 / hsvMaxVal);
			//画矩形柱状图,Point的座标中x值对应着hue维度,y值对应值saturation维度,这与画布矩阵必须一致
			cv::rectangle( hsvHistImage, 
                           cv::Point(i*hsvScale, j*hsvScale), 
                           cv::Point((i + 1)*hsvScale - 1, (j + 1)*hsvScale - 1), 
                           cv::Scalar::all(intensity), 
                           cv::FILLED);
		}
	}

	cv::namedWindow("H-S Histogram");
	cv::imshow("H-S Histogram", hsvHistImage); 
	cv::waitKey(0);
	cv::destroyAllWindows();
	return 0;
}

​

 

结果图:

 

参考:http://blog.csdn.net/sydnash/article/details/7451039

            http://blog.csdn.net/xfortius/article/details/8829246

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章