FLANN Introduction
The FLANN library is short for fast library for approximate nearest neighbors. It is currently the most complete (approximate) nearest neighbor open source library. It not only implements a series of search algorithms, but also includes a mechanism for Automatically Selecting the fastest algorithm.
FLANN: Index _ class
This type of template is the nearest neighbor index class, which is used to abstract the indexes of different types of Nearest Neighbor searches.
The following is the Declaration of The FLANN: Index _ class:
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;};
Constructor FLANN: 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.*/
The features parameter is a matrix containing the features used to build indexes. The Params parameter is a structure containing index parameters.
The quick search structure of the constructor instance is constructed based on the specific algorithm specified by the Params parameter. Params is referenced by the derived class of indexparams.
Where:
* Linearindexparams: The index corresponding to this structure performs linear, brute-force searches.
- Kdtreeindexparams: The index structure of this method is composed of a group of random KD trees (randomized KD-trees), which can be searched in parallel.
struct KDTreeIndexParams : public IndexParams{ KDTreeIndexParams( int trees = 4 );};//trees:The number of parallel kd-trees to use. Good values are in the range
- Kmeansindexparams: The index structure of this method is 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, which combines a random KD tree and a hierarchical K-means tree to construct an index.
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: This structure uses the multi-probe lsh method to create an index (Multi-probe lsh: Efficient indexing for High-dimen1_similarity search by Qin LV, William Joseph Son, 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: This structure automatically selects the Optimal Index type based on data to provide the best performance.
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: used to load the index structure stored on the hard disk.
struct SavedIndexParams : public IndexParams{ SavedIndexParams( std::string filename );};//filename:The filename in which the index was saved.
FLANN: Index _: knnsearch
Based on the given query data, the constructed index is used for K-Nearest Neighbor Search.
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
Perform radius-Based Nearest Neighbor Search Based on the given query data.
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
Store indexes into files.
void flann::Index_<T>::save(std::string filename)
FLANN: Index _: getindexparameters
Obtain the index parameters.
const IndexParams* flann::Index_<T>::getIndexParameters()
Use FLANN for feature point matching
Next we will provide a small official example program, using the flannbasedmatcher interface and the function FLANN for fast and efficient matching.
The main process of this Code is divided into the following parts:
- Extract key points using surf features
- Calculate the surf feature description
- Use FLANN matching to describe sub-vector matching
Keypoint matching method in opencv
Opencv provides two matching methods:
? Brute-force matcher (CV: bfmatcher)
? FLANN-based matcher (CV: flannbasedmatcher)
Brute-force matcher is to use the brute force method to find the closest descriptor of each descriptor in point set;
FLANN-based matcher uses a fast approximate Nearest Neighbor Search Algorithm.
To improve the detection speed, you can train a matcher before calling the matching function. You can use CV: flannbasedmatcher to optimize the training process and create an index tree for the descriptor, this operation will play a huge role in matching a large amount of data (for example, searching for matching images in a data set of hundreds of images ). Brute-force matcher does not operate in this process, but stores train descriptors in the memory.
Sample Code
#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;}
Lab results
References
FLANN project Homepage
FLANN manual PDF
Learning opencv -- SURF (feature points) & FLANN
Opencv documentation: Fast approximate Nearest Neighbor Search
Reprinted, please indicate the author Jason Ding and its source
GitHub blog home (http://jasonding1354.github.io /)
Csdn blog (http://blog.csdn.net/jasonding1354)
Home (http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)
[Computer Vision] the nearest neighbor open source library FLANN of opencv