FlannBasedMatcher(LshIndex) in the feature2d optimization for continuance additional...
authorippei ito <github@mysrv.link>
Fri, 13 Mar 2015 19:38:07 +0000 (04:38 +0900)
committerippei ito <github@mysrv.link>
Fri, 13 Mar 2015 19:38:07 +0000 (04:38 +0900)
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.

14 files changed:
modules/features2d/src/matchers.cpp
modules/flann/include/opencv2/flann/autotuned_index.h
modules/flann/include/opencv2/flann/composite_index.h
modules/flann/include/opencv2/flann/flann_base.hpp
modules/flann/include/opencv2/flann/hierarchical_clustering_index.h
modules/flann/include/opencv2/flann/kdtree_index.h
modules/flann/include/opencv2/flann/kdtree_single_index.h
modules/flann/include/opencv2/flann/kmeans_index.h
modules/flann/include/opencv2/flann/linear_index.h
modules/flann/include/opencv2/flann/lsh_index.h
modules/flann/include/opencv2/flann/lsh_table.h
modules/flann/include/opencv2/flann/miniflann.hpp
modules/flann/include/opencv2/flann/nn_index.h
modules/flann/src/miniflann.cpp

index 893ad77..f001ef4 100644 (file)
@@ -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);
+        }
     }
 }
 
index 2b9ca91..e82d053 100644 (file)
@@ -95,6 +95,13 @@ public:
     }
 
     /**
+     * Dummy implementation for other algorithms of addable indexes after that.
+     */
+    void addIndex(const Matrix<ElementType>& wholeData, const Matrix<ElementType>& additionalData)
+    {
+    }
+
+    /**
      *          Method responsible with building the index.
      */
     virtual void buildIndex()
index 527ca1a..9372007 100644 (file)
@@ -131,6 +131,13 @@ public:
     }
 
     /**
+     * Dummy implementation for other algorithms of addable indexes after that.
+     */
+    void addIndex(const Matrix<ElementType>& wholeData, const Matrix<ElementType>& additionalData)
+    {
+    }
+
+    /**
      * \brief Builds the index
      */
     void buildIndex()
index b5ba7d7..bb5b120 100644 (file)
@@ -125,6 +125,16 @@ public:
     }
 
     /**
+    * implementation for algorithms of addable indexes after that.
+    */
+    void addIndex(const Matrix<ElementType>& wholeData, const Matrix<ElementType>& additionalData)
+    {
+        if (!loaded_) {
+            nnIndex_->addIndex(wholeData, additionalData);
+        }
+    }
+
+    /**
      * Builds the index.
      */
     void buildIndex()
index 54cb8e5..dddd98a 100644 (file)
@@ -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<ElementType>& wholeData, const Matrix<ElementType>& additionalData)
+    {
+    }
+
     /**
      * Builds the index
      */
index dc0971c..8c0024a 100644 (file)
@@ -118,6 +118,13 @@ public:
     }
 
     /**
+     * Dummy implementation for other algorithms of addable indexes after that.
+     */
+    void addIndex(const Matrix<ElementType>& wholeData, const Matrix<ElementType>& additionalData)
+    {
+    }
+
+    /**
      * Builds the index
      */
     void buildIndex()
index 30488ad..2b507e1 100644 (file)
@@ -111,6 +111,13 @@ public:
     }
 
     /**
+     * Dummy implementation for other algorithms of addable indexes after that.
+     */
+    void addIndex(const Matrix<ElementType>& wholeData, const Matrix<ElementType>& additionalData)
+    {
+    }
+
+    /**
      * Builds the index
      */
     void buildIndex()
index 8bcb63d..f95e2fc 100644 (file)
@@ -363,6 +363,13 @@ public:
     }
 
     /**
+     * Dummy implementation for other algorithms of addable indexes after that.
+     */
+    void addIndex(const Matrix<ElementType>& wholeData, const Matrix<ElementType>& additionalData)
+    {
+    }
+
+    /**
      * Builds the index
      */
     void buildIndex()
index 5aa7a5c..f54e3de 100644 (file)
@@ -85,6 +85,13 @@ public:
         return 0;
     }
 
