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