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我們最終可以知道序列中哪些是內點,哪些是外點。
匹配效果示例:
目標檢測示例圖
后期我會將完整代碼上傳github,歡迎關注,github地址:https://github.com/JunJieDing666