SIFT特徵檢測與RANSAC過濾
阿新 • • 發佈:2019-02-01
/* *@function SiftDetect.cpp *@brief 對sift特徵檢測和匹配進行測試,並實現RANSAC演算法進行過濾錯配點 *@author ltc *@date 11:20 Saturday,28 November,2015 */ #include<iostream> #include<opencv2\opencv.hpp> #include<opencv2\nonfree\nonfree.hpp> using namespace std; using namespace cv; //RANSAC演算法 vector<DMatch> ransac(vector<DMatch> matches,vector<KeyPoint> queryKeyPoint,vector<KeyPoint> trainKeyPoint); int main(int argc,char* argv[]) { //影象讀取 Mat img1,img2; img1=imread("1 (2).jpg",CV_WINDOW_AUTOSIZE); img2=imread("2 (2).jpg",CV_WINDOW_AUTOSIZE); if(img1.empty()||img2.empty()) { return -1; } //sift特徵提取 SiftFeatureDetector detector; vector<KeyPoint> keyPoint1,keyPoint2; detector.detect(img1,keyPoint1); detector.detect(img2,keyPoint2); //cout<<"Number of KeyPoint1:"<<keyPoint1.size()<<endl; //cout<<"Number of KeyPoint2:"<<keyPoint2.size()<<endl; //sift特徵描述子計算 SiftDescriptorExtractor desExtractor; Mat des1,des2; desExtractor.compute(img1,keyPoint1,des1); desExtractor.compute(img2,keyPoint2,des2); //sift特徵點(描述子)匹配 Mat res1,res2; // drawKeypoints(img1,keyPoint1,res1,Scalar::all(-1),/*DrawMatchesFlags::DRAW_RICH_KEYPOINTS*/DrawMatchesFlags::DEFAULT); // drawKeypoints(img2,keyPoint2,res2,Scalar::all(-1),/*DrawMatchesFlags::DRAW_RICH_KEYPOINTS*/DrawMatchesFlags::DEFAULT); BFMatcher matcher(NORM_L2); FlannBasedMatcher matcher_flann; vector<DMatch> matches; vector<vector<DMatch>> matches_knn; matcher.match(des1,des2,matches); matcher.knnMatch(des1,des2,matches_knn,2); // cout<<"matches_knn.size:"<<matches_knn.size()<<endl; //sift特徵最近距離與次近距離之比小於0.6視為正確匹配 vector<DMatch> match_knn; for(int i=0;i<matches_knn.size();i++) { float ratio=matches_knn[i][0].distance/matches_knn[i][1].distance; if(ratio<0.6) { match_knn.push_back(matches_knn[i][0]); } } // matcher_flann.match(des1,des2,matches_flann); //for(int i=0;i<matches.size();i++) //{ // cout<<"第"<<i<<"對匹配:"<<endl; // cout<<"queryIdx:"<<matches[i].queryIdx<<"\ttrainIdx:"<<matches[i].trainIdx<<endl; // cout<<"imgIdx:"<<matches[i].imgIdx<<"\tdistance:"<<matches[i].distance<<endl; //} //cout<<"Number of matches:"<<matches.size()<<endl; //cout<<"Number of matches_flann:"<<matches_flann.size()<<endl; vector<DMatch> matches_ransac=ransac(matches,keyPoint1,keyPoint2); Mat img_match,img_match_flann; drawMatches(img1,keyPoint1,img2,keyPoint2,matches_ransac,img_match); drawMatches(img1,keyPoint1,img2,keyPoint2,match_knn,img_match_flann); imshow("img_match",img_match); imshow("img_match_flann",img_match_flann); //for(size_t i=0;i<keyPoint1.size();i++) //{ // //cout<<"x:"<<kp1.at(i).pt.x<<endl; // circle(img1,Point((int)(keyPoint1.at(i).pt.x),(int)(keyPoint1.at(i).pt.y)),3,Scalar(255,0,0),2,8,0); //} //imshow("img1",img1); //imshow("img1_",res1); // imshow("img2",res2); ransac(matches,keyPoint1,keyPoint2); waitKey(0); return 0; } //RANSAC演算法實現 vector<DMatch> ransac(vector<DMatch> matches,vector<KeyPoint> queryKeyPoint,vector<KeyPoint> trainKeyPoint) { //定義儲存匹配點對座標 vector<Point2f> srcPoints(matches.size()),dstPoints(matches.size()); //儲存從關鍵點中提取到的匹配點對的座標 for(int i=0;i<matches.size();i++) { srcPoints[i]=queryKeyPoint[matches[i].queryIdx].pt; dstPoints[i]=trainKeyPoint[matches[i].trainIdx].pt; } //儲存計算的單應性矩陣 Mat homography; //儲存點對是否保留的標誌 vector<unsigned char> inliersMask(srcPoints.size()); //匹配點對進行RANSAC過濾 homography = findHomography(srcPoints,dstPoints,CV_RANSAC,5,inliersMask); //RANSAC過濾後的點對匹配資訊 vector<DMatch> matches_ransac; //手動的保留RANSAC過濾後的匹配點對 for(int i=0;i<inliersMask.size();i++) { //cout<<inliersMask[i]<<endl; cout<<(int)(inliersMask[i])<<endl; if(inliersMask[i]) { matches_ransac.push_back(matches[i]); //cout<<"第"<<i<<"對匹配:"<<endl; //cout<<"queryIdx:"<<matches[i].queryIdx<<"\ttrainIdx:"<<matches[i].trainIdx<<endl; //cout<<"imgIdx:"<<matches[i].imgIdx<<"\tdistance:"<<matches[i].distance<<endl; } } //返回RANSAC過濾後的點對匹配資訊 return matches_ransac; }
匹配結果: