StupidBeauty
Read times:3414Posted at: - no title specified
  • OpenCV 2.4.12.0 文档翻译:直方图,Histograms

calcHist

计算一组数组的直方图。

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中有一个针对单张图片创建直方图的示例。

calcBackProject

计算一个直方图的反投影。

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. 1.在开始跟踪之前,在相机前展示该物体,使得它几乎占据整个画面。计算一个色度(hue)直方图。这个直方图中,可能会出现狠强的最大值分量,它就对应于该物体的支配色彩。

  2. 2.在实际跟踪过程中,对于输入视频中的每一帧,对于其色度平面,使用预先计算的直方图来计算出一个反投影。对这个反投影图片进行阈值化处理,以过滤掉弱颜色。另外,以下手段可能也会直到一定的作用:过滤掉那些饱和度不够的像素、颜色过暗的像素、颜色过亮的像素。

  3. 3.在所得到的结果图片中,寻找连通分量,并且选择最合适的那一个,例如,选择面积最大的那个。

这是对于颜色对象跟踪器 CamShift() 的近似算法描述。

参考

calcHist()

compareHist

比较两个直方图

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() 函数。

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)值甚至可以以更快的速度计算出来 (使用线性时间复杂 度的算法 ) ,因而 可以用来粗略地确定两个点集 是否是相距足够 远以至于它们不可能是 与同一个物体相关的。

Your opinions
Your name:Email:Website url:Opinion content: