核心函数:

cvFindContours

cvApproxPoly

cvCreateContourTree

cvMatchContourTrees

结果:

完全相同的图像比较结果:

wKioL1PsEuGhA386AAK6VC9shXw634.jpg

完全不同的图像的比较结果:

wKiom1PsEdXBF3zwAAJyd4c3pGU678.jpg

形变的结果:可以看出直接用轮廓进行比较结果几乎为两个不相同的图像,而用多边形逼近建立的轮廓树进行比较还具有相当的相似度

wKiom1PsEe3w9za_AAIEQAG7Dbk331.jpg

改变箭头方向比较:

wKioL1PsE3WzW9G8AAK_JFitEHE701.jpg

wKiom1PsEmjzVhi7AAK-yrgLI_I972.jpg

wKioL1PsE5CjrCtYAAMdjOhq_5M509.jpg

改变方向,大小,形变比较:感觉效果不理想

wKiom1PsEoSgNkPcAAKqFZJ1Yts252.jpg

代码:

#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <iostream>
#include "function.h"
int MatchContour(int argc,char** argv)
{
IplImage *Src1=cvLoadImage("e:\\picture\\jiantou.jpg",0);
IplImage *Src2=cvLoadImage("e:\\picture\\jiantougai.jpg",0);
IplImage *BinaryImage1=cvCreateImage(cvGetSize(Src1),Src1->depth,1);
IplImage *BinaryImage2=cvCreateImage(cvGetSize(Src2),Src2->depth,1);
IplImage *SrcColor1=cvCreateImage(cvGetSize(Src1),Src1->depth,3);
IplImage *SrcColor2=cvCreateImage(cvGetSize(Src2),Src2->depth,3);
cvThreshold(Src1,BinaryImage1,100,255,CV_THRESH_BINARY);
cvThreshold(Src2,BinaryImage2,100,255,CV_THRESH_BINARY);
IplImage *BinaryImageTemp1=cvCloneImage(BinaryImage1);
IplImage *BinaryImageTemp2=cvCloneImage(BinaryImage2);
//求轮廓
CvMemStorage* storage1=cvCreateMemStorage(0);
CvMemStorage* storage2=cvCreateMemStorage(0);
CvSeq* ContourSeq1=NULL;
CvSeq* ContourSeq2=NULL;
cvFindContours(BinaryImageTemp1,storage1,&ContourSeq1,sizeof(CvContour));
cvFindContours(BinaryImageTemp2,storage2,&ContourSeq2,sizeof(CvContour));
cvCvtColor(Src1,SrcColor1,CV_GRAY2BGR);
cvCvtColor(Src2,SrcColor2,CV_GRAY2BGR);
IplImage* ApproxPolyColor1=cvCloneImage(SrcColor1);
IplImage* ApproxPolyColor2=cvCloneImage(SrcColor2);
cvDrawContours(SrcColor1,ContourSeq1,cvScalar(255,0,0),cvScalar(0,255,0),100,2);
cvDrawContours(SrcColor2,ContourSeq2,cvScalar(255,0,0),cvScalar(0,255,0),100,2);
cvNamedWindow("src1");
cvNamedWindow("src2");
cvNamedWindow("coutour1");
cvNamedWindow("coutour2");
cvShowImage("src1",BinaryImage1);
cvShowImage("src2",BinaryImage2);
cvShowImage("coutour1",SrcColor1);
cvShowImage("coutour2",SrcColor2);
//求多边形逼近的轮廓
double threshold1=0.001;
CvSeq* ApproxPolySeq1=cvApproxPoly(ContourSeq1,sizeof(CvContour),NULL,CV_POLY_APPROX_DP,cvContourPerimeter(ContourSeq1)*threshold1,0);
CvSeq* ApproxPolySeq2=cvApproxPoly(ContourSeq2,sizeof(CvContour),NULL,CV_POLY_APPROX_DP,cvContourPerimeter(ContourSeq1)*threshold1,0);
cvDrawContours(ApproxPolyColor1,ApproxPolySeq1,cvScalar(255,0,0),cvScalar(0,255,0),100,2);
cvDrawContours(ApproxPolyColor2,ApproxPolySeq2,cvScalar(255,0,0),cvScalar(0,255,0),100,2);
cvNamedWindow("ApproxPolyColor1");
cvNamedWindow("ApproxPolyColor2");
cvShowImage("ApproxPolyColor1",ApproxPolyColor1);
cvShowImage("ApproxPolyColor2",ApproxPolyColor2);
//分别建立正常轮廓和多边形逼近轮廓的ContourTree然后比较
CvMemStorage* storage3=cvCreateMemStorage(0);
CvMemStorage* storage4=cvCreateMemStorage(0);
CvMemStorage* storage5=cvCreateMemStorage(0);
CvMemStorage* storage6=cvCreateMemStorage(0);
CvContourTree* ContourTree1=cvCreateContourTree(ContourSeq1,storage3,0);
CvContourTree* ContourTree2=cvCreateContourTree(ContourSeq2,storage4,0);
CvContourTree* ContourTree3=cvCreateContourTree(ApproxPolySeq1,storage5,0);
CvContourTree* ContourTree4=cvCreateContourTree(ApproxPolySeq2,storage6,0);
double match1=cvMatchContourTrees(ContourTree1,ContourTree2,CV_CONTOUR_TREES_MATCH_I1,100);
double match2=cvMatchContourTrees(ContourTree3,ContourTree4,CV_CONTOUR_TREES_MATCH_I1,100);
std::cout<<"注释:完全相同的图像的相似度为0"<<std::endl;
std::cout<<"逼近精度取周长的 "<<threshold1<<" 倍"<<std::endl;
std::cout<<"直接用轮廓创建轮廓树进行比较的相似度:"<<match1<<std::endl;
std::cout<<"用多边形逼近轮廓创建轮廓树比较的相似度:"<<match2<<std::endl;
cvWaitKey(0);
return 0;
}