SURF匹配點單應性提純
阿新 • • 發佈:2018-12-18
1、SURF簡介
Speeded Up Robust Features(SURF,加速穩健特徵),是一種穩健的區域性特徵點檢測和描述演算法。最初由Herbert Bay發表在2006年的歐洲計算機視覺國際會議(Europen Conference on Computer Vision,ECCV)上,並在2008年正式發表在Computer Vision and Image Understanding期刊上。 Surf是對David Lowe在1999年提出的Sift演算法的改進,提升了演算法的執行效率,為演算法在實時計算機視覺系統中應用提供了可能。與Sift演算法一樣,Surf演算法的基本路程可以分為三大部分:區域性特徵點的提取、特徵點的描述、特徵點的匹配。
2、SURF匹配程式碼
// 讀入你所要匹配的圖片 Mat image1 = imread("D:/test2-1.jpg", 0); Mat image2 = imread("D:/test2-2.jpg", 0); if (!image1.data || !image2.data) return 0; // 宣告兩個vector變數存放兩張圖的關鍵點 vector<KeyPoint> keypoints1; vector<KeyPoint> keypoints2; // 宣告一個SURF特徵檢測器 Ptr<SurfFeatureDetector> surf = SurfFeatureDetector::create(3000); // 檢測 SURF 特徵關鍵點 surf->detect(image1, keypoints1); surf->detect(image2, keypoints2); if (keypoints1.size() == 0 || keypoints2.size() == 0) { return -1; } else { cout << "Number of SURF points (1): " << keypoints1.size() << endl; cout << "Number of SURF points (2): " << keypoints2.size() << endl; } // 宣告一個SURF特徵點描述子抽取器 Ptr<SURF> surfDesc = SURF::create(); // 抽取特徵點描述子(以向量矩陣形式存入Mat中,用於匹配兩特徵點是否相似) Mat descriptors1, descriptors2; surfDesc->compute(image1, keypoints1, descriptors1); surfDesc->compute(image2, keypoints2, descriptors2); // 宣告一個匹配器 Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce"); // 匹配兩圖描述子(也即看特徵向量像不像) vector<cv::DMatch> matches; matcher->match(descriptors1, descriptors2, matches); // 採用RANSAC計算單應矩陣,然後通過單應矩陣提純得到好的特徵點 vector<Point2f> object; vector<Point2f> scene; for (size_t i = 0; i < matches.size(); i++) { //從好的匹配中獲取關鍵點: 匹配關係是兩組關鍵點間具有的一一對應關係,可以根據此匹配關係獲得關鍵點的索引 //這裡的goodMatches[i].queryIdx和goodMatches[i].trainIdx是匹配中一對關鍵點的索引 object.push_back(keypoints1[matches[i].queryIdx].pt); scene.push_back(keypoints2[matches[i].trainIdx].pt); } Mat H; float reprojectionThreshold = 3; vector<DMatch> inliers; vector<unsigned char> inliersMask(object.size()); H = findHomography(object, scene, CV_RANSAC, reprojectionThreshold, inliersMask); for (size_t i = 0; i < inliersMask.size(); i++) { if (inliersMask[i]) inliers.push_back(matches[i]); } matches.swap(inliers);
其中,findHomography()我們單獨拿出來解析,這個函式的引數中:
- object和scene是好點在兩張圖中分別的座標集合,且他們是一一對應的,其中既有正確的匹配,也有錯誤的匹配,正確的稱為內點,錯誤的稱為外點,RANSAC方法就是從這些包含錯誤匹配的資料中,分離出正確的匹配,並且求得單應矩陣(H就是我們要求的單應矩陣)。
- reprojThreshold為閾值,當某一個匹配小於閾值時,則被認為是一個內點。
- inliersMask即為掩膜,它的長度和object、scene一樣長,當一個object和scene中的點為內點時,inliersMask的相應位置標記為1,反之為0,說白了,通過inliersMask我們最終可以知道序列中哪些是內點,哪些是外點。
匹配效果示例:
目標檢測示例圖