opencv直方图cvhistogram

直方图


CvHistogram

多维直方图

     typedef struct CvHistogram      {          int header_size; /* 头尺寸 */          CvHistType type; /* 直方图类型 */          int flags; /* 直方图标识 */          int c_dims; /* 直方图维数 */          int dims[CV_HIST_MAX_DIM]; /* 每一维的尺寸 */          int mdims[CV_HIST_MAX_DIM]; /* 快速访问元素的系数 */          /* &m[a,b,c] = m + a*mdims[0] + b*mdims[1] + c*mdims[2] */          float* thresh[CV_HIST_MAX_DIM]; /* 每一维的直方块边界数组 */          float* array; /* 所有的直方图数据,扩展为单行 */      struct CvNode* root; /* 存储直方块的平衡树的根结点 */          CvSet* set; /* 内存存储仓的指针 (对平衡树而言) */          int* chdims[CV_HIST_MAX_DIM]; /* 快速计算的缓存 */      } CvHistogram;

CreateHist

创建直方图

CvHistogram* cvCreateHist( int dims, int* sizes, int type,                             float** ranges=NULL, int uniform=1 );

 

dims
直方图维数的数目
sizes
直方图维数尺寸的数组
type
直方图的表示格式: CV_HIST_ARRAY 意味着直方图数据表示为多维密集数组 CvMatNDCV_HIST_TREE 意味着直方图数据表示为多维稀疏数组CvSparseMat.
ranges
图中方块范围的数组. 它的内容取决于参数 uniform 的值。这个范围的用处是确定何时计算直方图或决定反向映射(backprojected ),每个方块对应于输入图像的哪个/哪组值。
uniform
归一化标识。 如果不为0,则ranges[i]0<=i<cDims,译者注:cDims为直方图的维数,对于灰度图为1,彩色图为3)是包含两个元素的范围数组,包括直方图第i维的上界和下界。在第i维上的整个区域 [lower,upper]被分割成 dims[i] 个相等的块(译者注:dims[i]表示直方图第i维的块数),这些块用来确定输入象素的第 i 个值(译者注:对于彩色图像,i确定R, G,或者B)的对应的块;如果为0,则ranges[i]是包含dims[i]+1个元素的范围数组,包括lower0, upper0, lower1, upper1 == lower2, ..., upperdims[i]-1, 其中lowerj 和upperj分别是直方图第i维上第 j 个方块的上下界(针对输入象素的第 i 个值)。任何情况下,输入值如果超出了一个直方块所指定的范围外,都不会被 cvCalcHist 计数,而且会被函数cvCalcBackProject 置零。

函数 cvCreateHist 创建一个指定尺寸的直方图,并且返回创建的直方图的指针。 如果数组的 ranges 是 0, 则直方块的范围必须由函数cvSetHistBinRanges 稍后指定。虽然 cvCalcHist 和 cvCalcBackProject 可以处理 8-比特图像而无需设置任何直方块的范围,但它们都被假设等分 0..255 之间的空间。


SetHistBinRanges

设置直方块的区间

void cvSetHistBinRanges( CvHistogram* hist, float** ranges, int uniform=1 );

 

hist
直方图.
ranges
直方块范围数组的数组,见 cvCreateHist.
uniform
归一化标识,见 cvCreateHist.

函数 cvSetHistBinRanges 是一个独立的函数,完成直方块的区间设置。更多详细的关于参数 ranges 和 uniform 的描述,请参考函数  cvCalcHist , 该函数也可以初始化区间。直方块的区间的设置必须在计算直方图之前,或 在计算直方图的反射图之前。


ReleaseHist

释放直方图结构

void cvReleaseHist( CvHistogram** hist );

 

hist
被释放的直方图结构的双指针.

函数 cvReleaseHist 释放直方图 (头和数据). 指向直方图的指针被函数所清空。如果 *hist 指针已经为 NULL, 则函数不做任何事情。


ClearHist

清除直方图

void cvClearHist( CvHistogram* hist );

 

hist
直方图.

函数 cvClearHist 当直方图是稠密数组时将所有直方块设置为 0,当直方图是稀疏数组时,除去所有的直方块。


