FLANN庫全稱是Fast Library for Approximate Nearest Neighbors,它是目前最完整的(近似)最近鄰開源庫。不但實現了一系列查找算法,還包含了一種自動選取最快算法的機制,在一個度量空間X給定一組點P=p1,p2,…,pn,這些點必須通過以下方式進行預處理,給第一個新的查詢點q屬於X,快速在P中找到距離q最近的點,即最近鄰搜索問題。最近鄰搜索的問題是在很多應用領域是一個重大問題,如圖像識別、數據壓縮、模式識別和分類.在高維空間中解決這個問題似乎是一個非常難以執行任務,沒有算法明顯優於標准的蠻力搜索。因此越來越多的人把興趣點轉向執行近似最近鄰搜索的一類算法,這些方法在很多實際應用和大多數案例中被證明是足夠好的近似,比精確搜索算法快很大的數量級
庫的地址:www.cs.ubc.ca/research/flann/
很顯然在PCL 搜索最近鄰也是屬於高維度近鄰搜索,所以需要用到這樣的庫來尋找匹配的,比如我們如果想通過使用PCL點雲的數據來識別出物體到底是什么,那么很明顯是需要一個數據錄的,這個數據庫的訓練該怎么來實現呢?因為我對機器學習了解的比較少,我想通過機器學習的方法來識別是最好的,也是今后可以做的工作,目前來看,我認為的方法就是通過對大量的點雲進行訓練並提取他們的特征點,比如VFH,然后把大量點雲訓練存儲成八叉樹,以便於很好的搜索和匹配,而且在PCL 中使用八叉樹是很常見的一種存儲結構,也是方便搜索的,然后通過計算我們想要識別物體的點雲 的VFH,通過FLANN算法尋找到最接近的,這就是整體的思路
主要流程
- 使用SURF,SIFT特征提取關鍵點(在PCL中同樣適用)
- 計算特征描述子(比如VFH)
- 使用FLANN匹配器進行描述子向量匹配
那么有興趣可以去仔細看看論文啊,我等渣渣真是多年以來對論文沒什么感覺
介紹幾種FLANN庫中的API接口,如何去使用它,然后通過具體的實例去實現這樣一個匹配
(1)flann::Index這是FLANN最近鄰指數類。該類用於抽象的不同類型的最近鄰搜索索引。距離函數類模板用於計算兩個特征空間之間的距離。
namespace flann { template<typename Distance> class Index { typedef typename Distance::ElementType ElementType; typedef typename Distance::ResultType DistanceType; public: Index(const IndexParams& params, Distance distance = Distance() ); Index(const Matrix<ElementType>& points, const IndexParams& params, Distance distance = Distance() ); ~Index(); void buildIndex(); void buildIndex(const Matrix<ElementType>& points); void addPoints(const Matrix<ElementType>& points, float rebuild_threshold = 2); void removePoint(size_t point_id); ElementType* getPoint(size_t point_id); int knnSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, size_t knn, const SearchParams& params); int knnSearch(const Matrix<ElementType>& queries, std::vector< std::vector<int> >& indices, std::vector<std::vector<DistanceType> >& dists, size_t knn, const SearchParams& params); int radiusSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, float radius, const SearchParams& params); int radiusSearch(const Matrix<ElementType>& queries, std::vector< std::vector<int> >& indices, std::vector<std::vector<DistanceType> >& dists, float radius, const SearchParams& params); void save(std::string filename); int veclen() const; int size() const; IndexParams getParameters() const; flann_algorithm_t getType() const; }; }
(2)flann::Index::knnSearch
對一組點查詢點,該方法執行K最近鄰搜索。該方法有兩個實現,一個攜帶預開辟空間的flann::Matrix對象接收返回的找到鄰居的索引號和到其距離;另一個是攜帶std::vector<std::vector>根據需要自動重新調整大小。
參數解釋:
queries: 承載查詢點的矩陣,矩陣大小是:查詢點數*緯數;
indices: 將承載所有被找到的K最近鄰的索引號( 預開辟的大小應該至少是查詢點數*knn);
dists: 將承載到所有被找到的K最近鄰的距離只(預開辟大小應該至少是查詢點數*knn);
knn: 要找的最近鄰的個數;
params: 搜索參數。承載搜索時要使用的參數的結構體,結構體類型是SearchParameters。
int Index::knnSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, size_t knn, const SearchParams& params); int Index::knnSearch(const Matrix<ElementType>& queries, std::vector< std::vector<int> >& indices, std::vector<std::vector<DistanceType> >& dists, size_t knn, const SearchParams& params);
在這里就不再一一翻譯了
/** Sets the log level used for all flann functions (unless specified in FLANNParameters for each call Params: level = verbosity level */ FLANN_EXPORT void flann_log_verbosity(int level);
設置FLANN距離的類型
/** * Sets the distance type to use throughout FLANN. * If distance type specified is MINKOWSKI, the second argument * specifies which order the minkowski distance should have. */ FLANN_EXPORT void flann_set_distance_type(enum flann_distance_t distance_type, int order);
建立和返回索引的函數
/** Builds and returns an index. It uses autotuning if the target_precision field of index_params is between 0 and 1, or the parameters specified if it's -1. Params: dataset = pointer to a data set stored in row major order rows = number of rows (features) in the dataset cols = number of columns in the dataset (feature dimensionality) speedup = speedup over linear search, estimated if using autotuning, output parameter index_params = index related parameters flann_params = generic flann parameters Returns: the newly created index or a number <0 for error */ FLANN_EXPORT flann_index_t flann_build_index(float* dataset, int rows, int cols, float* speedup, struct FLANNParameters* flann_params);
保存索引到本地磁盤(僅僅是索引被保存)
/** * Saves the index to a file. Only the index is saved into the file, the dataset corresponding to the index is not saved. * * @param index_id The index that should be saved * @param filename The filename the index should be saved to 文件名 * @return Returns 0 on success, negative value on error. 返回0則保存成功 */ FLANN_EXPORT int flann_save_index(flann_index_t index_id, char* filename);
從磁盤中載入索引文件
/** * Loads an index from a file. * * @param filename File to load the index from. * @param dataset The dataset corresponding to the index. * @param rows Dataset tors * @param cols Dataset columns * @return */ FLANN_EXPORT flann_index_t flann_load_index(char* filename, float* dataset, int rows, int cols);
建立一個索引或者說指定一個索引來尋找最近鄰域
/** Builds an index and uses it to find nearest neighbors. Params: dataset = pointer to a data set stored in row major order rows = number of rows (features) in the dataset cols = number of columns in the dataset (feature dimensionality) testset = pointer to a query set stored in row major order trows = number of rows (features) in the query dataset (same dimensionality as features in the dataset) indices = pointer to matrix for the indices of the nearest neighbors of the testset features in the dataset (must have trows number of rows and nn number of columns) nn = how many nearest neighbors to return flann_params = generic flann parameters Returns: zero or -1 for error */ FLANN_EXPORT int flann_find_nearest_neighbors(float* dataset, int rows, int cols, float* testset, int trows, int* indices, float* dists, int nn, struct FLANNParameters* flann_params);
對提供的索引來尋找最近鄰
/** Searches for nearest neighbors using the index provided Params: index_id = the index (constructed previously using flann_build_index). testset = pointer to a query set stored in row major order trows = number of rows (features) in the query dataset (same dimensionality as features in the dataset) indices = pointer to matrix for the indices of the nearest neighbors of the testset features in the dataset (must have trows number of rows and nn number of columns) dists = pointer to matrix for the distances of the nearest neighbors of the testset features in the dataset (must have trows number of rows and 1 column) nn = how many nearest neighbors to return flann_params = generic flann parameters Returns: zero or a number <0 for error */ FLANN_EXPORT int flann_find_nearest_neighbors_index(flann_index_t index_id, float* testset, int trows, int* indices, float* dists, int nn, struct FLANNParameters* flann_params);
半徑搜索的方法在已經建立的索引文件中尋找
/** * Performs an radius search using an already constructed index. * * In case of radius search, instead of always returning a predetermined * number of nearest neighbours (for example the 10 nearest neighbours), the * search will return all the neighbours found within a search radius * of the query point. * * The check parameter in the FLANNParameters below sets the level of approximation * for the search by only visiting "checks" number of features in the index * (the same way as for the KNN search). A lower value for checks will give * a higher search speedup at the cost of potentially not returning all the * neighbours in the specified radius. */ FLANN_EXPORT int flann_radius_search(flann_index_t index_ptr, /* the index */ float* query, /* query point */ int* indices, /* array for storing the indices found (will be modified) */ float* dists, /* similar, but for storing distances */ int max_nn, /* size of arrays indices and dists */ float radius, /* search radius (squared radius for euclidian metric) */ struct FLANNParameters* flann_params);
釋放內存
/** Deletes an index and releases the memory used by it. Params: index_id = the index (constructed previously using flann_build_index). flann_params = generic flann parameters Returns: zero or a number <0 for error */ FLANN_EXPORT int flann_free_index(flann_index_t index_id, struct FLANNParameters* flann_params);
利用特征聚類
/** Clusters the features in the dataset using a hierarchical kmeans clustering approach. This is significantly faster than using a flat kmeans clustering for a large number of clusters. Params: dataset = pointer to a data set stored in row major order rows = number of rows (features) in the dataset cols = number of columns in the dataset (feature dimensionality) clusters = number of cluster to compute result = memory buffer where the output cluster centers are storred index_params = used to specify the kmeans tree parameters (branching factor, max number of iterations to use) flann_params = generic flann parameters Returns: number of clusters computed or a number <0 for error. This number can be different than the number of clusters requested, due to the way hierarchical clusters are computed. The number of clusters returned will be the highest number of the form (branch_size-1)*K+1 smaller than the number of clusters requested. */ FLANN_EXPORT int flann_compute_cluster_centers(float* dataset, int rows, int cols, int clusters, float* result, struct FLANNParameters* flann_params);
基本的介紹,可以查看相應的手冊
#include <flann/flann.h>
#include <flann/io/hdf5.h>
其中還涉及到另外一種文件的數據結構的使用,一般都會包含兩個頭文件,第一個頭文件是關於FLANN算法實現的聲明的函數集,第二個頭文件是關於數據結構的一種存儲的方式,hdf5是用於存儲和分發科學數據的一種自我描述、多對象文件格式,HDF 被設計為:
- 自述性:對於一個HDF 文件里的每一個數據對象,有關於該數據的綜合信息(元數據)。在沒有任何外部信息的情況下,HDF 允許應用程序解釋HDF文件的結構和內容。
- 通用性:許多數據類型都可以被嵌入在一個HDF文件里。例如,通過使用合適的HDF 數據結構,符號、數字和圖形數據可以同時存儲在一個HDF 文件里。
- 靈活性:HDF允許用戶把相關的數據對象組合在一起,放到一個分層結構中,向數據對象添加描述和標簽。它還允許用戶把科學數據放到多個HDF 文件里。
- 擴展性:HDF極易容納將來新增加的數據模式,容易與其他標准格式兼容。
- 跨平台性:HDF 是一個與平台無關的文件格式。HDF 文件無需任何轉換就可以在不同平台上使用
最好的辦法是把HDF 文件看成為一本有表格內容的多章節書。HDF 文件是“數據書”,其中每章都包含一個不同類型的數據內容。正如書籍用一個目錄表列出它的章節一樣,HDF文件用“data index”(數據索引)列出其數據內容
HDF 文件結構包括一個file id(文件號)、至少一個 data descriptor (數據描述符)、沒有或多個 data element(數據內容)數據內容。
以上內容是涉及到關於對PCL中物體的識別的基礎知識。
有興趣者關注微信公眾號,更歡迎大家投稿分享,只要是關於點雲的都可以分享