今天做了一下opencv1的直方图实验,结果被坑了一上午。
直方图的含义十分简单,就是统计各个像素值的分布情况,因此我们的操作对象应该是一个单通道图,当然多通道图也可以,这样做出来的就是多维直方图,不过就一般应用而言,还是一维直方图用得比较多。
opencv中集成了计算直方图的函数,说实话,这个函数的传参有点过于复杂了,不过如果有个例子比照着写还是比较简单的。另外,要注意的是,如果要在函数中计算直方图,传参时务必要使用指针或者引用,只有这样,计算出的直方图才能在函数外部访问到,否则会一直出现错误。
/*
本函数用于计算直方图,注意传入参数必须为hist的引用
输入为单通道图,hist矩阵和bins的数目
*/
void myCal_Hist(Mat &Gray_img,Mat &hist,int binsNum)
{
int hist_size[] = {binsNum};
float range[] = { 0, 256 };
const float* ranges[] = { range};
int channels[] = {0};
//计算直方图
calcHist( &Gray_img, 1, channels, Mat(), // do not use mask
hist, 1, hist_size, ranges,
true, // the histogram is uniform
false );
}
/*
绘制hist图像
*/
void showHist(Mat &hist,int binsNum)
{
int hist_w = 512; int hist_h = 400;
int bin_w = cvRound( (double) hist_w/binsNum );
Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );
/// Normalize the result to [ 0, histImage.rows ]
normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
for(int i = 1;i < binsNum;i++)
{
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(hist.at<float>(i)) ),
Scalar( 255, 0, 0), 2, 8, 0 );
}
imshow("calcHist Demo", histImage );
}