From cd42e38013e5ed80ecaf5874ff83c889725ce99f Mon Sep 17 00:00:00 2001 From: ippei ito Date: Sat, 14 Mar 2015 04:38:07 +0900 Subject: [PATCH] FlannBasedMatcher(LshIndex) in the feature2d optimization for continuance additional train() Current implementation of miniflann is releasing the trained index, and rebuilding the index from the beginning. But, some indexing algorithms like the LSH are able to add the indexing data after that. This branch is implementation of that optimization for LshIndex FlannBasedMatcher in the feature2d. --- modules/features2d/src/matchers.cpp | 14 ++++- .../include/opencv2/flann/autotuned_index.h | 7 +++ .../include/opencv2/flann/composite_index.h | 7 +++ .../include/opencv2/flann/flann_base.hpp | 10 ++++ .../flann/hierarchical_clustering_index.h | 8 +++ .../include/opencv2/flann/kdtree_index.h | 7 +++ .../opencv2/flann/kdtree_single_index.h | 7 +++ .../include/opencv2/flann/kmeans_index.h | 7 +++ .../include/opencv2/flann/linear_index.h | 7 +++ .../flann/include/opencv2/flann/lsh_index.h | 18 +++++- .../flann/include/opencv2/flann/lsh_table.h | 4 +- .../flann/include/opencv2/flann/miniflann.hpp | 3 +- .../flann/include/opencv2/flann/nn_index.h | 5 ++ modules/flann/src/miniflann.cpp | 55 ++++++++++++------- 14 files changed, 133 insertions(+), 26 deletions(-) diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index 893ad7743a..f001ef4882 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -531,10 +531,20 @@ void FlannBasedMatcher::clear() void FlannBasedMatcher::train() { - if( flannIndex.empty() || mergedDescriptors.size() < addedDescCount ) + int trained = mergedDescriptors.size(); + if (flannIndex.empty() || trained < addedDescCount) { mergedDescriptors.set( trainDescCollection ); - flannIndex = new flann::Index( mergedDescriptors.getDescriptors(), *indexParams ); + + // construct flannIndex class, if empty or Algorithm not equal FLANN_INDEX_LSH + if (flannIndex.empty() || flannIndex->getAlgorithm() != cvflann::FLANN_INDEX_LSH) + { + flannIndex = new flann::Index(mergedDescriptors.getDescriptors(), *indexParams); + } + else + { + flannIndex->build(mergedDescriptors.getDescriptors(), mergedDescriptors.getDescriptors().rowRange(trained, mergedDescriptors.size()), *indexParams, cvflann::FLANN_DIST_HAMMING); + } } } diff --git a/modules/flann/include/opencv2/flann/autotuned_index.h b/modules/flann/include/opencv2/flann/autotuned_index.h index 2b9ca91a42..e82d053568 100644 --- a/modules/flann/include/opencv2/flann/autotuned_index.h +++ b/modules/flann/include/opencv2/flann/autotuned_index.h @@ -94,6 +94,13 @@ public: } } + /** + * Dummy implementation for other algorithms of addable indexes after that. + */ + void addIndex(const Matrix& wholeData, const Matrix& additionalData) + { + } + /** * Method responsible with building the index. */ diff --git a/modules/flann/include/opencv2/flann/composite_index.h b/modules/flann/include/opencv2/flann/composite_index.h index 527ca1ad77..9372007467 100644 --- a/modules/flann/include/opencv2/flann/composite_index.h +++ b/modules/flann/include/opencv2/flann/composite_index.h @@ -130,6 +130,13 @@ public: return kmeans_index_->usedMemory() + kdtree_index_->usedMemory(); } + /** + * Dummy implementation for other algorithms of addable indexes after that. + */ + void addIndex(const Matrix& wholeData, const Matrix& additionalData) + { + } + /** * \brief Builds the index */ diff --git a/modules/flann/include/opencv2/flann/flann_base.hpp b/modules/flann/include/opencv2/flann/flann_base.hpp index b5ba7d79e2..bb5b120099 100644 --- a/modules/flann/include/opencv2/flann/flann_base.hpp +++ b/modules/flann/include/opencv2/flann/flann_base.hpp @@ -124,6 +124,16 @@ public: delete nnIndex_; } + /** + * implementation for algorithms of addable indexes after that. + */ + void addIndex(const Matrix& wholeData, const Matrix& additionalData) + { + if (!loaded_) { + nnIndex_->addIndex(wholeData, additionalData); + } + } + /** * Builds the index. */ diff --git a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h index 54cb8e55fc..dddd98ad52 100644 --- a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h +++ b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h @@ -378,6 +378,14 @@ public: return pool.usedMemory+pool.wastedMemory+memoryCounter; } + + /** + * Dummy implementation for other algorithms of addable indexes after that. + */ + void addIndex(const Matrix& wholeData, const Matrix& additionalData) + { + } + /** * Builds the index */ diff --git a/modules/flann/include/opencv2/flann/kdtree_index.h b/modules/flann/include/opencv2/flann/kdtree_index.h index dc0971c9ef..8c0024a4de 100644 --- a/modules/flann/include/opencv2/flann/kdtree_index.h +++ b/modules/flann/include/opencv2/flann/kdtree_index.h @@ -117,6 +117,13 @@ public: delete[] var_; } + /** + * Dummy implementation for other algorithms of addable indexes after that. + */ + void addIndex(const Matrix& wholeData, const Matrix& additionalData) + { + } + /** * Builds the index */ diff --git a/modules/flann/include/opencv2/flann/kdtree_single_index.h b/modules/flann/include/opencv2/flann/kdtree_single_index.h index 30488ad567..2b507e16b7 100644 --- a/modules/flann/include/opencv2/flann/kdtree_single_index.h +++ b/modules/flann/include/opencv2/flann/kdtree_single_index.h @@ -110,6 +110,13 @@ public: if (reorder_) delete[] data_.data; } + /** + * Dummy implementation for other algorithms of addable indexes after that. + */ + void addIndex(const Matrix& wholeData, const Matrix& additionalData) + { + } + /** * Builds the index */ diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index 8bcb63d72f..f95e2fcabd 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -362,6 +362,13 @@ public: return pool_.usedMemory+pool_.wastedMemory+memoryCounter_; } + /** + * Dummy implementation for other algorithms of addable indexes after that. + */ + void addIndex(const Matrix& wholeData, const Matrix& additionalData) + { + } + /** * Builds the index */ diff --git a/modules/flann/include/opencv2/flann/linear_index.h b/modules/flann/include/opencv2/flann/linear_index.h index 5aa7a5cfac..f54e3dee86 100644 --- a/modules/flann/include/opencv2/flann/linear_index.h +++ b/modules/flann/include/opencv2/flann/linear_index.h @@ -85,6 +85,13 @@ public: return 0; } + /** + * Dummy implementation for other algorithms of addable indexes after that. + */ + void addIndex(const Matrix& wholeData, const Matrix& additionalData) + { + } + void buildIndex() { /* nothing to do here for linear search */ diff --git a/modules/flann/include/opencv2/flann/lsh_index.h b/modules/flann/include/opencv2/flann/lsh_index.h index 23988d436a..5d00bea950 100644 --- a/modules/flann/include/opencv2/flann/lsh_index.h +++ b/modules/flann/include/opencv2/flann/lsh_index.h @@ -104,6 +104,20 @@ public: LshIndex(const LshIndex&); LshIndex& operator=(const LshIndex&); + /** + * Implementation for the LSH addable indexes after that. + */ + void addIndex(const Matrix& wholeData, const Matrix& additionalData) + { + tables_.resize(table_number_); + for (unsigned int i = 0; i < table_number_; ++i) { + lsh::LshTable& table = tables_[i]; + // Add the features to the table with indexed offset + table.add(wholeData.rows - additionalData.rows, additionalData); + } + dataset_ = wholeData; + } + /** * Builds the index */ @@ -126,8 +140,8 @@ public: lsh::LshTable& table = tables_[i]; table = lsh::LshTable(feature_size_, key_size_, indices); - // Add the features to the table - table.add(dataset_); + // Add the features to the table with offset 0 + table.add(0, dataset_); } } diff --git a/modules/flann/include/opencv2/flann/lsh_table.h b/modules/flann/include/opencv2/flann/lsh_table.h index 0defa52a77..bfc486dbc5 100644 --- a/modules/flann/include/opencv2/flann/lsh_table.h +++ b/modules/flann/include/opencv2/flann/lsh_table.h @@ -194,13 +194,13 @@ public: /** Add a set of features to the table * @param dataset the values to store */ - void add(Matrix dataset) + void add(int indexed_ofst, Matrix dataset) { #if USE_UNORDERED_MAP buckets_space_.rehash((buckets_space_.size() + dataset.rows) * 1.2); #endif // Add the features to the table - for (unsigned int i = 0; i < dataset.rows; ++i) add(i, dataset[i]); + for (unsigned int i = 0; i < dataset.rows; ++i) add(i + indexed_ofst, dataset[i]); // Now that the table is full, optimize it for speed/space optimize(); } diff --git a/modules/flann/include/opencv2/flann/miniflann.hpp b/modules/flann/include/opencv2/flann/miniflann.hpp index ada375691c..121f8d05c3 100644 --- a/modules/flann/include/opencv2/flann/miniflann.hpp +++ b/modules/flann/include/opencv2/flann/miniflann.hpp @@ -134,7 +134,8 @@ public: CV_WRAP Index(InputArray features, const IndexParams& params, cvflann::flann_distance_t distType=cvflann::FLANN_DIST_L2); virtual ~Index(); - CV_WRAP virtual void build(InputArray features, const IndexParams& params, cvflann::flann_distance_t distType=cvflann::FLANN_DIST_L2); + CV_WRAP virtual void build(InputArray wholefeatures, InputArray additionalfeatures, const IndexParams& params, cvflann::flann_distance_t distType=cvflann::FLANN_DIST_L2); + CV_WRAP virtual void knnSearch(InputArray query, OutputArray indices, OutputArray dists, int knn, const SearchParams& params=SearchParams()); diff --git a/modules/flann/include/opencv2/flann/nn_index.h b/modules/flann/include/opencv2/flann/nn_index.h index d14e83a92c..4a874f5867 100644 --- a/modules/flann/include/opencv2/flann/nn_index.h +++ b/modules/flann/include/opencv2/flann/nn_index.h @@ -59,6 +59,11 @@ public: */ virtual void buildIndex() = 0; + /** + * \brief implementation for algorithms of addable indexes after that. + */ + virtual void addIndex(const Matrix& wholeData, const Matrix& additionalData) = 0; + /** * \brief Perform k-nearest neighbor search * \param[in] queries The query points for which to find the nearest neighbors diff --git a/modules/flann/src/miniflann.cpp b/modules/flann/src/miniflann.cpp index 3747102728..a84f2408c9 100644 --- a/modules/flann/src/miniflann.cpp +++ b/modules/flann/src/miniflann.cpp @@ -308,7 +308,7 @@ SearchParams::SearchParams( int checks, float eps, bool sorted ) template void -buildIndex_(void*& index, const Mat& data, const IndexParams& params, const Distance& dist = Distance()) +buildIndex_(void*& index, const Mat& wholedata, const Mat& data, const IndexParams& params, const Distance& dist = Distance()) { typedef typename Distance::ElementType ElementType; if(DataType::type != data.type()) @@ -317,15 +317,25 @@ buildIndex_(void*& index, const Mat& data, const IndexParams& params, const Dist CV_Error(CV_StsBadArg, "Only continuous arrays are supported"); ::cvflann::Matrix dataset((ElementType*)data.data, data.rows, data.cols); - IndexType* _index = new IndexType(dataset, get_params(params), dist); - _index->buildIndex(); - index = _index; + + IndexType* _index = NULL; + if( !index || getParam(params, "algorithm", FLANN_INDEX_LINEAR) != FLANN_INDEX_LSH) // currently, additional index support is the lsh algorithm only. + { + _index = new IndexType(dataset, get_params(params), dist); + _index->buildIndex(); + index = _index; + } + else // build additional lsh index + { + ::cvflann::Matrix wholedataset((ElementType*)wholedata.data, wholedata.rows, wholedata.cols); + ((IndexType*)index)->addIndex(wholedataset, dataset); + } } template void -buildIndex(void*& index, const Mat& data, const IndexParams& params, const Distance& dist = Distance()) +buildIndex(void*& index, const Mat& wholedata, const Mat& data, const IndexParams& params, const Distance& dist = Distance()) { - buildIndex_ >(index, data, params, dist); + buildIndex_ >(index, wholedata, data, params, dist); } #if CV_NEON @@ -348,21 +358,28 @@ Index::Index(InputArray _data, const IndexParams& params, flann_distance_t _dist featureType = CV_32F; algo = FLANN_INDEX_LINEAR; distType = FLANN_DIST_L2; - build(_data, params, _distType); + build(_data, _data, params, _distType); } -void Index::build(InputArray _data, const IndexParams& params, flann_distance_t _distType) +void Index::build(InputArray &_wholedata, InputArray &_data, const IndexParams& params, flann_distance_t _distType) { - release(); algo = getParam(params, "algorithm", FLANN_INDEX_LINEAR); - if( algo == FLANN_INDEX_SAVED ) + + if (algo != FLANN_INDEX_LSH) // do not release if algo == FLANN_INDEX_LSH + { + release(); + } + if (algo == FLANN_INDEX_SAVED) { load(_data, getParam(params, "filename", std::string())); return; } Mat data = _data.getMat(); - index = 0; + if (algo != FLANN_INDEX_LSH) // do not clear if algo == FLANN_INDEX_LSH + { + index = 0; + } featureType = data.type(); distType = _distType; @@ -374,29 +391,29 @@ void Index::build(InputArray _data, const IndexParams& params, flann_distance_t switch( distType ) { case FLANN_DIST_HAMMING: - buildIndex< HammingDistance >(index, data, params); + buildIndex< HammingDistance >(index, _wholedata.getMat(), data, params); break; case FLANN_DIST_L2: - buildIndex< ::cvflann::L2 >(index, data, params); + buildIndex< ::cvflann::L2 >(index, _wholedata.getMat(), data, params); break; case FLANN_DIST_L1: - buildIndex< ::cvflann::L1 >(index, data, params); + buildIndex< ::cvflann::L1 >(index, _wholedata.getMat(), data, params); break; #if MINIFLANN_SUPPORT_EXOTIC_DISTANCE_TYPES case FLANN_DIST_MAX: - buildIndex< ::cvflann::MaxDistance >(index, data, params); + buildIndex< ::cvflann::MaxDistance >(index, _wholedata.getMat(), data, params); break; case FLANN_DIST_HIST_INTERSECT: - buildIndex< ::cvflann::HistIntersectionDistance >(index, data, params); + buildIndex< ::cvflann::HistIntersectionDistance >(index, _wholedata.getMat(), data, params); break; case FLANN_DIST_HELLINGER: - buildIndex< ::cvflann::HellingerDistance >(index, data, params); + buildIndex< ::cvflann::HellingerDistance >(index, _wholedata.getMat(), data, params); break; case FLANN_DIST_CHI_SQUARE: - buildIndex< ::cvflann::ChiSquareDistance >(index, data, params); + buildIndex< ::cvflann::ChiSquareDistance >(index, _wholedata.getMat(), data, params); break; case FLANN_DIST_KL: - buildIndex< ::cvflann::KL_Divergence >(index, data, params); + buildIndex< ::cvflann::KL_Divergence >(index, _wholedata.getMat(), data, params); break; #endif default: