【電腦視覺】OpenCV的最近鄰開源庫FLANN

來源:互聯網
上載者:User

標籤:電腦視覺

FLANN介紹

FLANN庫全稱是Fast Library for Approximate Nearest Neighbors,它是目前最完整的(近似)最近鄰開源庫。不但實現了一系列尋找演算法,還包含了一種自動選取最快演算法的機制。

flann::Index_類

該類模板是最近鄰索引類,該類用於抽象不同類型的最近鄰搜尋的索引。
以下是flann::Index_類的聲明:

template <typename T>class#ifndef _MSC_VER FLANN_DEPRECATED#endif Index_ {public:        typedef typename L2<T>::ElementType ElementType;        typedef typename L2<T>::ResultType DistanceType;    Index_(const Mat& features, const ::cvflann::IndexParams& params);    ~Index_();    void knnSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, int knn, const ::cvflann::SearchParams& params);    void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params);    int radiusSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, DistanceType radius, const ::cvflann::SearchParams& params);    int radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& params);    void save(std::string filename)        {            if (nnIndex_L1) nnIndex_L1->save(filename);            if (nnIndex_L2) nnIndex_L2->save(filename);        }    int veclen() const    {            if (nnIndex_L1) return nnIndex_L1->veclen();            if (nnIndex_L2) return nnIndex_L2->veclen();        }    int size() const    {            if (nnIndex_L1) return nnIndex_L1->size();            if (nnIndex_L2) return nnIndex_L2->size();        }        ::cvflann::IndexParams getParameters()        {            if (nnIndex_L1) return nnIndex_L1->getParameters();            if (nnIndex_L2) return nnIndex_L2->getParameters();        }        FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters()        {            if (nnIndex_L1) return nnIndex_L1->getIndexParameters();            if (nnIndex_L2) return nnIndex_L2->getIndexParameters();        }private:        // providing backwards compatibility for L2 and L1 distances (most common)        ::cvflann::Index< L2<ElementType> >* nnIndex_L2;        ::cvflann::Index< L1<ElementType> >* nnIndex_L1;};
建構函式flann::Index_::Index_
flann::Index_<T>::Index_(const Mat& features, const IndexParams& params)/*Parameters: features – Matrix of containing the features(points) to index. The size of the matrix is num_features x feature_dimensionality and the data type of the elements in the matrix must coincide with the type of the index.params – Structure containing the index parameters. The type of index that will be constructed depends on the type of this parameter. See the description.*/

參數features,是包含用於構建索引的特徵的矩陣;參數params,是包含索引參數的結構。
該建構函式所執行個體的快速搜尋結構是根據參數params所指定的特定演算法來構建的。params是由IndexParams的衍生類別的引用。
其中:
* LinearIndexParams,該結構對應的索引進行線性、暴力(brute-force)的搜尋。

  • KDTreeIndexParams,該方法對應的索引結構由一組隨機kd樹構成(randomized kd-trees),它可以平行地進行搜尋。
struct KDTreeIndexParams : public IndexParams{    KDTreeIndexParams( int trees = 4 );};//trees:The number of parallel kd-trees to use. Good values are in the range
  • KMeansIndexParams,該方法對應的索引結構是一個層次k均值樹(a hierarchical k-means tree)。
struct KMeansIndexParams : public IndexParams{    KMeansIndexParams(        int branching = 32,        int iterations = 11,        flann_centers_init_t centers_init = CENTERS_RANDOM,        float cb_index = 0.2 );};
  • CompositeIndexParams,該結構結合隨機kd樹和層次k均值樹來構建索引。
struct CompositeIndexParams : public IndexParams{    CompositeIndexParams(        int trees = 4,        int branching = 32,        int iterations = 11,        flann_centers_init_t centers_init = CENTERS_RANDOM,        float cb_index = 0.2 );};
  • LshIndexParams,該結構使用multi-probe LSH方法建立索引(Multi-Probe LSH: Efficient Indexing for High-Dimensional Similarity Search by Qin Lv, William Josephson, Zhe Wang, Moses Charikar, Kai Li., Proceedings of the 33rd International Conference on Very Large Data Bases (VLDB). Vienna, Austria. September 2007)。
struct LshIndexParams : public IndexParams{    LshIndexParams(        unsigned int table_number,        unsigned int key_size,        unsigned int multi_probe_level );};
  • AutotunedIndexParams,該結構是根據資料自動選取最優的索引類型來提供最好的效能。
struct AutotunedIndexParams : public IndexParams{    AutotunedIndexParams(        float target_precision = 0.9,        float build_weight = 0.01,        float memory_weight = 0,        float sample_fraction = 0.1 );};
  • SavedIndexParams,該結構用於載入存放在硬碟的索引結構。
struct SavedIndexParams : public IndexParams{    SavedIndexParams( std::string filename );};//filename:The filename in which the index was saved.
flann::Index_::knnSearch

根據給定的查詢資料,利用構建的索引來執行k近鄰搜尋。