+    /**
+     * Dummy implementation for other algorithms of addable indexes after that.
+     */
+    void addIndex(const Matrix<ElementType>& wholeData, const Matrix<ElementType>& additionalData)
+    {
+    }
+
     void buildIndex()
     {
         /* nothing to do here for linear search */
index 23988d4..5d00bea 100644 (file)
@@ -105,6 +105,20 @@ public:
     LshIndex& operator=(const LshIndex&);
 
     /**
+    * Implementation for the LSH addable indexes after that.
+    */
+    void addIndex(const Matrix<ElementType>& wholeData, const Matrix<ElementType>& additionalData)
+    {
+        tables_.resize(table_number_);
+        for (unsigned int i = 0; i < table_number_; ++i) {
+            lsh::LshTable<ElementType>& table = tables_[i];
+            // Add the features to the table with indexed offset
+            table.add(wholeData.rows - additionalData.rows, additionalData);
+        }
+        dataset_ = wholeData;
+    }
+
+    /**
      * Builds the index
      */
     void buildIndex()
@@ -126,8 +140,8 @@ public:
             lsh::LshTable<ElementType>& table = tables_[i];
             table = lsh::LshTable<ElementType>(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_);
         }
     }
 
index 0defa52..bfc486d 100644 (file)
@@ -194,13 +194,13 @@ public:
     /** Add a set of features to the table
      * @param dataset the values to store
      */
-    void add(Matrix<ElementType> dataset)
+    void add(int indexed_ofst, Matrix<ElementType> 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();
     }
index ada3756..121f8d0 100644 (file)
@@ -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());
 
index d14e83a..4a874f5 100644 (file)
@@ -60,6 +60,11 @@ public:
     virtual void buildIndex() = 0;
 
     /**
+     * \brief implementation for algorithms of addable indexes after that.
+     */
+    virtual void addIndex(const Matrix<ElementType>& wholeData, const Matrix<ElementType>& additionalData) = 0;
+
+    /**
      * \brief Perform k-nearest neighbor search
      * \param[in] queries The query points for which to find the nearest neighbors
      * \param[out] indices The indices of the nearest neighbors found
index 3747102..a84f240 100644 (file)
@@ -308,7 +308,7 @@ SearchParams::SearchParams( int checks, float eps, bool sorted )
 
 
 template<typename Distance, typename IndexType> 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<ElementType>::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<ElementType> 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<flann_algorithm_t>(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<ElementType> wholedataset((ElementType*)wholedata.data, wholedata.rows, wholedata.cols);
+        ((IndexType*)index)->addIndex(wholedataset, dataset);
+    }
 }
 
 template<typename Distance> 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_<Distance, ::cvflann::Index<Distance> >(index, data, params, dist);
+    buildIndex_<Distance, ::cvflann::Index<Distance> >(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<flann_algorithm_t>(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<std::string>(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<float> >(index, data, params);
+        buildIndex< ::cvflann::L2<float> >(index, _wholedata.getMat(), data, params);
         break;
     case FLANN_DIST_L1:
-        buildIndex< ::cvflann::L1<float> >(index, data, params);
+        buildIndex< ::cvflann::L1<float> >(index, _wholedata.getMat(), data, params);
         break;
 #if MINIFLANN_SUPPORT_EXOTIC_DISTANCE_TYPES
     case FLANN_DIST_MAX:
-        buildIndex< ::cvflann::MaxDistance<float> >(index, data, params);
+        buildIndex< ::cvflann::MaxDistance<float> >(index, _wholedata.getMat(), data, params);
         break;
     case FLANN_DIST_HIST_INTERSECT:
-        buildIndex< ::cvflann::HistIntersectionDistance<float> >(index, data, params);
+        buildIndex< ::cvflann::HistIntersectionDistance<float> >(index, _wholedata.getMat(), data, params);
         break;
     case FLANN_DIST_HELLINGER:
-        buildIndex< ::cvflann::HellingerDistance<float> >(index, data, params);
+        buildIndex< ::cvflann::HellingerDistance<float> >(index, _wholedata.getMat(), data, params);
         break;
     case FLANN_DIST_CHI_SQUARE:
-        buildIndex< ::cvflann::ChiSquareDistance<float> >(index, data, params);
+        buildIndex< ::cvflann::ChiSquareDistance<float> >(index, _wholedata.getMat(), data, params);
         break;
     case FLANN_DIST_KL:
-        buildIndex< ::cvflann::KL_Divergence<float> >(index, data, params);
+        buildIndex< ::cvflann::KL_Divergence<float> >(index, _wholedata.getMat(), data, params);
         break;
 #endif
     default: