首页 > 代码库 > OpenCV编程->对比直方图

OpenCV编程->对比直方图

      OpenCv提供了5种对比直方图的方式:CORREL(相关)、CHISQR(卡方)、INTERSECT(相交)、BHATTACHARYYA、EMD(最小工作距离),其中CHISQR速度最快,EMD速度最慢且有诸多限制,但是EMD的效果可能最好。

      接下来开始测试一下:

对比函数如下:

#define cvQueryHistValue_3D( hist, idx0, idx1, idx2 )      cvGetReal3D( (hist)->bins, (idx0), (idx1), (idx2) ) 
//画直方图用
int HistogramBins = 256;
float HistogramRange1[2]={0,255};
float *HistogramRange[1]={&HistogramRange1[0]};

void histemd(IplImage* src,IplImage* src1)
{
   IplImage* hsv = cvCreateImage( cvGetSize(src), 8, 3 );  
   IplImage* hsv1 = cvCreateImage( cvGetSize(src), 8, 3 );  
   cvCvtColor( src, hsv, CV_BGR2HSV );  
   cvCvtColor( src1, hsv1, CV_BGR2HSV );  
   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* h_plane1 = cvCreateImage( cvGetSize(src), 8, 1 );  
   IplImage* s_plane1 = cvCreateImage( cvGetSize(src), 8, 1 );  
   IplImage* v_plane1 = cvCreateImage( cvGetSize(src), 8, 1 );  
   IplImage* planes[] = { h_plane, s_plane,v_plane };  
   IplImage* planes1[] = { h_plane1, s_plane1,v_plane1 };  
    cvSplit( hsv, h_plane, s_plane, v_plane, 0 );  
    cvSplit( hsv1, h_plane1, s_plane1, v_plane1, 0 );  
   // Build the histogram and compute its contents.  
   //计算规模与h_bins*s_bins*v_bins成指数关系,原先 int h_bins = 32, s_bins = 30, v_bins = 8 时,运行半天都没反应  
   int h_bins = 8, s_bins = 5, v_bins = 5; 
    CvHistogram* hist, *hist1;  
   {  
      int hist_size[] = { h_bins, s_bins ,v_bins};  
      float h_ranges[] = { 0, 180 }; // hue is [0,180]  
      float s_ranges[] = { 0, 255 };  
      float v_ranges[] = { 0, 255 };  
      float* ranges[] = { h_ranges, s_ranges ,v_ranges};  
      hist = cvCreateHist(  
         3,  
         hist_size,  
         CV_HIST_ARRAY,  
         ranges,  
         1  
         );  
      hist1 = cvCreateHist(  
         3,  
         hist_size,  
         CV_HIST_ARRAY,  
         ranges,  
         1  
         );  
   }  
   cvCalcHist( planes, hist, 0, 0 ); //Compute histogram  
   cvNormalizeHist( hist, 1.0 ); //Normalize it  
   cvCalcHist( planes1, hist1, 0, 0 ); //Compute histogram  
   cvNormalizeHist( hist1, 1.0 ); //Normalize it  
  
   CvMat* sig1,*sig2;  
   int numrows = h_bins*s_bins*v_bins;  

   sig1 = cvCreateMat(numrows, 4, CV_32FC1);   
   sig2 = cvCreateMat(numrows, 4, CV_32FC1);   
   int h,s,v;  
   for( h = 0; h < h_bins; h++ )   
   {  
      for( s = 0; s < s_bins; s++ )  
      {  
         for( v=0; v < v_bins; v++)  
         {  
            float bin_val = cvQueryHistValue_3D( hist, h, s,v );  
              
            cvSet2D(sig1,h*s_bins*v_bins + s*v_bins+v,0,cvScalar(bin_val)); //bin value  
            cvSet2D(sig1,h*s_bins*v_bins + s*v_bins+v,1,cvScalar(h)); //Coord 1  
            cvSet2D(sig1,h*s_bins*v_bins + s*v_bins+v,2,cvScalar(s)); //Coord 2  
            cvSet2D(sig1,h*s_bins*v_bins + s*v_bins+v,3,cvScalar(v)); //Coord 3  
  
            bin_val = cvQueryHistValue_3D( hist1, h, s,v );  
            cvSet2D(sig2,h*s_bins*v_bins + s*v_bins+v,0,cvScalar(bin_val)); //bin value  
            cvSet2D(sig2,h*s_bins*v_bins + s*v_bins+v,1,cvScalar(h)); //Coord 1  
            cvSet2D(sig2,h*s_bins*v_bins + s*v_bins+v,2,cvScalar(s)); //Coord 2  
            cvSet2D(sig2,h*s_bins*v_bins + s*v_bins+v,3,cvScalar(v)); //Coord 3  
  
         }  
      }  
   }  
      
   float emd = cvCalcEMD2(sig1,sig2,CV_DIST_L2);  
   printf("CV_COMP_EMD :%3.1f%%",(1-emd)*100);  
  
   cvNamedWindow( "Source1", 1 );  
   cvMoveWindow("Source1", 0, 0);  
   cvShowImage( "Source1", src );  
   cvNamedWindow( "Source2", 1 );  
   cvMoveWindow("Source2", 550, 0);  
   cvShowImage( "Source2", src1 );  
   cvWaitKey(0);  
}

void CompareHist(const char* imagefile1, const char* imagefile2)
{
    IplImage *image1=cvLoadImage(imagefile1, 0);
    IplImage *image2=cvLoadImage(imagefile2, 0);

	IplImage *image3=cvLoadImage(imagefile1,1);
    IplImage *image4=cvLoadImage(imagefile2,1);

    CvHistogram *Histogram1 = cvCreateHist(1, &HistogramBins, CV_HIST_ARRAY,HistogramRange);
    CvHistogram *Histogram2 = cvCreateHist(1, &HistogramBins, CV_HIST_ARRAY,HistogramRange);

    cvCalcHist(&image1, Histogram1);
    cvCalcHist(&image2, Histogram2);

    cvNormalizeHist(Histogram1, 1);
    cvNormalizeHist(Histogram2, 1);

    // CV_COMP_CHISQR,CV_COMP_BHATTACHARYYA这两种都可以用来做直方图的比较,值越小,说明图形越相似
    printf("CV_COMP_CHISQR : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_CHISQR));//卡方
    printf("CV_COMP_BHATTACHARYYA : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_BHATTACHARYYA));

    // CV_COMP_CORREL, CV_COMP_INTERSECT这两种直方图的比较,值越大,说明图形越相似
    printf("CV_COMP_CORREL : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_CORREL));//相关
    printf("CV_COMP_INTERSECT : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_INTERSECT));//相交
	 histemd(image3,image4);

}
在主函数里面调用:

 CompareHist("1001.png", "1002.png");
得到如下测试结果:



对于不同图片:


对于做直方图对比,对比图像的颜色背景需要一致,不然就出入很大。

参考:

http://www.cnblogs.com/slysky/archive/2011/10/13/2210745.html

http://blog.csdn.net/nicebooks/article/details/8175002