MakeHistHeaderForArray

从数组中创建直方图

CvHistogram*   cvMakeHistHeaderForArray( int dims, int* sizes, CvHistogram* hist,                                          float* data, float** ranges=NULL, int uniform=1 );

 

dims
直方图维数.
sizes
直方图维数尺寸的数组
hist
为函数所初始化的直方图头
data
用来存储直方块的数组
ranges
直方块范围,见 cvCreateHist.
uniform
归一化标识,见 cvCreateHist.

函数 cvMakeHistHeaderForArray 初始化直方图,其中头和直方块为用户所分配。以后不需要调用 cvReleaseHist 只有稠密直方图可以采用这种方法,函数返回 hist.


QueryHistValue_1D

查询直方块的值

#define cvQueryHistValue_1D( hist, idx0 ) /      cvGetReal1D( (hist)->bins, (idx0) ) #define cvQueryHistValue_2D( hist, idx0, idx1 ) /      cvGetReal2D( (hist)->bins, (idx0), (idx1) ) #define cvQueryHistValue_3D( hist, idx0, idx1, idx2 ) /      cvGetReal3D( (hist)->bins, (idx0), (idx1), (idx2) ) #define cvQueryHistValue_nD( hist, idx ) /      cvGetRealND( (hist)->bins, (idx) )

 

hist
直方图
idx0, idx1, idx2, idx3
直方块的下标索引
idx
下标数组

宏 cvQueryHistValue_*D 返回 1D, 2D, 3D 或 N-D 直方图的指定直方块的值。对稀疏直方图,如果方块在直方图中不存在,函数返回 0, 而且不创建新的直方块。


GetHistValue_1D

返回直方块的指针

#define cvGetHistValue_1D( hist, idx0 ) /      ((float*)(cvPtr1D( (hist)->bins, (idx0), 0 )) #define cvGetHistValue_2D( hist, idx0, idx1 ) /      ((float*)(cvPtr2D( (hist)->bins, (idx0), (idx1), 0 )) #define cvGetHistValue_3D( hist, idx0, idx1, idx2 ) /      ((float*)(cvPtr3D( (hist)->bins, (idx0), (idx1), (idx2), 0 )) #define cvGetHistValue_nD( hist, idx ) /      ((float*)(cvPtrND( (hist)->bins, (idx), 0 ))

 

hist
直方图.
idx0, idx1, idx2, idx3
直方块的下标索引.
idx
下标数组

宏 cvGetHistValue_*D 返回 1D, 2D, 3D 或 N-D 直方图的指定直方块的指针。对稀疏直方图,函数创建一个新的直方块,且设置其为 0,除非它已经存在。


GetMinMaxHistValue

发现最大和最小直方块

void cvGetMinMaxHistValue( const CvHistogram* hist,                             float* min_value, float* max_value,                             int* min_idx=NULL, int* max_idx=NULL );

 

hist
直方图
min_value
直方图最小值的指针
max_value
直方图最大值的指针
min_idx
数组中最小坐标的指针
max_idx
数组中最大坐标的指针

函数 cvGetMinMaxHistValue 发现最大和最小直方块以及它们的位置。任何输出变量都是可选的。在具有同样值几个极值中,返回具有最小下标索引(以字母排列顺序定)的那一个。


NormalizeHist

归一化直方图

void cvNormalizeHist( CvHistogram* hist, double factor );

 

hist
直方图的指针.
factor
归一化因子

函数 cvNormalizeHist 通过缩放来归一化直方块,使得所有块的和等于 factor.


ThreshHist

对直方图取阈值

void cvThreshHist( CvHistogram* hist, double threshold );

 

hist
直方图的指针.
threshold
阈值大小

函数 cvThreshHist 清除那些小于指定阈值得直方块


CompareHist

比较两个稠密直方图

double cvCompareHist( const CvHistogram* hist1, const CvHistogram* hist2, int method );

 

hist1
第一个稠密直方图
hist2
第二个稠密直方图
method
比较方法,采用其中之一:
  • CV_COMP_CORREL
  • CV_COMP_CHISQR
  • CV_COMP_INTERSECT

