OpenCV 2.4.12.0 文档翻译:直方图,Histograms
计算一组数组的直方图。
C++: 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 )
C++: 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 )
参数: |
images – 源图片数组。它们应当具有相同的位深( CV_8U 或 CV_32F ),以及相同的尺寸。每张图片,可以具有任意的通道个数。 nimages – 源图片的个数。 channels – 用来计算直方图的维度( dims )通道列表。第一组通道个数数组,从0 到 images[0].channels()-1 依次列举;第二组通道个数数组,从 images[0].channels() 到 images[0].channels() + images[1].channels()-1 依次列举,如此下去。 mask – 可选的掩膜。如果这个矩阵不为空,那么,它必须是一个8位的数组,并且与 images[i] 的尺寸相同。非零的掩膜元素,选择出了要计数到这个直方图中去的数组元素。 hist – 输出直方图,它是一个密集或稀疏的 dims 维的数组。 dims – 直方图维度数,必须是正数,并且不能大于 CV_MAX_DIMS (在当前的OpenCV 版本中,值为32)。 histSize – 每个维度中的直方图的尺寸组成的数组。 ranges – 在每个维度中,直方图统计桶的边界所组成的 dims 个数组所组成的数组。如果该直方图是归一化的( uniform =true),那么,对于每个维度 i ,指定第0个直方图桶的较小(包含)边界L 0 和最后一个(即第 histSize[i]-1 个)直方图的较大(不包含)边界u histSize[i]-1 即可。也就是说,对于一个归一化的直方图,每个 ranges[i] 都是一个包含2 个元素的数组。如果该直方图不是归一化的( uniform=false ),那么,每个ranges[i]中都包含着histSize[i]+1个元素:L0,u0=L1,u1=L2,…,uhistSize[i]-2=L histSize[i]-1 ,u histSize[i]-1 。位于L 0 和u histSize[i]-1 范围之外的数组元素,不会被计入到直方图中。 uniform – 这个标志位,表明该直方图是否是归一化的(参考上面的参数)。 accumulate – 累积标志位。如果设置了这个标志位,则,直方图不会在创建之时清空。利用这个特性,可以用多组数组来计算出单个直方图,或者,随时间而更新直方图。 |
calcHist 函数 ,用来计算一个或多个数组的直方图。用来累积某个直方图统计 桶的元组中的元素,来自 于对应 的输入数组中相同的位置。下面 的示例,展示了,如何计算一个彩色图片的二维色调/饱和 度(Hue-Saturation)直方图。
#include <cv.h>
#include <highgui.h>
using namespace cv;
int main( int argc, char ** argv )
{
Mat src, hsv;
if ( argc != 2 || ! (src = imread(argv[ 1 ], 1 )).data )
return - 1 ;
cvtColor(src, hsv, CV_BGR2HSV);
// 将色调 (hue) 量化为 30 个级别
// 将饱和度 (saturation) 量化为 32 个级别
int hbins = 30 , sbins = 32 ;
int histSize[] = {hbins, sbins};
// 色调 ( hue )取值范围为从 0 到 179 ,参考 cvtColor文档
float hranges[] = { 0 , 180 };
// 饱和 度( saturation )取值范围为从 0 ( 黑-灰-白( black-gray-white ) ) 到
// 255 ( 纯的彩虹色 )
float sranges[] = { 0 , 256 };
const float * ranges[] = { hranges, sranges };
MatND hist;
// 我们计算第0个通道和第1个通道的直方图
int channels[] = { 0 , 1 };
calcHist( & hsv, 1 , channels, Mat(), // 不使用掩膜
hist, 2 , histSize, ranges,
true , // 直方图 是归一化的
false );
double maxVal = 0 ;
minMaxLoc(hist, 0 , & maxVal, 0 , 0 );
int scale = 10 ;
Mat histImg = Mat :: zeros(sbins * scale, hbins * 10 , 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 * 255 / maxVal);
rectangle( histImg, Point(h * scale, s * scale),
Point( (h + 1 ) * scale - 1 , (s + 1 ) * scale - 1 ),
Scalar :: all(intensity),
CV_FILLED );
}
namedWindow( "Source" , 1 );
imshow( "Source" , src );
namedWindow( "H-S Histogram" , 1 );
imshow( "H-S Histogram" , histImg );
waitKey();
}
注意
•.opencv_source_code/samples/cpp/demhist.cpp中有一个针对单张图片创建直方图的示例。
计算一个直方图的反投影。
C++: void calcBackProject ( const Mat* images , int nimages , const int* channels , InputArray hist , OutputArray backProject , const float** ranges , double scale =1, bool uniform =true )
C++: void calcBackProject ( const Mat* images , int nimages , const int* channels , const SparseMat& hist , OutputArray backProject , const float** ranges , double scale =1, bool uniform =true )
参数: |
images – 源图片数组。它们应当具有相同的位深( CV_8U 或 CV_32F ),以及相同的尺寸。每张图片,可以具有任意的通道个数。 nimages – 源图片的个数。 channels – 用来计算反投影的通道列表。通道的个数必须与直方图的维度相匹配。第一组通道个数数组,从0 到 images[0].channels()-1 依次列举;第二组通道个数数组,从 images[0].channels() 到 images[0].channels() + images[1].channels()-1 依次列举,如此下去。 hist – 输入直方图,它是一个密集或稀疏的数组。 backProject – 目标反投影数组,它是一个单通道的数组,与 images[0] 的尺寸和位深相同。 ranges – 在每个维度中,直方图统计桶的边界所组成的数组所组成的数组。参考 calcHist() 。 scale – 可选参数,输出的反投影的缩放因子。 uniform – 这个标志位,表明该直方图是否是归一化的(参考上面的参数)。 |
calcBackProject 函数 ,计算指定直方图的反投影。 也就是说,它做的工作与 calcHist 类似。 calcHist 函数 ,在工作过程中,对于每个位置 (x, y) , 会收集输入图片中选中通道的像素值,进而找到对应的直方图统计桶。但是 ,这个函数,不是对统计桶进行累加,而是读取统计桶的值,按照scale对它进行缩放,然后 将得到的值存入到 backProject(x,y) 中去。 以统计学的术语来说,就是, 这个函数,根据该直方图所表现出来的经验概率分布,计算出每个元素值的出现概率。例如, 妳可以以下述方法来寻找及跟踪某个场景中的一个亮色物体:
1.在开始跟踪之前,在相机前展示该物体,使得它几乎占据整个画面。计算一个色度(hue)直方图。这个直方图中,可能会出现狠强的最大值分量,它就对应于该物体的支配色彩。
2.在实际跟踪过程中,对于输入视频中的每一帧,对于其色度平面,使用预先计算的直方图来计算出一个反投影。对这个反投影图片进行阈值化处理,以过滤掉弱颜色。另外,以下手段可能也会直到一定的作用:过滤掉那些饱和度不够的像素、颜色过暗的像素、颜色过亮的像素。
3.在所得到的结果图片中,寻找连通分量,并且选择最合适的那一个,例如,选择面积最大的那个。
这是对于颜色对象跟踪器 CamShift() 的近似算法描述。
参考
比较两个直方图。
C++: double compareHist ( InputArray H1 , InputArray H2 , int method )
C++: double compareHist ( const SparseMat& H1 , const SparseMat& H2 , int method )
参数: |
H1 – 要比较的第一个直方图。 H2 – 要比较的第二个直方图,与 H1 的尺寸相同。 method – 比较算法,可以是以下取值: CV_COMP_CORREL 相关度(Correlation) CV_COMP_CHISQR 卡方值(Chi-Square) CV_COMP_INTERSECT 交集 CV_COMP_BHATTACHARYYA 巴塔恰里雅距离 (Bhattacharyya distance) CV_COMP_HELLINGER CV_COMP_BHATTACHARYYA 的同义词 |
compareHist 函数 ,使用指定的方法来比较两个密集或松散的直方图:
•. 相关 度 ( method=CV_COMP_CORREL )
其中
而N是直方图统计桶的总个数。
•. 卡方值( Chi-Square ) ( method=CV_COMP_CHISQR )
•. 交集( method=CV_COMP_INTERSECT )
•. 巴塔恰里雅距离 ( Bhattacharyya distance ) ( method=CV_COMP_BHATTACHARYYA 或 method=CV_COMP_HELLINGER ) 。实际 上, OpenCV计算 的是海灵格距离(Hellinger distance), 它与 巴塔恰里雅 系 数 相关。
这个函数返回的是d(H 1 ,H 2 )。
尽管 这个函数对于 一维、二维、三维的密集 型 直方图都能工作得狠好,但是, 它可能并不适用于 高维度的稀松型直方图。 在这种直方图中,由于别名和采样的原因,那些非零的直方图统计桶的坐标会发生轻微的偏移。 为了比较这种直方图,或者,更通用地讲, 为了比较 带权点组成的稀松集合,应当使用 EMD() 函数。
计算出两个带权点集之间的“最小工作量”距离(“minimal work” distance)。
C++: float EMD ( InputArray signature1 , InputArray signature2 , int distType , InputArray cost =noArray(), float* lowerBound =0, OutputArray flow =noArray() )
参数: |
signature1 – 第一个特征签名,它是一个(size1×dims+1)的浮点数矩阵。每一行,储存的是,该点的权值,接下来是该点的坐标。如果提供了一个由用户定义的花费(cost)矩阵,则,此参数对应的矩阵允许只有单个列(即,只有权重值)。 signature2 – 第二个特征签名,与 signature1 的格式相同,不过,行数可以不同。总的权重值也可以不同。在这种情况下,会向 signature1 或 signature2 中加入一个额外的“无意义”(“dummy”)点。 distType – 所使用的度量手段。 CV_DIST_L1 、 CV_DIST_L2 和 CV_DIST_C 分别代表着一种标准度量手段。 CV_DIST_USER 则表示,使用一个预先计算好的花费(cost)矩阵 cost 。 distance_func – 旧的接口所支持的自定义距离函数。 CvDistanceFunction 的定义是: typedef float (CV_CDECL * CvDistanceFunction)( const float * a, const float * b, void * userdata ); 其中, a 和 b 是点的坐标集合,而 userdata 就是本函数的最后一个参数。 cost – 用户定义的(size1×size2)花费(cost)矩阵。同时,如果使用了一个花费(cost)矩阵,则,无法计算下界(lower boundary) lowerBound ,因为,它需要一个度量函数。 lowerBound – 可选的输入/输出参数:两个特征点集的距离的下界(lower boundary),也就是两个特征点集的质心的距离。以下情况下,下界(lower boundary)可不计算:使用了一个由用户定义的花费(cost)矩阵;两个点集的总权重不相等;或,两个点集中仅包含权重(点集中只有单个列)。妳 必须初始化 *lowerBound 。如果计算出来的质心间距离大于或等于 *lowerBound (意味着,两个点集距离足够远),则,这个函数不会计算EMD。在任何情况下, *lowerBound 都会被设置成所计算出来的两个质心之间的距离,用作返回值。因此,如 果妳既想计算质心距离,也想计算EMD,则, *lowerBound 应当被设置成0。 flow – 结果中的(size1×size2)流矩阵:flow i,j ,指的是,signature1中第i个点指向signature2中第j个点的流。 userdata – 可选的指针,会被直接传递给自定义的距离函数。 |
这个函数,计算两个带权点集之间的推土机距离(earth mover distance)和/或它们之间的距离的下界(lower boundary)。 它的一个应用是, 如 [RubnerSept98] 中所说,用于进行 多维的直方图比较,以实现图像检索。推土机距离 ( EMD ),是一个运输问题,通过 对某个单一算法做某些修改来实现解决,因此 , 在最坏情况下,它的算法复杂度是指数级别的, 而从平均复杂度来看,就要快得多了。 在实际的度量场景中,下界 (lower boundary)值甚至可以以更快的速度计算出来 (使用线性时间复杂 度的算法 ) ,因而 可以用来粗略地确定两个点集 是否是相距足够 远以至于它们不可能是 与同一个物体相关的。
对某个灰度图片的直方图进行均衡化。
C++: void equalizeHist ( InputArray src , OutputArray dst )
参数: |
src – 源图片,8位单通道图片。 dst – 目标图片,尺寸及类型与 src 相同。 |
这个函数,使用以下算法来对输入图片的直方图进行均衡化:
1. 计算 源图片 src 的直方图H。
2. 将直方图归一化,使得,所有直方图统计桶的和值为255。
3.计算出该直方图的积分:
4.将H'用作一个查找表,对图片进行变换:dst(x,y)=H'(src(x,y))
这个算法,会将图片的亮度归一化,会增加图片的对比度。
庄芬妮
未知美人
未知美人
未知美人
HxLauncher: Launch Android applications by voice commands