1)SIFT特征提取匹配的步骤 A使用SiftFeatureDector的detect方法检测特征存入一个向量(可以使用drawKeypoints在图中标记出来) B使用SiftDescriptorExtractor的compute方法提取特征描述符(特征向量),特征描述符是一个矩阵 C使用匹配器matcher对描述符进行匹配 D匹配结果保存由DMatch的组成的向量里设置距离阈值,使得匹配的向量距离小于阈值才能进入最终的结果 E用DrawMatch绘制显示匹配结果
特征描述符(特征向量)提取: void compute(const Mat&image,CV_OUT CV_IN_OUT std:vector&keypoints,CV_OUT Mat&descriptors)const;
SiftDescriptorExtractor descriptor; Mat decscription1; descriptor.compute(srcImg1,keyPoints1,description1);
使用匹配器进行匹配 1)Brute-Force匹配的基础 暴力匹配器 很简单,首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行(描述符)距离进行测试,最后返回距离相近的关键点 BFMatcher(int normType=NORM_L2,bool crossCheck=false) &&normType:用于指定要使用的距离测试类型,默认值NORM_L2,LI和L2较适用SIFT和SUFT算法 &&crossCheck:是否交叉检测,默认值false(不使用)。如果设置为true,匹配条件就会更加严格,只有到A中的第i个特征点与B中的第j个特征点距离最近,并且B中的第j个特征点到A中的第i个特征点也是最近(A中没有其他的点到j的距离最近)时才会返回最佳匹配(i,j)也就是这两个特征点要互相匹配才行 void match(const Mat & queryDescriptors,const Mat&trainDescriptors,CV_OUT vector /DMarch>&matches,const Mat &mask=Mat())const; 注意要加下面文件及lib #include/opencv/nofree/nofree.hpp> #include/opencv2/legacy/legacy.hpp> opencv_nofree248.lib opencv_legacy248d.lib
DMatch结构体—用于存放匹配结果的结构 struct DMatch { //三个构造函数 intqueryIdx://此匹配对应的查询图像的特征描述子索引 inttrainIdx://此匹配对应的训练(模板)图像的特征描述子索引 intimgIdx:训练图像的索引(若有多个) float distance://两个特征向量之间的欧式距离。越小表明匹配度越高 boolperator<(const DMatch &m)const; } 绘制匹配结果: void drawMatches(const Mat&img1,const vector/KeyPoint>&keypoints1,const Mat &img2,const vector/KeyPoint>&keypoints2,const vector/DMatch>&matches1to2,Mat&outImg,const Scalar &matchColor=Scalar::all(-1),const Scalar &singlePointColor=Scalar:all(-1), const vector/char>&matchesMask=vector/char>(),int flags=DrawMatchesFlags::DEFAULT);
&&img1:输入的第一幅图像 &&keypoints1:根据第一幅图像得到的特征点 &&img2:输入的第二幅图像 &&keypoints2:根据第二幅图像得到的特征点 &&matches1to2:第一幅图像到第二幅图像的匹配点,即表示每一图1中的特征点都能在图二中有一一对应的点 &&outImg:输出图像,包含匹配结果,与flags参数有关 &&matchColor:匹配的输出颜色,即匹配到的线和匹配点的颜色,默认值Scalar:all(-1) &&singlePointColor:单一特征点的颜色,默认值Scalar:all(-1) &&matchesMask:确定哪些匹配是要绘制出来的掩码,为空则所有匹配都绘制 &&flags:特征绘制的标识符,默认值DrawmatchesFlags::DEFAULY,可以在下面选 struct CVEXPORTS DrawMatchesFlags { enum { DEFAULT=0, DRAW_OVER_OUTIMG=1, NOT_DRAW_SINGLE_POINTS=2, DRAW_RICH_KEYPOINTS=4 };
}
Mat srcImg1=imread("00.jpg"); Mat srcImg2=imread("01.jpg"); //定义SIFT特征检测类对象 SiftFeatureDetector siftDectector1; SiftFeatureDetector siftDectector2; //定义keyPoint变量 vector<KeyPoint>keyPoints1; vector<KeyPoint>keyPoints2; //特征点检测 siftDetector1.dector(srcImg1,keyPoints1); siftDetector2.dector(srcImg2,keyPoints2); //绘制特征点(关键点) Mat feature_pic1,feature_pic2; drawKeypoints(srcImg1,KeyPoints1,feature_pic1,Scalar::all(-1)) drawKeypoints(srcImg2,keyPoints2,feature_pic2,Scalar::all(-1)) //drawKeypoints(srcImg1,keyPoints1,feature_pic1,Scalar(0,255,0),DrawMatchesFlags::DRAW_RICH_KEYPOINTS); //drawKeupoints(srcImg2,keyPonts2,feature_pic2,Scalar(0,255,0),DrawMatchesFlags::DRAW_RICH_KEYPOINTS); //显示原图 imshow("src1",srcImg1); imshow("src2",srcImg2); //显示结果 imshow("feature",feature_pic1); imshow("feature",feature_pic2); //计算特征点描述符/特征向量提取 SiftDescriptorExtractor descriptor; Mat description1; descriptor.compute(srcImg1,KeyPoints1,description1); Mat description2; descriptor.compute(srcImg2,keyPoints2,description2); cout<<description1.rows<<endl; cout<<description1.cols<<endl; //进行BFMatch暴力匹配 BruteForceMatcher<L2<float>>matcher;//实例化暴力匹配器 vector<DMatch>matches;//定义匹配结果变量 matcher.match(description1,description2,matched);//实现描述符之间的匹配 //匹配结果删选 std::nth_element(matches.begin(),matches.begin()+29,matches.end());//提取出前30个最佳匹配结果 matched.erase(matches.begin()+30,matched..end());//剔除掉其余的匹配结果 Mat result; drawMatches(srcImg1,keyPoints1,srcImg2,keyPoints2,matches,result,Scalar(0,255,0),Scalar::all(-1)); imshow("Match_reuslt",result); waitKey(0); //另一种删选方法 //计算向量距离的最大值与最小值 double max_dist=0,min_dist=100; for(int i=0;i<description1.rows;i++) { if(matches.at(i).distance>mac_dist) max_dist=matches[i].distance; if(matched.at(i).distance<min_dist) min_dist=matched[i].distance; } cont<<"min_distance"<<min_dist<<endl; cout<<"max_distance"<<max_dist<<endl; //匹配结果删选 vector<DMatch>good_matched; for(int i=0;i<matches.size();i++) { if(matches[i].distance<2*min_dist) good_matched.push_back(matched[i]); } Mat result; drawMatches(srcImg1,keyPoints1,srcImg2,keyPoints2,good_matches,result,Scalar(0,255,0),Scalar::all(-1)); imshow("Match_result",result); waitKey(0);