函数 cvCompareHist 采用下面指定的方法比较两个稠密直方图(H1 表示第一个, H2 - 第二个):

相关 (method=CV_COMP_CORREL): d(H

1

,H

2

)=sum

I

(H'

1

(I)•H'

2

(I))/sqrt(sum

I

[H'

1

(I)

2

]•sum

I

[H'

2

(I)

2

]) 其中 H'

k

(I)=H

k

(I)-1/N•sum

J

H

k

(J) (N=number of histogram bins) Chi-square(method=CV_COMP_CHISQR): d(H

1

,H

2

)=sum

I

[(H

1

(I)-H

2

(I))/(H

1

(I)+H

2

(I))] 交叉 (method=CV_COMP_INTERSECT): d(H

1

,H

2

)=sum

I

max(H

1

(I),H

2

(I))

函数返回 d(H1,H2) 的值。

为了比较稀疏直方图或更一般的加权稀疏点集(译者注:直方图匹配是图像检索中的常用方法),考虑使用函数 cvCalcEMD 。


CopyHist

拷贝直方图

void cvCopyHist( const CvHistogram* src, CvHistogram** dst );

 

src
输入的直方图
dst
输出的直方图指针

函数 cvCopyHist 对直方图作拷贝。如果第二个直方图指针 *dst 是 NULL, 则创建一个与 src 同样大小的直方图。否则,两个直方图必须大小和类型一致。然后函数将输入的直方块的值复制到输出的直方图中,并且设置取值范围与 src 的一致。


CalcHist

计算图像image(s) 的直方图

void cvCalcHist( IplImage** image, CvHistogram* hist,                   int accumulate=0, const CvArr* mask=NULL );

 

image
输入图像s (虽然也可以使用 CvMat** ).
hist
直方图指针
accumulate
累计标识。如果设置,则直方图在开始时不被清零。这个特征保证可以为多个图像计算一个单独的直方图,或者在线更新直方图。
mask
操作 mask, 确定输入图像的哪个象素被计数

函数 cvCalcHist 计算单通道或多通道图像的直方图。 用来增加直方块的数组元素可从相应输入图像的同样位置提取。

Sample. 计算和显示彩色图像的 2D 色调-饱和度图像

#include <cv.h> #include <highgui.h> int main( int argc, char** argv ) {      IplImage* src;      if( argc == 2 && (src=cvLoadImage(argv[1], 1))!= 0)      {          IplImage* h_plane = cvCreateImage( cvGetSize(src), 8, 1 );          IplImage* s_plane = cvCreateImage( cvGetSize(src), 8, 1 );          IplImage* v_plane = cvCreateImage( cvGetSize(src), 8, 1 );          IplImage* planes[] = { h_plane, s_plane };          IplImage* hsv = cvCreateImage( cvGetSize(src), 8, 3 );          int h_bins = 30, s_bins = 32;          int hist_size[] = {h_bins, s_bins};          float h_ranges[] = { 0, 180 }; /* hue varies from 0 (~0°red) to 180 (~360°red again) */          float s_ranges[] = { 0, 255 }; /* saturation varies from 0 (black-gray-white) to 255 (pure spectrum color) */          float* ranges[] = { h_ranges, s_ranges };          int scale = 10;          IplImage* hist_img = cvCreateImage( cvSize(h_bins*scale,s_bins*scale), 8, 3 );          CvHistogram* hist;          float max_value = 0;          int h, s;          cvCvtColor( src, hsv, CV_BGR2HSV );          cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 );          hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1 );          cvCalcHist( planes, hist, 0, 0 );          cvGetMinMaxHistValue( hist, 0, &max_value, 0, 0 );          cvZero( hist_img );          for( h = 0; h < h_bins; h++ )          {              for( s = 0; s < s_bins; s++ )              {                  float bin_val = cvQueryHistValue_2D( hist, h, s );                  int intensity = cvRound(bin_val*255/max_value);                  cvRectangle( hist_img, cvPoint( h*scale, s*scale ),                               cvPoint( (h+1)*scale - 1, (s+1)*scale - 1),                               CV_RGB(intensity,intensity,intensity), /* graw a grayscale histogram.                                                                         if you have idea how to do it                                                                         nicer let us know */                               CV_FILLED );              }          }          cvNamedWindow( "Source", 1 );          cvShowImage( "Source", src );          cvNamedWindow( "H-S Histogram", 1 );          cvShowImage( "H-S Histogram", hist_img );          cvWaitKey(0);      } }

CalcBackProject

计算反向投影

void cvCalcBackProject( IplImage** image, CvArr* back_project, const CvHistogram* hist );

 

image
输入图像 (也可以传递 CvMat** ).
back_project
反向投影图像,与输入图像具有同样类型.
hist
直方图

函数 cvCalcBackProject 直方图的反向投影. 对于所有输入的单通道图像同一位置的象素数组,该函数根据相应的象素数组(RGB),放置其对应的直方块的值到输出图像中。用统计学术语,输出图像象素点的值是观测数组在某个分布(直方图)下的的概率。 例如,为了发现图像中的红色目标,可以这么做:

  1. 对红色物体计算色调直方图,假设图像仅仅包含该物体。则直方图有可能有极值,对应着红颜色。
  2. 对将要搜索目标的输入图像,使用直方图计算其色调平面的反向投影,然后对图像做阈值操作。
  3. 在产生的图像中发现连通部分,然后使用某种附加准则选择正确的部分,比如最大的连同部分。

这是 Camshift 彩色目标跟踪器中的一个逼进算法,除了第三步,CAMSHIFT 算法使用了上一次目标位置来定位反向投影中的目标。


CalcBackProjectPatch

用直方图比较来定位图像中的模板

void cvCalcBackProjectPatch( IplImage** image, CvArr* dst,                               CvSize patch_size, CvHistogram* hist,                               int method, float factor );

 

image
输入图像 (可以传递 CvMat** )
dst
输出图像.
patch_size
扫描输入图像的补丁尺寸
hist
直方图
method
比较方法,传递给 cvCompareHist (见该函数的描述).
factor
直方图的归一化因子,将影响输出图像的归一化缩放。如果为 1,则不定。

函数 cvCalcBackProjectPatch 通过输入图像补丁的直方图和给定直方图的比较,来计算反向投影。提取图像在 ROI 中每一个位置的某种测量结果产生了数组 image. 这些结果可以是色调, x 差分, y 差分, Laplacian 滤波器, 有方向 Gabor 滤波器等中 的一个或多个。每种测量输出都被划归为它自己的单独图像。 image 图像数组是这些测量图像的集合。一个多维直方图 hist 从这些图像数组中被采样创建。最后直方图被归一化。直方图 hist 的维数通常很大等于图像数组 image 的元素个数。

在选择的 ROI 中,每一个新的图像被测量并且转换为一个图像数组。在以锚点为“补丁”中心的图像 image 区域中计算直方图 (如下图所示)。用参数norm_factor 来归一化直方图,使得它可以与 hist 互相比较。计算出的直方图与直方图模型互相比较, (hist 使用函数 cvCompareHist ,比较方法是 method=method). 输出结果被放置到概率图像 dst 补丁锚点的对应位置上。这个过程随着补丁滑过整个 ROI 而重复进行。迭代直方图的更新可以通过在原直方图中减除“补丁”已覆盖的尾象素点或者加上新覆盖的象素点来实现,这种更新方式可以节省大量的操作,尽管目前在函数体中还没有实现。

Back Project Calculation by Patches


CalcProbDensity

两个直方图相除

void   cvCalcProbDensity( const CvHistogram* hist1, const CvHistogram* hist2,                           CvHistogram* dst_hist, double scale=255 );

 

hist1
第一个直方图(分子).
hist2
第二个直方图
dst_hist
输出的直方图
scale
输出直方图的尺度因子

函数 cvCalcProbDensity 从两个直方图中计算目标概率密度:

dist_hist(I)=0       if hist1(I)==0               scale   if hist1(I)!=0 && hist2(I)>hist1(I)               hist2(I)*scale/hist1(I) if hist1(I)!=0 && hist2(I)<=hist1(I)

所以输出的直方块小于尺度因子。

posted on 2012-02-09 22:11  伪君  阅读(3181)  评论(0编辑  收藏  举报

导航