OpenCV提供了calcHist函數來計算圖像直方圖。
其中C++的函數原型如下:void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, OutputArray
hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=
false );
void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, SparseMat&
hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=
false );
參數解釋:
arrays。輸入的圖像的指針,可以是多幅圖像,所有的圖像必須有同樣的深度(CV_8U or CV_32F)。同時一副圖像可以有多個channes。
narrays。輸入的圖像的個數。
channels。用來計算直方圖的channes的數組。比如輸入是2副圖像,第一副圖像有0,1,2共三個channel,第二幅圖像只有0一個channel,
那么輸入就一共有4個channes,如果int channels[3] = {3, 2, 0},那么就表示是使用第二副圖像的第一個通道和第一副圖像的第2和第0個通道來計
算直方圖。
mask。掩碼。如果mask不為空,那么它必須是一個8位(CV_8U)的數組,並且它的大小的和arrays[i]的大小相同,值為1的點將用來計算
直方圖。
hist。計算出來的直方圖
dims。計算出來的直方圖的維數。
histSize。在每一維上直方圖的個數。簡單把直方圖看作一個一個的豎條的話,就是每一維上豎條的個數。
ranges。用來進行統計的范圍。比如
float rang1[] = {0, 20};
float rang2[] = {30, 40};
const float *rangs[] = {rang1, rang2};那么就是對0,20和30,40范圍的值進行統計。
uniform。每一個豎條的寬度是否相等。
accumulate。Accumulation flag. If it is set, the histogram is not cleared in the beginning
when it is allocated. This feature enables you to compute a single histogram from several
sets of arrays, or to update the histogram in time. 是否累加。如果為true,在下次計算的時候不會首先清空hist。這個地方我是這樣理解的,不知道有沒有錯,
請高手指點。
1 Histogram1D::Histogram1D(){ 2 histSize[0] = 256; 3 hranges[0] = 0.0; 4 hranges[1] = 255.0; 5 ranges[0] = hranges; 6 channels[0] = 0; 7 } 8 9 cv::MatND Histogram1D::getHistogram(const cv::Mat &image){ 10 cv::MatND hist; 11 cv::calcHist(&image, //source image 12 1, //histogram from 1 image only 13 channels, //the channel used 14 cv::Mat(),//no mask is uesd 15 hist, //the resulting histogram 16 1, //it is a 1D histogram 17 histSize, //number of bins 18 ranges //pixel value range 19 );//直方圖函數 20 return hist; 21 }
下面是計算1維圖像的直方圖:
cv::Mat Histogram1D::getHistogramImage(const cv::Mat &image){ //compute histogram first cv::MatND hist = getHistogram(image); //get min and max bin values double maxVal = 0; double minVal = 0; cv::minMaxLoc(hist,&minVal,&maxVal,0,0); //Image on which to display histogram cv::Mat histImg(histSize[0],histSize[0],CV_8U,cv::Scalar(255)); //set highest point at 90% of nbins int hpt = static_cast<int>(0.9*histSize[0]); //Draw a vertical line for each bin for (int h =0;h<histSize[0];h++) { float binVal = hist.at<float>(h); int intensity = static_cast<int>(binVal*hpt/maxVal); cv::line(histImg,cv::Point(h,histSize[0]),cv::Point(h,histSize[0]-intensity),cv::Scalar::all(0)); } return histImg; }
計算H-S直方圖分布:
/********************************************* 內容:計算H-S 直方圖分布 時間:2013 5.27 作者:戀上蛋炒面 *********************************************/ #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; void main() { Mat source = imread("baboon.jpg"); namedWindow("Source"); imshow("Source",source); Mat hsv; cvtColor(source,hsv,CV_BGR2HSV); //Quantize the hue to 60 levels //and the saturation to 64 levels int hbins = 60,sbins = 64; int histSize[] = {hbins,sbins}; int histSize[] = {hbins,sbins}; //hue varies from 0 to 179 float hranges[] = {0,180}; //saturation varies from 0 to 255 float sranges[] = {0,255}; const float *ranges[] = {hranges,sranges}; //two channels 0th,1th int channels[] = {0,1}; MatND hist; //compute h-s histogram calcHist(&hsv,1,channels,Mat(),hist,2,histSize,ranges); //get the max value double maxVal = .0; minMaxLoc(hist,0,&maxVal,0,0); int scale = 8; //show the histogram on the image Mat histImg = Mat::zeros(sbins*scale,hbins*scale,CV_8UC3); for (int h = 0;h < hbins;h++) { for (int s = 0;s<sbins;s++) { float binVal = hist.at<float>(h,s); int intensity = cvRound(binVal*0.9*255/maxVal); rectangle(histImg,Point(h*scale,s*scale),Point((h+1)*scale-1,(s+1)*scale-1),Scalar::all(intensity),CV_FILLED); } } namedWindow("H-S Histogram"); imshow("H-S Histogram",histImg); imwrite("hshistogram.jpg",histImg); waitKey(0); }
RGB直方圖:
1 #include <opencv2/core/core.hpp> 2 #include <opencv2/highgui/highgui.hpp> 3 #include <opencv2/imgproc/imgproc.hpp> 4 5 #include <fstream> 6 7 using namespace cv; 8 using namespace std; 9 10 void main() 11 { 12 //Mat source = imread("red.jpg"); 13 Mat source = imread("baboon.jpg"); //讀取圖片 14 //Mat source(300,300,CV_8UC3,Scalar(1,1,244)); 15 //imwrite("red.jpg",source); 16 namedWindow("Source");//窗口顯示圖片 17 imshow("Source",source); 18 //初始化calcHist函數的參數 19 int channels_r[1],channels_g[1],channels_b[1],histSize[1],range; 20 float hranges[2]; 21 const float *ranges[1]; 22 histSize[0] = 256; 23 hranges[0] = 0.0; 24 hranges[1] = 255.0; 25 ranges[0] = hranges; 26 channels_b[0] = 0; 27 channels_g[0] = 1; 28 channels_r[0] = 2; 29 MatND hist_r,hist_g,hist_b; 30 31 double max_val_r,max_val_g,max_val_b; 32 Mat histImage(histSize[0],3*histSize[0],CV_8UC3); //定義一個顯示直方圖的圖片,長256*3 高256 33 //R 34 calcHist(&source,1,channels_r,Mat(),hist_r,1,histSize,ranges);//分別計算R,G,B的直方圖分布 35 minMaxLoc(hist_r,0,&max_val_r,0,0);//計算直方圖中統計最大值 36 //G 37 calcHist(&source,1,channels_g,Mat(),hist_g,1,histSize,ranges); 38 minMaxLoc(hist_g,0,&max_val_g,0,0); 39 //B 40 calcHist(&source,1,channels_b,Mat(),hist_b,1,histSize,ranges); 41 minMaxLoc(hist_b,0,&max_val_b,0,0); 42 43 //將r,g,b的最大統計值,以及像素點從0-255的統計值寫入txt中 44 ofstream outfile1("d:\\r.txt"); 45 ofstream outfile2("d:\\g.txt"); 46 ofstream outfile3("d:\\b.txt"); 47 48 //在txt中寫入最大統計值 49 outfile1<<"max_val_r = "<<max_val_r<<endl; 50 outfile2<<"max_val_g = "<<max_val_g<<endl; 51 outfile3<<"max_val_b = "<<max_val_b<<endl; 52 53 for (int i =0;i<histSize[0];i++) 54 { 55 //R,G,B= i的統計值 56 float binVal_r = hist_r.at<float>(i); 57 float binVal_g = hist_g.at<float>(i); 58 float binVal_b = hist_b.at<float>(i); 59 //統一R,G,B統計值的大小,以高度的90%封頂 60 int intensity_r = static_cast<int>(0.9*histSize[0]*binVal_r/max_val_r); 61 outfile1<<i<<" "<<binVal_r<<" "<<intensity_r<<endl; 62 int intensity_g = static_cast<int>(0.9*histSize[0]*binVal_g/max_val_g); 63 outfile2<<i<<" "<<binVal_g<<" "<<intensity_g<<endl; 64 int intensity_b = static_cast<int>(0.9*histSize[0]*binVal_b/max_val_b); 65 outfile3<<i<<" "<<binVal_b<<" "<<intensity_b<<endl; 66 //畫出R,G,B的直方圖直線 67 line(histImage,Point(i,histImage.rows),Point(i,histImage.rows-intensity_r),Scalar(0,0,255)); 68 line(histImage,Point(i+histSize[0],histImage.rows),Point(i+histSize[0],histImage.rows-intensity_g),Scalar(0,255,0)); 69 line(histImage,Point(i+histSize[0]*2,histImage.rows),Point(i+histSize[0]*2,histImage.rows-intensity_b),Scalar(255,0,0)); 70 } 71 namedWindow("RGB Histogram"); 72 imshow("RGB Histogram",histImage); 73 imwrite("RGB_Histogram.jpg",histImage); 74 waitKey(0); 75 }
