opencv学习之路(35)、SURF特征点提取与匹配(三)
一、简介
二、opencv中的SURF算法接口
三、特征点匹配方法
四、代码
1.特征点提取
#include "opencv2/opencv.hpp" #include <opencv2/nonfree/nonfree.hpp> #include <vector> #include<iostream> using namespace std; using namespace cv; void main() { Mat srcImg1 = imread("E://1.jpg"); Mat srcImg2 = imread("E://2.jpg"); //定义SURF特征检测类对象 SurfFeatureDetector surfDetector(400);//SIFT有默认值,SURF没有默认值,需要赋初值 hessianThreshold //定义KeyPoint变量 vector<KeyPoint>keyPoints1; vector<KeyPoint>keyPoints2; //特征点检测 surfDetector.detect(srcImg1, keyPoints1); surfDetector.detect(srcImg2, keyPoints2); //绘制特征点(关键点) Mat feature_pic1, feature_pic2; drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar(0,255,0)); //drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar::all(-1)); //drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar::all(-1), DrawMatchesFlags::DRAW_RICH_KEYPOINTS); drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar::all(-1), DrawMatchesFlags::DRAW_RICH_KEYPOINTS); //显示原图 imshow("src1", srcImg1); imshow("src2", srcImg2); //显示结果 imshow("feature1", feature_pic1); imshow("feature2", feature_pic2); waitKey(0); }
2.暴力匹配(尽量避免使用“nth_element前多少个”筛选)
#include "opencv2/opencv.hpp" #include <opencv2/nonfree/nonfree.hpp> #include <opencv2/legacy/legacy.hpp> #include <vector> #include<iostream> using namespace std; using namespace cv; void main() { Mat srcImg1 = imread("E://11.jpg"); Mat srcImg2 = imread("E://22.jpg"); //定义SURF特征检测类对象 SurfFeatureDetector surfDetector(400); //HessianThreshold //定义KeyPoint变量 vector<KeyPoint>keyPoints1; vector<KeyPoint>keyPoints2; //特征点检测 surfDetector.detect(srcImg1, keyPoints1); surfDetector.detect(srcImg2, keyPoints2); //绘制特征点(关键点) Mat feature_pic1, feature_pic2; drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar::all(-1)); drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar::all(-1)); //显示原图 imshow("src1", srcImg1); imshow("src2", srcImg2); //显示结果 imshow("feature1", feature_pic1); imshow("feature2", feature_pic2); //计算特征点描述符 / 特征向量提取 SurfDescriptorExtractor descriptor; Mat description1; descriptor.compute(srcImg1, keyPoints1, description1); Mat description2; descriptor.compute(srcImg2, keyPoints2, description2); cout<<description1.cols<<endl; cout<<description1.rows<<endl; //进行BFMatch暴力匹配 BruteForceMatcher<L2<float>>matcher; //实例化暴力匹配器 vector<DMatch>matches; //定义匹配结果变量 matcher.match(description1, description2, matches); //实现描述符之间的匹配 //计算向量距离的最大值与最小值 double max_dist=0, min_dist=100; for(int i=0; i<description1.rows; i++) { if(matches.at(i).distance > max_dist) max_dist = matches[i].distance; if(matches.at(i).distance < min_dist) min_dist = matches[i].distance; } cout<<"min_distance="<<min_dist<<endl; cout<<"max_distance="<<max_dist<<endl; //匹配结果筛选 vector<DMatch>good_matches; for(int i=0; i<matches.size(); i++) { if(matches[i].distance < 2*min_dist) good_matches.push_back(matches[i]); } Mat result; //drawMatches(srcImg1, keyPoints1, srcImg2, keyPoints2, matches, result, Scalar::all(-1), Scalar::all(-1)); drawMatches(srcImg1, keyPoints1, srcImg2, keyPoints2, good_matches, result, Scalar(0, 255, 0), Scalar::all(-1)); imshow("Match_Result", result); waitKey(0); }
因为surf检测到的角点比较少,所以不适合做小目标匹配。
同样代码,使用sift作对比
3.FlannBasedMatcher匹配
//BruteForceMatcher<L2<float>>matcher; //实例化暴力匹配器 FlannBasedMatcher matcher; //实例化FLANN匹配器 vector<DMatch>matches; //定义匹配结果变量 matcher.match(description1, description2, matches); //实现描述符之间的匹配
其余代码相同