1. 程式人生 > >Flann特徵點匹配簡述(Lowe's algorithm)

Flann特徵點匹配簡述(Lowe's algorithm)

/***好記性不如爛筆頭,記下來便於以後複習***/       

      特徵匹配的結果會得到兩個特徵集合的對應關係列表。第一組特徵集被稱為訓練集(train),第二組被稱為查詢集(query)。Flann 在呼叫匹配函式之前,為了提高匹配速度,訓練一個匹配器。訓練階段是為了優化cv::FlannBasedMatcher的效能。train類將會建立特徵集的索引樹。將 query image 的每一個特徵點和 train 匹配器進行匹配,找出最佳匹配;也就是從query image 的特徵中逐個去和訓練器做匹配,也就是說每一個query image 特徵點都會有一個最佳匹配,後期還需要驗證這匹配的正確性,可以通過設定截斷值來去除誤差大的匹配;

     去除了誤差大的匹配即可以使用 Lowe's策略進行匹配的再一次篩選;

      knnMatch()找每個query image特徵的K近鄰匹配,效率不夠高,幀率很低。

Lowe’s演算法:為了進一步篩選匹配點,來獲取優秀的匹配點,這就是所謂的“去粗取精”。一般會採用Lowe’s演算法來進一步獲取優秀匹配點。
   為了排除因為影象遮擋和背景混亂而產生的無匹配關係的關鍵點,SIFT的作者Lowe提出了比較最近鄰距離與次近鄰距離的SIFT匹配方式:取一幅影象中的一個SIFT關鍵點,並找出其與另一幅影象中歐式距離最近的前兩個關鍵點,在這兩個關鍵點中,如果最近的距離除以次近的距離得到的比率ratio少於某個閾值T,則接受這一對匹配點。因為對於錯誤匹配,由於特徵空間的高維性,相似的距離可能有大量其他的錯誤匹配,從而它的ratio值比較高。顯然降低這個比例閾值T,SIFT匹配點數目會減少,但更加穩定,反之亦然。
   Lowe推薦ratio的閾值為0.8,但作者對大量任意存在尺度、旋轉和亮度變化的兩幅圖片進行匹配,結果表明ratio取值在0. 4~0. 6 之間最佳,小於0. 4的很少有匹配點,大於0. 6的則存在大量錯誤匹配點,所以建議ratio的取值原則如下:

ratio=0. 4:對於準確度要求高的匹配;

ratio=0. 6:對於匹配點數目要求比較多的匹配;

ratio=0. 5:一般情況下。

Lowe's改進:可以反過來使用最近鄰比次近鄰,在匹配中可以作為置信度來使用,當滿足最近鄰比次近鄰大於某個值的時候,作為某個條件的判別  置信度;比如可以應用在雙目視覺立體匹配中的視差選擇與優化環節中(論文正在編寫中);

#include "highgui/highgui.hpp"    
#include "opencv2/nonfree/nonfree.hpp"    
#include "opencv2/legacy/legacy.hpp"   
#include <iostream>  

using namespace cv;
using namespace std;

int main()
{
    Mat image01 = imread("g2.jpg", 1);    
    Mat image02 = imread("g4.jpg", 1);    
    imshow("p2", image01);
    imshow("p1", image02);

    //灰度圖轉換  
    Mat image1, image2;
    cvtColor(image01, image1, CV_RGB2GRAY);
    cvtColor(image02, image2, CV_RGB2GRAY);


    //提取特徵點    
    SurfFeatureDetector surfDetector(2000); //海塞矩陣閾值,在這裡調整精度,值越大點越少,越精準 
    vector<KeyPoint> keyPoint1, keyPoint2;
    surfDetector.detect(image1, keyPoint1);
    surfDetector.detect(image2, keyPoint2);

    //特徵點描述,為下邊的特徵點匹配做準備    
    SurfDescriptorExtractor SurfDescriptor;
    Mat imageDesc1, imageDesc2;
    SurfDescriptor.compute(image1, keyPoint1, imageDesc1);
    SurfDescriptor.compute(image2, keyPoint2, imageDesc2);

    FlannBasedMatcher matcher;
    vector<vector<DMatch> > matchePoints;
    vector<DMatch> GoodMatchePoints;

    vector<Mat> train_desc(1, imageDesc1);
    matcher.add(train_desc);
    matcher.train();

    matcher.knnMatch(imageDesc2, matchePoints, 2);
    cout << "total match points: " << matchePoints.size() << endl;

    // Lowe's algorithm,獲取優秀匹配點
    for (int i = 0; i < matchePoints.size(); i++)
    {
        if (matchePoints[i][0].distance < 0.6 * matchePoints[i][1].distance)
        {
            GoodMatchePoints.push_back(matchePoints[i][0]);
        }
    }

    Mat first_match;
    drawMatches(image02, keyPoint2, image01, keyPoint1, GoodMatchePoints, first_match);
    imshow("first_match ", first_match);
    waitKey();
    return 0;
}

參考部落格:

https://blog.csdn.net/xxzxxzdlut/article/details/72930209

https://www.cnblogs.com/wyuzl/p/7816011.html