关于颜色直方图和反向投影的一些理解

  http://blog.csdn.net/armily/article/details/8965629

最近在研究Meanshift跟踪算法,遇到一些概念,比如颜色直方图和反向投影,有些不理解,故百度搜之,并小结,希望能印象深刻。

(一)颜色直方图

        颜色特征是图像检索中应用最为广泛的视觉特征,主要原因在于颜色往往和图像中所包含的物体或场景十分相关。此外,与其他的视觉特征相比,颜色特征对图像本身的尺寸、方向、视角的依赖性较小,从而具有较高的鲁棒性。

        首先,我们需要合适的颜色空间来描述颜色特征;其次,我们要采用一定的量化方法将颜色特征表达为向量的形式;最后,还要定义一种相似度(距离)标准用来衡量图像之间在颜色上的相似性。 

         颜色直方图所描述的是不同色彩在整幅图像中所占的比例,而并不关心每种色彩所处的空间位置,即无法描述图像中的对象或物体。颜色直方图特别适于描述那些难以进行自动分割的图像。颜色直方图是基于不同的颜色空间和坐标系。最常用的颜色空间是RGB颜色空间,原因在于大部分的数字图像都是用这种颜色空间表达的。然而,RGB空间结构,并不符合人们对颜色相似性的主观判断。因此,有人提出了基于HSV空间、Luv空间和Lab空间的颜色直方图,因为它们更接近于人们对颜色的主观认识。其中HSV空间是直方图最常用的颜色空间。它的三个分量分别代表色彩(Hue)、饱和度(S)和值(V)。

       计算颜色直方图需要将颜色空间划分为若干个小的颜色区间,每个小区间成为直方图的一个bin。这个过程成为颜色量化(color quantization)。然后,通过计算颜色落在每个小区间内的像素数量可以得到颜色直方图。颜色量化有许多种方法,例如向量量化、聚类方法或者神经网络方法。

OpenCV中常用的直方图操作

1)归一化直方图

     cvNormalizeHist(CvHistogram * hist,double factor); factor通常设为1

2)阈值函数

    cvThreshHist(CvHistogram * hist,double factor);factor是一个开关阈值

3)复制直方图

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

4)获得直方图的最小最大值

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

5)计算直方图

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

6)对比两个直方图

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

7)创建直方图

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

举例:  

   int h_bins=30,s_bins=32;
   int hist_size[]={ h_bins, s_bins};
   float h_ranges[]={0,180};
   float s_ranges[]={0,255};
   float * ranges[]={h_ranges,s_ranges};
   CvHistogram * hist;
   hist=cvCreateHist(2,hist_size,CV_HIST_ARRAY,ranges,1);

8)在使用直方图之前给rangs设置数值

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

注意:

    I)uniform 说明直方图是否有均匀的bin,如果设置为非零值,则直方图是均匀的,也可以设置为NULL,意味着rangs是未知的。

    II)这个范围的用处是确定何时计算直方图或决定反向映射

9)释放直方图

如果想重用直方图,可以对其进行清零操作(即设置所有bins为0),或者使用通常的释放函数释放直方图

    void cvClearHist(CvHistogram * hist);

   void cvReleaseHist(CvHistogram ** hist);

10)根据已给出的数据创建直方图

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

11)访问直方图

    double cvQueryHistValue_1D(CvHistogram * hist,int idx0);

    double cvQueryHistValue_2D(CvHistogram * hist,int idx0,int idx1);

    double cvQueryHistValue_3D(CvHistogram * hist,int idx0,int idx1,int idx2);

    double cvQueryHistValue_nD(CvHistogram * hist,int * idxN);

12)反向投影

http://blog.163.com/chenliangren@126/blog/static/168305659201072761518425/

反向投影是一种记录像素点或者像素块如何适应直方图模型中分布的方式。

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

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

应用:

I)如果我们有一个颜色直方图,可以利用反向投影在图像中找到该区域。

II)我们可以用函数cvCalcBackProject()计算一个像素是否是一个已知目标的一部分

III)也可以用函数cvCalcBackProjectPatch()计算一块区域是否包含已知的目标

13)画直方图

http://hi.baidu.com/devisdu/blog/item/2f73ff2d1f15403f349bf712.html

 

(二)反向投影图

      反向投影图,用输入图像的某一位置上像素值(多维或灰度)对应在直方图的一个bin上的值来代替该像素值,所以得到的反向投影图是单通的。用统计学术语,输出图像象素点的值是观测数组在某个分布(直方图)下的概率。图像的反向投影图,简单理解,就是一张概率密度图。反向投影图上的像素点表征着一种概率,如果这个点越亮,就说明这个点属于物体的概率越大。

 

例子:

反向投影图 - 十三月de天空 - 十三月de天空
 
其中 b(xi) 表示在位置 xi 上像素对应的直方图第 b(xi) bin ,直方图共 m bin ,qu表示第ubin的值。
 
例:灰度图像如下

Image=

  0    1    2    3

  4    5    6    7

  8    9   10   11

  8    9   14   15

 

该灰度图的直方图为(bin指定的区间为[0,3)[4,7)[8,11)[12,16)

Histogram=

   4       4       6       2

(3)反向投影图

Back_Projection=

  4    4    4    4

  4    4    4    4

  6    6    6    6

  6    6    2    2

例如位置(0,0)上的像素值为0,对应的bin为[0,3),所以反向直方图在该位置上的值这个bin的值4。

 

用到的函数:

calcBackProject

calcBackProject的输入为图像及其直方图,输出与待跟踪图像大小相同,每一个像素点表示该点为目标区域的概率。这个点越亮,该点属于物体的概率越大。

 

[html]  view plain copy
  1. 测试代码如下:  
  2.   
  3. #include <iostream>  
  4. using namespace std;  
  5. #include <iomanip>  
  6. #include <highgui.h>  
  7. #include <cv.h>  
  8.    
  9. int main()  
  10. {  
  11.          uchar data[]={0,1,2,3,4,5,6,7,8,9,10,11,8,9,14,15};     //图像数据  
  12.          CvMat mat=cvMat(4,4,CV_8UC1,data);  
  13.    
  14.          IplImage g_img;      //灰度图  
  15.          cvGetImage(&mat,&g_img);  
  16.    
  17.          //打印图像数据  
  18.          cout<<"Image="<<endl;  
  19.          for(int i=0;i<g_img.height;i++)  
  20.          {  
  21.                    uchar* ptr=(uchar*)(g_img.imageData+i*g_img.widthStep);  
  22.                    for(int j=0;j<g_img.width;j++)  
  23.                    {  
  24.                             cout<<setw(3)<<setprecision(2)<<(int)ptr[j]<<"  ";  
  25.                    }  
  26.                    cout<<endl;  
  27.          }  
  28.    
  29.          //计算图像直方图  
  30.          IplImage* imgs[]={&g_img};  
  31.          int g_bin=4;  
  32.          int size[]={g_bin};  
  33.          float g_ranges[]={0,4,8,12,16};  
  34.          float* ranges[]={g_ranges};  
  35.          CvHistogram* hist=cvCreateHist(1,size,CV_HIST_ARRAY,ranges,0);  
  36.          cvCalcHist(imgs,hist);  
  37.    
  38.          //打印图像直方图数据  
  39.          cout<<"Histogram="<<endl;  
  40.          for(int i=0;i<g_bin;i++)  
  41.          {  
  42.                    cout<<setw(3)<<setprecision(2)<<*cvGetHistValue_1D(hist,i)<<"  ";  
  43.          }  
  44.          cout<<endl;  
  45.    
  46.          //计算反向投影图  
  47.          IplImage* back_project=cvCreateImage(cvGetSize(&g_img),g_img.depth,1);  
  48.          cvCalcBackProject(imgs,back_project,hist);  
  49.    
  50.          //打印反向投影图数据  
  51.          cout<<"Back_Projection="<<endl;  
  52.          for(int i=0;i<back_project->height;i++)  
  53.          {  
  54.                    uchar* ptr=(uchar*)(back_project->imageData+i*back_project->widthStep);  
  55.                    for(int j=0;j<back_project->width;j++)  
  56.                    {  
  57.                             cout<<setw(3)<<setprecision(2)<<(int)ptr[j]<<"  ";  
  58.                    }  
  59.                    cout<<endl;  
  60.          }  
  61.    
  62. }  

 

     反向投影的作用:反向投影用于在输入图像(通常较大)中查找特定图像(通常较小或者仅1个像素,以下将其称为模板图像)最匹配的点或者区域,也就是定位模板图像出现在输入图像的位置。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
反向投影是一种用于图像分割的技术,它可以将图像中某个特定区域中的像素值与整个图像中的像素值进行比较,从而实现对该区域的分离。OpenCV中提供了多通道直方图算法来实现反向投影,以下是一些示例代码: ```c++ #include <opencv2/opencv.hpp> using namespace cv; int main() { Mat image, hsv; image = imread("image.jpg"); // 转换为HSV格式 cvtColor(image, hsv, COLOR_BGR2HSV); // 设置H、S通道的范围 float h_ranges[] = { 0, 180 }; float s_ranges[] = { 0, 256 }; const float* ranges[] = { h_ranges, s_ranges }; // 设置H、S通道的数量 int h_bins = 16, s_bins = 16; int hist_sizes[] = { h_bins, s_bins }; // 计算图像的直方图 MatND hist; int channels[] = { 0, 1 }; calcHist(&hsv, 1, channels, Mat(), hist, 2, hist_sizes, ranges, true, false); // 归一化直方图 normalize(hist, hist, 0, 255, NORM_MINMAX, -1, Mat()); // 反向投影 Mat dst; calcBackProject(&hsv, 1, channels, hist, dst, ranges, 1, true); // 显示结果 imshow("image", image); imshow("back projection", dst); waitKey(0); return 0; } ``` 在这个示例中,我们首先将图像转换为HSV格式,然后计算出H、S通道的直方图,并将其归一化。接下来,我们使用`calcBackProject`函数来计算反向投影图像,并将结果显示出来。 注意,我们在调用`calcHist`和`calcBackProject`函数时,都需要指定通道数量和通道范围。在本例中,我们使用了两个通道(H、S),并将H通道的范围设置为0到180,S通道的范围设置为0到256。我们还指定了16个bin用于计算直方图,这个值可以根据实际需要进行调整。 希望这些代码可以对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值