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
OpenCV编程->对比直方图,布布扣,bubuko.com
时间: 2024-10-05 16:50:31