histogram从不会到理解的过程:
1.我想先从读取histogram的bins的方法说起.(Mat hist,假设已经过calchist())
首先 Mat类型的hist,他的维数是dims的,这就决定了,Mat hist中每个bins的存放形式.如果dims=1,则hist就是一个一维的数组,访问的时候,就for(inti=0;i<bins;++i) ,顺序访问hist.at<float>(i) ,画图的时候就要把float转化为int,使用cvRount()即可;
因此,对于dims=2,二维的hist,Mat hist 就是一个二维的矩阵,每个点对应一个(bins_1,bins_2)的值,访问的时候就用一个两层
用矩形表示吧,个人理解
2.谈一下calchist(),直方图计算函数
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)
(1)images:是一个图像数组,所以传参的时候,要传一个地址(一幅图用&src,多幅图的话,放在数组中,传入数组名)
(2)nimages:就是上一个中的图像总数
(3)channels:用来计算直方图的通道维数数组,第一个数组的通道由0到arrays[0].channels()-1列出,第二个数组的通道从arrays[0].channels()到arrays[0].channels()+arrays[1].channels()-1以此类推;(其实不太懂什么意思,求教)
(4)mask:一个掩码,用来选择图像中参与hist统计的像素,0表示参加计算.一般用Mat(),表示全部参与
(5)hist,直接传入即可(为传引用,也不用取地址),经计算后变成一个dims维的矩阵
(6)dims,维数 CV_MAX_DIMS ==32,最大的
(7)histSize,就是每一维的bins的个数,也要传入地址 eg.二维的int histSize={bins_1,bins_2};
(8)ranges 对于均匀直方图(即nuiform==true),ranges是一个由dims个float数对构成的数组,数对表示对应维的bin的范围. eg.某维有N==2个bins,在ranges中对应的数对为{0,10},均匀的意思是讲,将该维的bin均匀的非为N==2个区间:[0,5]和[5,10],这是程序自动划分的,只需提供给他数对表示最值范围即可.
对于非均匀的直方图,ranges的组成元素就不在是简单的数对了,而是一个个子数组,每个数组还有N+1个元素(N为该维的bin的数量),这N+1个元素将表示怎样对bin进行非均匀的划分. eg.某维N==4个bins,ranges中对应的字数组为5个元素{0,2,4,9,10},非均匀的意思就是讲,讲该bin划分为非均匀区间[0,2],[2,4][4,9].[9,10].
然后根据区间统计落在每个区间中的数量,从而计算出直方图.
(9)nuiform是否均匀,对应ranges中元素的不同表示.如上.
(10)accumulate一般为false,为TRUE时,在calchist中给hist分配内存时hist不会被清除,从而可以将多幅图的直方图统计到一个hist矩阵中. 或者有利于及时的更新直方图(不懂什么意思).