OpenCV中的直方图绘制(C++)
官方文档中的函数声明:
函数一:
void cv::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
)
功能
这个函数只能得到一张直方图,即便是可以传入多个图像,也只能得到一张直方图,维度指定并不是指定输出直方图有几个通道,而是说从多通道维度进行统计,并且是数学中的交集的含义,表示某一个像素点的个各通道同时满足ranges范围。
The function cv::calcHist calculates the histogram of one or more arrays. The elements of a tuple used to increment a histogram bin are taken from the corresponding input arrays at the same location.
参数解释
images,图像指针
可以是数组,包含多个图像(必须有相同的深度和大小),图像通道数量任意;
They all should have the same depth, CV_8U, CV_16U or CV_32F , and the same size. Each of them can have an arbitrary number of channels.
nimages,图像张数
channels,通道编号构成的数组的指针
通道编号规则为:按images里的mat排序,每个mat的通道占1(首个序号为0,比如有两张mat,都是3通道,那么序号就是0,1,2,3,4,5);注:这里传的是指针或数组名。
channels List of the dims channels used to compute the histogram. The first array channels are numerated from 0 to mages[0]. channels()-1 , the second array channels are counted from images[0].channels() to images[0].channels() + images[1].channels()-1, and so on.
mask,掩模mat。
如果是空,则cv::calcHist将统计整个mat,否则只会统计非0区域。
If the matrix is not empty, it must be an 8-bit array of the same size as images[i] . The non-zero mask elements mark the array elements counted in the histogram.
OutputArray,输出阵列
(可以是mat(稠密),也可以是sparseMat(稀疏));
dims,维度个数
如果上面的输出是mat类型,则最多为2;如果大于2,则上面的输出阵列应该要指定为sparseMat类型才可以;
Histogram dimensionality that must be positive and not greater than CV_MAX_DIMS (equal to 32 in the current OpenCV 4.7.0 version).
histSize,每个通道被分割成的个数
大概就是直方图的条块数(如果把每个通道的直方图看作一个一个竖条的话,就是竖条的个数)。
ranges:数组的数组
ranges Array of the dims arrays of the histogram bin boundaries in each dimension. When the histogram is uniform ( uniform =true), then for each dimension i it is enough to specify the lower (inclusive) boundary \fKaTeX parse error: Undefined control sequence: \f at position 4: L_0\̲f̲ of the 0-th histogram bin and the upper (exclusive) boundary \fKaTeX parse error: Undefined control sequence: \f at position 27: …histSize}[i]-1}\̲f̲
二维C++数组指针,用来存储每个维度的统计数据的区间。比如:
第一个通道值域是[0,180],第二个通道值域是[0,255],我可以指定:
第一个通道只统计[50,100)之间的分布数据,指定第二个通道只统计[20,220])之间的分布数据,
相当于只截取其中一段来统计(注意指定范围是左闭右开的)。
特别的有:对于均匀平分的直方图(每条的宽度相同),每个直方图只需要左右两个数就可以了(如果把每个通道的直方图看作一个一个竖条的话,就是每张直方图左边界和右边界值);对于不均匀的直方图,则需要手动指出histSize+1个数值。并且直方图只会统计这histSize+1个数值对应的频数,数值之间的甩掉不统计。
uniform,是否均匀划分通道范围
上面的histSize指定了直方图每个通道划分个数,而uniform用来告诉函数,直方图是否是均匀分条,不均匀则只统计点位上的值的频数。
accumulate=false:在多个图像时,是否累积计算像素值的个数;
另外,还有一种符合C++泛型编程的重载函数可以使用,更符合C++11的书写习惯和STL模板库的风格:
注意,只能用于均匀分条的情况。
//this variant supports only uniform histograms.
//ranges argument is either empty vector or a flattened vector of histSize.size()*2 elements(histSize.size() element pairs).
//The first and second elements of each pair specify the lower and upper boundaries.
void calcHist( InputArrayOfArrays images,
const std::vector<int>& channels;
InputArray mask;
OutputArray hist,
const std::vector<int>& histSize,
const std::vector<float>& ranges,
bool accumulate = false
);