图像的灰度直方图是一个离散函数,它表示图像每一灰度级与该灰度级出现频率的对应关系。可以应用于各种需要统计的数据中,使用简单、方便。但该运算是一个不可逆的过程。
函数原型如下:
//! computes the joint dense histogram for a set of images.
CV_EXPORTS 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 );
//! computes the joint sparse histogram for a set of images.
CV_EXPORTS void calcHist( const Mat* images, int nimages,
const int* channels, InputArray mask,
SparseMat& hist, int dims,
const int* histSize, const float** ranges,
bool uniform=true, bool accumulate=false );
CV_EXPORTS_W void calcHist( InputArrayOfArrays images,
const vector<int>& channels,
InputArray mask, OutputArray hist,
const vector<int>& histSize,
const vector<float>& ranges,
bool accumulate=false );
参数:
nimages——输入的图像的个数。
channels——指明通道数。int channels[] = {0, 1};通道0和通道1。
mask——掩码。如果mask不为空,那么它必须是一个8位(CV_8U)的数组,为0的像素点不统计。
hist——保存直方图的矩阵
dims——直方图的维数。
histSize——每维bin的个数。
ranges——用来进行统计的范围。 float rang1[] = {0, 256}; float rang2[] = {0, 256};
const float *rangs[] = {rang1, rang2};那么就是对0,256和0,256范围的值进行统计,2D直方图)。
uniform——如果为true,采用均匀直方图。
accumulate——直方图建立时清除内存痕迹标志,默认为0,即清除。
下面是1D和2D直方图计算CODE:
#include "opencv2/opencv.hpp" using namespace std; using namespace cv;
int main() { //生成一幅单通道图像。 cv::Mat src = cv::imread("lena.png"); if( !src.data ) { return -1; }
/// 分割成3个单通道图像 ( R, G 和 B )vector<Mat> rgb_planes;split( src, rgb_planes );<pre name="code" class="cpp" style="color: rgb(0, 128, 0); font-size: 14px; line-height: 21px;">#pragma region single
/// 设定bin数目
int histSize = 255;
/// 设定取值范围 ( R,G,B) )
float range[] = { 0, 255 } ;
const float* histRange = { range };
bool uniform = true; bool accumulate = false;
Mat r_hist, g_hist, b_hist;
/// 计算直方图:
calcHist( &rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
calcHist( &rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
calcHist( &rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
// 创建直方图画布
int hist_w = 400; int hist_h = 400;
int bin_w = cvRound( (double) hist_w/histSize );
Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );
/// 将直方图归一化到范围 [ 0, histImage.rows ]
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
// 在直方图画布上画出直方图
for( int i = 1; i < histSize; i++ )
{
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
Scalar( 0, 0, 255), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
Scalar( 0, 255, 0), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
Scalar( 255, 0, 0), 2, 8, 0 );
}
/// 显示直方图
namedWindow("calcHist sDemo", CV_WINDOW_AUTOSIZE );
imshow("calcHist sDemo", histImage );
waitKey(0);
#pragma endregion single
#pragma region multi
MatND hist;
/// 计算直方图:
int rbins = 255, gbins = 255, bbins = 255;
int histSize1[] = {rbins, gbins, bbins};
float rranges[] = { 0, 256};
float granges[] = { 0, 256};
float branges[] = { 0, 256};
const float*ranges[] = { rranges, granges, branges };
int channels[] = {0, 1, 2};
calcHist( &src, 1,channels , Mat(), hist, 2, histSize1, ranges, true, false );
double maxVal=0;
minMaxLoc(hist, 0, &maxVal, 0, 0);
int scale = 2;
Mat histImg = Mat::zeros(gbins*scale, rbins*scale, CV_8UC3);
int n = hist.channels();
for( int h = 0; h < rbins; h++ )
{
for( int s = 0; s < gbins; s++ )
{
float binVal = hist.at<float>(h, s);
int intensity = cvRound(binVal*255/maxVal);
rectangle( histImg, Point(h*scale, s*scale),Point((h+1)*scale-1, (s+1)*scale-1), Scalar::all(intensity), CV_FILLED);
}
}
/// 显示直方图
namedWindow("<span style="font-family: 'Courier New'; white-space: pre-wrap;">calcHist MDemo</span><span style="font-family: 'Courier New'; white-space: pre-wrap;">"</span><span style="line-height: 1.5; font-family: 'Courier New'; white-space: pre-wrap;">, 1 ); </span><span style="font-family: 'Courier New'; white-space: pre-wrap;">
</span> imshow( "<span style="font-family: 'Courier New'; white-space: pre-wrap;">calcHist MDemo</span><span style="line-height: 1.5; font-family: 'Courier New'; white-space: pre-wrap;">", histImg ); </span>
waitKey(0);
#pragma endregion multi
return 0;
}