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: