Opencv 直方图使用

 

OpenCV直方图的使用


目录(?)[+]

主要涉及两个函数:

CvHistogram
cvCalcHist

   
   
   
   
[cpp] view plain copy
  1. #include<stdio.h>  
  2. #include<cv.h>  
  3. #include<highgui.h>  
  4. int main()  
  5. {  
  6.     int hist_size[]={16,16,16};  
  7.     float range[]={0,255};  
  8.     float *ranges[]={range};  
  9.     int i,j,bin_w;  
  10.     float max_value,min_value;  
  11.     int min_idx, max_idx;  
  12.     char *name[3]={"b","g","r"};  
  13.     double mean=0,variance=0;  
  14.     IplImage* img=cvLoadImage("b.jpg",1);  
  15.     IplImage *pImage=NULL;  
  16.     IplImage *pImg[3];  
  17.     pImg[0]=cvCreateImage(cvGetSize(img),8,1);  
  18.     pImg[1]=cvCreateImage(cvGetSize(img),8,1);  
  19.     pImg[2]=cvCreateImage(cvGetSize(img),8,1);  
  20.     cvSplit(img,pImg[0],pImg[1],pImg[2],NULL);  
  21.     pImage=cvCloneImage(img);  
  22.   
  23.     CvRect rect= cvRect(0,0,500,600);  
  24.     cvSetImageROI(pImage,rect);  
  25.    
  26.     //创建一个图像用来存放直方图  
  27.     IplImage *histImage[3];  
  28.     CvHistogram *hist[3];  
  29.     for(j=0;j<3;j++){  
  30.         histImage[j]=cvCreateImage(cvSize(320,200),8,3);  
  31.         //cvZero(histImage[j]);  
  32.         hist[j]=cvCreateHist(1,&hist_size[j],CV_HIST_ARRAY,ranges,1);  
  33.         //计算直方图并作用到hist变量中  
  34.         cvCalcHist(&pImg[j], hist[j], 0, NULL);  
  35.         //得到直方图的最值及标号  
  36.         cvGetMinMaxHistValue(hist[j],&min_value,&max_value,&min_idx,&max_idx);  
  37.         //缩放其最大值和最小值让其融入图像  
  38.         cvScale(hist[j]->bins,hist[j]->bins,((double)histImage[j]->height)/max_value,0);  
  39.         //设置所有的直方图的数值为255  
  40.         cvSet(histImage[j],cvScalarAll(255),0);  
  41.         //建一个比例因子  沿宽度释放  
  42.         bin_w=cvRound((double)histImage[j]->width/hist_size[j]);  
  43.         mean=0;  
  44.         for(i=0;i<hist_size[j];i++)  
  45.         {  
  46.             CvScalar scalar=cvScalarAll(0);  
  47.             scalar.val[j]=(i*255/hist_size[j]);  
  48.             cvRectangle(histImage[j],cvPoint(i*bin_w,histImage[j]->height),  
  49.             cvPoint((i+1)*bin_w,histImage[j]->height-cvRound(cvGetReal1D(hist[j]->bins,i))),scalar,-1,8,0);  
  50.    
  51.             float *bins=cvGetHistValue_1D(hist[j],i);  
  52.             //增加均值  
  53.             mean+=bins[0];  
  54.             //std::cout<<bins[0]<<" "<<bins[1]<<std::endl;  
  55.             //printf("%d %d\n",bins[0],bins[1]);  
  56.         }  
  57.         cvNamedWindow(name[j],0);  
  58.         cvShowImage(name[j],histImage[j]);  
  59.           
  60.         mean/=hist_size[j];  
  61.         //根据均值计算变化量  
  62.         for(i=0;i<hist_size[j];i++)  
  63.         {  
  64.             float* bins=cvGetHistValue_1D(hist[j],i);  
  65.             variance+=pow((bins[0]-mean),2);  
  66.         }  
  67.    
  68.         variance/=hist_size[j];  
  69.         printf("histgram Mean:%f\n",mean);  
  70.   
  71.     }  
  72.       
  73.     //创建窗口  
  74.     cvNamedWindow("Original",0);  
  75.     cvShowImage("Original",pImage);  
  76.     cvWaitKey(0);  
  77.     cvReleaseImage(&img);  
  78.     for(j=0;j<3;j++){  
  79.         cvDestroyWindow(name[j]);  
  80.         cvReleaseImage(&pImg[j]);  
  81.         cvReleaseImage(&histImage[j]);  
  82.         cvReleaseHist(&hist[j]);  
  83.     }  
  84.     cvDestroyWindow("Original");  
  85.     return 0;  
  86. }  

