一、簡介
二、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); //實現描述符之間的匹配
其余代碼相同