void flann::Index_<T>::knnSearch(const vector<T>& query, vector<int>& indices, vector<float>& dists, int knn, const SearchParams& params)void flann::Index_<T>::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const SearchParams& params)
flann::Index_::radiusSearch

根據給定的查詢資料,執行基於半徑的最近鄰搜尋。

int flann::Index_<T>::radiusSearch(const vector<T>& query, vector<int>& indices, vector<float>& dists, float radius, const SearchParams& params)int flann::Index_<T>::radiusSearch(const Mat& query, Mat& indices, Mat& dists, float radius, const SearchParams& params)
flann::Index_::save

將索引存成檔案。

void flann::Index_<T>::save(std::string filename)
flann::Index_::getIndexParameters

得到索引參數。

const IndexParams* flann::Index_<T>::getIndexParameters()
利用FLANN進行特徵點匹配

接下來給出一段小的官方樣本程式,使用 FlannBasedMatcher 介面以及函數 FLANN 實現快速高效匹配。
這段代碼的主要流程分為以下幾部分:

  1. 使用SURF特徵提取關鍵點
  2. 計算SURF特徵描述子
  3. 使用FLANN匹配器進行描述子向量匹配
OpenCV中KeyPoint Matching的方法

OpenCV提供了 兩種Matching方式 :
? Brute-force matcher (cv::BFMatcher)
? Flann-based matcher (cv::FlannBasedMatcher)
Brute-force matcher就是用暴力方法找到點集一中每個descriptor在點集二中距離最近的 descriptor;
Flann-based matcher 使用快速近似最近鄰搜尋演算法尋找。
為了提高檢測速度,你可以調用matching函數前,先訓練一個matcher。訓練過程可以首先使用cv:: FlannBasedMatcher來最佳化,為 descriptor建立索引樹,這種操作將在匹配大量資料時發揮巨大作用(比如在上百幅映像的資料集中尋找匹配映像)。而 Brute-force matcher在這個過程並不進行操作,它只是將train descriptors儲存在記憶體中。

程式碼範例
#include <stdio.h>#include <iostream>#include "opencv2/core/core.hpp"#include "opencv2/highgui/highgui.hpp"#include "opencv2/nonfree/features2d.hpp"using namespace cv;/** @function main */int main( int argc, char** argv ){    Mat img_1 = imread("box.png", CV_LOAD_IMAGE_GRAYSCALE );    Mat img_2 = imread("box_in_scene.png", CV_LOAD_IMAGE_GRAYSCALE );    if( !img_1.data || !img_2.data )    { std::cout<< " --(!) Error reading images " << std::endl; return -1; }    //-- Step 1: Detect the keypoints using SURF Detector    int minHessian = 400;    SurfFeatureDetector detector( minHessian );    std::vector<KeyPoint> keypoints_1, keypoints_2;    detector.detect( img_1, keypoints_1 );    detector.detect( img_2, keypoints_2 );    //-- Step 2: Calculate descriptors (feature vectors)    SurfDescriptorExtractor extractor;    Mat descriptors_1, descriptors_2;    extractor.compute( img_1, keypoints_1, descriptors_1 );    extractor.compute( img_2, keypoints_2, descriptors_2 );    //-- Step 3: Matching descriptor vectors using FLANN matcher    FlannBasedMatcher matcher;    std::vector< DMatch > matches;    matcher.match( descriptors_1, descriptors_2, matches );    double max_dist = 0; double min_dist = 100;    //-- Quick calculation of max and min distances between keypoints    for( int i = 0; i < descriptors_1.rows; i++ )    { double dist = matches[i].distance;    if( dist < min_dist ) min_dist = dist;    if( dist > max_dist ) max_dist = dist;    }    printf("-- Max dist : %f \n", max_dist );    printf("-- Min dist : %f \n", min_dist );    //-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist )    //-- PS.- radiusMatch can also be used here.    std::vector< DMatch > good_matches;    for( int i = 0; i < descriptors_1.rows; i++ )    { if( matches[i].distance < 2*min_dist )    { good_matches.push_back( matches[i]); }    }    //-- Draw only "good" matches    Mat img_matches;    drawMatches( img_1, keypoints_1, img_2, keypoints_2,        good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),        vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );    //-- Show detected matches    imshow( "Good Matches", img_matches );    for( int i = 0; i < good_matches.size(); i++ )    { printf( "-- Good Match [%d] Keypoint 1: %d  -- Keypoint 2: %d  \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); }    waitKey(0);    return 0;}
實驗結果


參考資料

flann項目首頁
flann手冊 pdf
學習OpenCV——Surf(特徵點篇)&flann
OpenCV documentation:Fast Approximate Nearest Neighbor Search

轉載請註明作者Jason Ding及其出處
Github部落客頁(http://jasonding1354.github.io/)
CSDN部落格(http://blog.csdn.net/jasonding1354)
簡書首頁(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)

【電腦視覺】OpenCV的最近鄰開源庫FLANN

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.