Opencv 直方图使用_第1张图片

Opencv 直方图使用_第2张图片Opencv 直方图使用_第3张图片Opencv 直方图使用_第4张图片 CvHistogram结构

[cpp] view plain copy
  1. typedef struct CvHistogram  
  2. {  
  3.     int     type;  
  4.     CvArr*  bins;  
  5.     float   thresh[CV_MAX_DIM][2]; /* for uniform histograms */  
  6.     float** thresh2; /* for non-uniform histograms */  
  7.     CvMatND mat; /* embedded matrix header for array histograms */  
  8. }  
  9. CvHistogram;  

bins :用于存放直方图每个灰度级数目的数组指针,数组在cvCreateHist的时候创建,其维数由cvCreateHist确定(一般以一维比较常见)

CreateHist

[cpp] view plain copy
  1. 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之间的空间。

CalcHist

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

void cvCalcHist( IplImage** image, CvHistogram* hist,                   int accumulate=0, const CvArr* mask=NULL );
image
输入图像 s(虽然也可以使用 CvMat**).
hist
直方图指针
accumulate
累计标识。如果设置,则直方图在开始时不被清零。这个特征保证可以为多个图像计算一个单独的直方图,或者在线更新直方图。
mask
操作   mask,确定输入图像的哪个象素被计数
函数  cvCalcHist  计算单通道或多通道图像的直方图。 用来增加直方块的数组元素可从相应输入图像的同样位置提取。

CalcHist

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

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

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

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

http://blog.csdn.net/lansatiankongxxc/article/details/8272633

这个程序根据输入的图像计算出一个色相饱和度直方图,然后利用网格的方式将直方图以网格形式显示。

[cpp]  view plain copy
  1. #include<cv.h>  
  2. #include<highgui.h>  
  3. #include<stdio.h>  
  4.   
  5. #pragma comment(lib, "cv.lib")  
  6. #pragma comment(lib, "cxcore.lib")  
  7. #pragma comment(lib, "highgui.lib")  
  8.   
  9. int main()  
  10. {  
  11.     IplImage* src = NULL;  
  12.     src = cvLoadImage ("test.png", 1);  
  13.       
  14.     IplImage* hsv = cvCreateImage (cvGetSize(src), 8, 3);  
  15.     cvCvtColor (src, hsv, CV_BGR2HSV);  
  16.       
  17.     IplImage* h_plane = cvCreateImage (cvGetSize(src), 8, 1);  
  18.     IplImage* s_plane = cvCreateImage (cvGetSize(src), 8, 1);  
  19.     IplImage* v_plane = cvCreateImage (cvGetSize(src), 8, 1);  
  20.     IplImage* planes[] = {h_plane, s_plane};  
  21.     cvCvtPixToPlane (hsv, h_plane, s_plane, v_plane, 0);   
  22.   
  23.     /*创建和计算直方图*/  
  24.   
  25.     int h_bins = 30;  
  26.     int s_bins = 32;  
  27.     CvHistogram* hist = NULL;  
  28.     int hist_size[] = {h_bins, s_bins};  
  29.     float h_ranges[] = {0, 180};  
  30.     float s_ranges[] = {0, 255};  
  31.     float* ranges[] = {h_ranges, s_ranges};  
  32.     hist = cvCreateHist (2, hist_size, CV_HIST_ARRAY, ranges, 1);  
  33.     cvCalcHist (planes, hist, 0, 0); //计算直方图  
  34.     cvNormalizeHist (hist, 1.0);   //归一化  
  35.   
  36.     /*测试匹配度并输出*/  
  37.       
  38.     /*double like = cvCompareHist (hist, hist, CV_COMP_INTERSECT); 
  39.     printf("%lf\n", like);*/  
  40.   
  41.     /*创建一个图像来可视化我们的直方图*/  
  42.   
  43.     int scale = 10;  
  44.     IplImage* hist_img = cvCreateImage (cvSize(h_bins * scale, s_bins * scale), 8, 3);  
  45.     cvZero (hist_img);  
  46.   
  47.     /*用小的灰度方格填充hist_img*/  
  48.   
  49.     float max_value = 0;  
  50.     cvGetMinMaxHistValue (hist, 0, &max_value, 0, 0);  
  51.     for (int h = 0; h < h_bins; h++)  
  52.     {  
  53.         for (int s = 0; s < s_bins; s++)  
  54.         {  
  55.             float bin_val = cvQueryHistValue_2D (hist, h, s);  
  56.             int intensity = cvRound (bin_val * 255 / max_value);  
  57.             cvRectangle (hist_img, cvPoint(h*scale, s*scale), cvPoint((h+1)*scale-1, (s+1)*scale-1),   
  58.                 CV_RGB(intensity, intensity, intensity),CV_FILLED);  
  59.         }  
  60.     }  
  61.     cvNamedWindow ("src", 1);  
  62.     cvShowImage ("src", src);  
  63.     cvNamedWindow ("H-S histogram", 1);  
  64.     cvShowImage ("H-S histogram", hist_img);  
  65.   
  66.     cvWaitKey (0);  
  67.   
  68.     cvReleaseImage (&src);  
  69.     cvReleaseImage (&hsv);  
  70.     cvReleaseImage (&hist_img);  
  71.     cvReleaseHist (&hist);  
  72.   
  73.     return 0;  
  74. }  

在实验中,需要用到OpenCV直方图,并读取其中的bins里的信息,于是做了一些测试,确定了OpenCV直方图的创建方法与bins(直方图的格子们)信息读取方法。

1.如何使用自己的数据建立直方图结构。  使用的函数为cvMakeHistHeaderForArray() 

[cpp]  view plain copy
  1. CvHistogram* cvMakeHistHeaderForArray(  
  2.       int dims,  
  3.       int* sizes,  
  4.       CvHistogram* hist,  
  5.       float* data,  
  6.       float** ranges=NULL,  
  7.       int uniform=1 );   
hist  为函数所初始化的直方图头  data  用来存储直方块的数组

举个例子来理解上面函数中的各个参数,下面我将使用自己创建的数据来创建一个一维的直方图,看过《学习OpenCV》的人对于大部分参数应该都理解了,这里就着重介绍和函数cvMakeHistHeaderForArray关系密切的参数。

[cpp]  view plain copy
  1. int dims=1;  
  2. int sizes[]={8};  
  3. float data[8]={30,32,60,89,98,87,87,87};  
  4. float range1[]={0,8};  
  5. float *ranges[]={range1};  
  6. CvHistogram *hist=cvCreateHist(dims,sizes,CV_HIST_ARRAY,ranges,1);  
  7. CvHistogram *hist1=cvMakeHistHeaderForArray(dims,sizes,hist,data,ranges,1);   
函数需要一个指向结构CvHistogram 的指针hist,这个指针在使用之前必须经过初始化,即必须是分配过空间的。这个函数还有dims,sizes,ranges,uniform这几个参数,说明这个函数还可以以这些参数产生新的直方图。经过测试,这个函数返回的直方图hist1和以形参形式传入的hist的值是一样的。  其实我很奇怪,不知道这个函数这样做的原因是什么,既然函数运行会改变形参对应的直方图hist的值,那为什么还要来个返回值呢?

2.如何改变直方图bins中的数据。  我想这个很多看过《学习OpenCV》的高手应该都知道了,我是第二遍回来看的时候才感觉到的,所以还是说下吧。  第一个方法是使用函数cvGetHistValue_1D(CvHistogram* hist,int idx0)这个函数接受一个直方图结构和一个索引值,并返回一个指向对应bins的一个指针ptr。那么就可以使用这个指针访问这个bins的值了。比如给这个bins重新赋值为56,语句为“*ptr=56.f”。  第二个方法是使用指针定位直方图中数据结构部分的数据。”hist->mat.data.fl[0]”这里我假设我访问的是一维直方图的第一个元素。同样的,用“hist->mat.data.fl[0]=56”就可以进行赋值操作了。



    
    
    
    





你可能感兴趣的:(Opencv 直方图使用)