opencv2 直方图之calchist函数使用(转)
Posted wyu123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv2 直方图之calchist函数使用(转)相关的知识,希望对你有一定的参考价值。
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 }
以上是关于opencv2 直方图之calchist函数使用(转)的主要内容,如果未能解决你的问题,请参考以下文章
详解为什么OpenCV的直方图计算函数calcHist()计算出的灰度值为255的像素个数为0
利用OpenCV的函数calcHist()计算出图像的直方图数据后绘制图像的直方图
利用OpenCV的函数calcHist()计算出图像的直方图数据后绘制图像的直方图
OpenCV直方图计算函数calcHist()的最后一个参数accumulate的作用