【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

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