github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/opencv4/include/opencv2/flann/kdtree_index.h (about)

     1  /***********************************************************************
     2   * Software License Agreement (BSD License)
     3   *
     4   * Copyright 2008-2009  Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
     5   * Copyright 2008-2009  David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
     6   *
     7   * THE BSD LICENSE
     8   *
     9   * Redistribution and use in source and binary forms, with or without
    10   * modification, are permitted provided that the following conditions
    11   * are met:
    12   *
    13   * 1. Redistributions of source code must retain the above copyright
    14   *    notice, this list of conditions and the following disclaimer.
    15   * 2. Redistributions in binary form must reproduce the above copyright
    16   *    notice, this list of conditions and the following disclaimer in the
    17   *    documentation and/or other materials provided with the distribution.
    18   *
    19   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    20   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    21   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    22   * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    23   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    24   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    25   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    26   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    27   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    28   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    29   *************************************************************************/
    30  
    31  #ifndef OPENCV_FLANN_KDTREE_INDEX_H_
    32  #define OPENCV_FLANN_KDTREE_INDEX_H_
    33  
    34  //! @cond IGNORED
    35  
    36  #include <algorithm>
    37  #include <map>
    38  #include <cstring>
    39  
    40  #include "nn_index.h"
    41  #include "dynamic_bitset.h"
    42  #include "matrix.h"
    43  #include "result_set.h"
    44  #include "heap.h"
    45  #include "allocator.h"
    46  #include "random.h"
    47  #include "saving.h"
    48  
    49  
    50  namespace cvflann
    51  {
    52  
    53  struct KDTreeIndexParams : public IndexParams
    54  {
    55      KDTreeIndexParams(int trees = 4)
    56      {
    57          (*this)["algorithm"] = FLANN_INDEX_KDTREE;
    58          (*this)["trees"] = trees;
    59      }
    60  };
    61  
    62  
    63  /**
    64   * Randomized kd-tree index
    65   *
    66   * Contains the k-d trees and other information for indexing a set of points
    67   * for nearest-neighbor matching.
    68   */
    69  template <typename Distance>
    70  class KDTreeIndex : public NNIndex<Distance>
    71  {
    72  public:
    73      typedef typename Distance::ElementType ElementType;
    74      typedef typename Distance::ResultType DistanceType;
    75  
    76  
    77      /**
    78       * KDTree constructor
    79       *
    80       * Params:
    81       *          inputData = dataset with the input features
    82       *          params = parameters passed to the kdtree algorithm
    83       */
    84      KDTreeIndex(const Matrix<ElementType>& inputData, const IndexParams& params = KDTreeIndexParams(),
    85                  Distance d = Distance() ) :
    86          dataset_(inputData), index_params_(params), distance_(d)
    87      {
    88          size_ = dataset_.rows;
    89          veclen_ = dataset_.cols;
    90  
    91          trees_ = get_param(index_params_,"trees",4);
    92          tree_roots_ = new NodePtr[trees_];
    93  
    94          // Create a permutable array of indices to the input vectors.
    95          vind_.resize(size_);
    96          for (size_t i = 0; i < size_; ++i) {
    97              vind_[i] = int(i);
    98          }
    99  
   100          mean_ = new DistanceType[veclen_];
   101          var_ = new DistanceType[veclen_];
   102      }
   103  
   104  
   105      KDTreeIndex(const KDTreeIndex&);
   106      KDTreeIndex& operator=(const KDTreeIndex&);
   107  
   108      /**
   109       * Standard destructor
   110       */
   111      ~KDTreeIndex()
   112      {
   113          if (tree_roots_!=NULL) {
   114              delete[] tree_roots_;
   115          }
   116          delete[] mean_;
   117          delete[] var_;
   118      }
   119  
   120      /**
   121       * Builds the index
   122       */
   123      void buildIndex() CV_OVERRIDE
   124      {
   125          /* Construct the randomized trees. */
   126          for (int i = 0; i < trees_; i++) {
   127              /* Randomize the order of vectors to allow for unbiased sampling. */
   128  #ifndef OPENCV_FLANN_USE_STD_RAND
   129              cv::randShuffle(vind_);
   130  #else
   131              std::random_shuffle(vind_.begin(), vind_.end());
   132  #endif
   133  
   134              tree_roots_[i] = divideTree(&vind_[0], int(size_) );
   135          }
   136      }
   137  
   138  
   139      flann_algorithm_t getType() const CV_OVERRIDE
   140      {
   141          return FLANN_INDEX_KDTREE;
   142      }
   143  
   144  
   145      void saveIndex(FILE* stream) CV_OVERRIDE
   146      {
   147          save_value(stream, trees_);
   148          for (int i=0; i<trees_; ++i) {
   149              save_tree(stream, tree_roots_[i]);
   150          }
   151      }
   152  
   153  
   154  
   155      void loadIndex(FILE* stream) CV_OVERRIDE
   156      {
   157          load_value(stream, trees_);
   158          if (tree_roots_!=NULL) {
   159              delete[] tree_roots_;
   160          }
   161          tree_roots_ = new NodePtr[trees_];
   162          for (int i=0; i<trees_; ++i) {
   163              load_tree(stream,tree_roots_[i]);
   164          }
   165  
   166          index_params_["algorithm"] = getType();
   167          index_params_["trees"] = tree_roots_;
   168      }
   169  
   170      /**
   171       *  Returns size of index.
   172       */
   173      size_t size() const CV_OVERRIDE
   174      {
   175          return size_;
   176      }
   177  
   178      /**
   179       * Returns the length of an index feature.
   180       */
   181      size_t veclen() const CV_OVERRIDE
   182      {
   183          return veclen_;
   184      }
   185  
   186      /**
   187       * Computes the inde memory usage
   188       * Returns: memory used by the index
   189       */
   190      int usedMemory() const CV_OVERRIDE
   191      {
   192          return int(pool_.usedMemory+pool_.wastedMemory+dataset_.rows*sizeof(int));  // pool memory and vind array memory
   193      }
   194  
   195      /**
   196       * Find set of nearest neighbors to vec. Their indices are stored inside
   197       * the result object.
   198       *
   199       * Params:
   200       *     result = the result object in which the indices of the nearest-neighbors are stored
   201       *     vec = the vector for which to search the nearest neighbors
   202       *     maxCheck = the maximum number of restarts (in a best-bin-first manner)
   203       */
   204      void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams) CV_OVERRIDE
   205      {
   206          const int maxChecks = get_param(searchParams,"checks", 32);
   207          const float epsError = 1+get_param(searchParams,"eps",0.0f);
   208          const bool explore_all_trees = get_param(searchParams,"explore_all_trees",false);
   209  
   210          if (maxChecks==FLANN_CHECKS_UNLIMITED) {
   211              getExactNeighbors(result, vec, epsError);
   212          }
   213          else {
   214              getNeighbors(result, vec, maxChecks, epsError, explore_all_trees);
   215          }
   216      }
   217  
   218      IndexParams getParameters() const CV_OVERRIDE
   219      {
   220          return index_params_;
   221      }
   222  
   223  private:
   224  
   225  
   226      /*--------------------- Internal Data Structures --------------------------*/
   227      struct Node
   228      {
   229          /**
   230           * Dimension used for subdivision.
   231           */
   232          int divfeat;
   233          /**
   234           * The values used for subdivision.
   235           */
   236          DistanceType divval;
   237          /**
   238           * The child nodes.
   239           */
   240          Node* child1, * child2;
   241      };
   242      typedef Node* NodePtr;
   243      typedef BranchStruct<NodePtr, DistanceType> BranchSt;
   244      typedef BranchSt* Branch;
   245  
   246  
   247  
   248      void save_tree(FILE* stream, NodePtr tree)
   249      {
   250          save_value(stream, *tree);
   251          if (tree->child1!=NULL) {
   252              save_tree(stream, tree->child1);
   253          }
   254          if (tree->child2!=NULL) {
   255              save_tree(stream, tree->child2);
   256          }
   257      }
   258  
   259  
   260      void load_tree(FILE* stream, NodePtr& tree)
   261      {
   262          tree = pool_.allocate<Node>();
   263          load_value(stream, *tree);
   264          if (tree->child1!=NULL) {
   265              load_tree(stream, tree->child1);
   266          }
   267          if (tree->child2!=NULL) {
   268              load_tree(stream, tree->child2);
   269          }
   270      }
   271  
   272  
   273      /**
   274       * Create a tree node that subdivides the list of vecs from vind[first]
   275       * to vind[last].  The routine is called recursively on each sublist.
   276       * Place a pointer to this new tree node in the location pTree.
   277       *
   278       * Params: pTree = the new node to create
   279       *                  first = index of the first vector
   280       *                  last = index of the last vector
   281       */
   282      NodePtr divideTree(int* ind, int count)
   283      {
   284          NodePtr node = pool_.allocate<Node>(); // allocate memory
   285  
   286          /* If too few exemplars remain, then make this a leaf node. */
   287          if ( count == 1) {
   288              node->child1 = node->child2 = NULL;    /* Mark as leaf node. */
   289              node->divfeat = *ind;    /* Store index of this vec. */
   290          }
   291          else {
   292              int idx;
   293              int cutfeat;
   294              DistanceType cutval;
   295              meanSplit(ind, count, idx, cutfeat, cutval);
   296  
   297              node->divfeat = cutfeat;
   298              node->divval = cutval;
   299              node->child1 = divideTree(ind, idx);
   300              node->child2 = divideTree(ind+idx, count-idx);
   301          }
   302  
   303          return node;
   304      }
   305  
   306  
   307      /**
   308       * Choose which feature to use in order to subdivide this set of vectors.
   309       * Make a random choice among those with the highest variance, and use
   310       * its variance as the threshold value.
   311       */
   312      void meanSplit(int* ind, int count, int& index, int& cutfeat, DistanceType& cutval)
   313      {
   314          memset(mean_,0,veclen_*sizeof(DistanceType));
   315          memset(var_,0,veclen_*sizeof(DistanceType));
   316  
   317          /* Compute mean values.  Only the first SAMPLE_MEAN values need to be
   318              sampled to get a good estimate.
   319           */
   320          int cnt = std::min((int)SAMPLE_MEAN+1, count);
   321          for (int j = 0; j < cnt; ++j) {
   322              ElementType* v = dataset_[ind[j]];
   323              for (size_t k=0; k<veclen_; ++k) {
   324                  mean_[k] += v[k];
   325              }
   326          }
   327          for (size_t k=0; k<veclen_; ++k) {
   328              mean_[k] /= cnt;
   329          }
   330  
   331          /* Compute variances (no need to divide by count). */
   332          for (int j = 0; j < cnt; ++j) {
   333              ElementType* v = dataset_[ind[j]];
   334              for (size_t k=0; k<veclen_; ++k) {
   335                  DistanceType dist = v[k] - mean_[k];
   336                  var_[k] += dist * dist;
   337              }
   338          }
   339          /* Select one of the highest variance indices at random. */
   340          cutfeat = selectDivision(var_);
   341          cutval = mean_[cutfeat];
   342  
   343          int lim1, lim2;
   344          planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
   345  
   346          if (lim1>count/2) index = lim1;
   347          else if (lim2<count/2) index = lim2;
   348          else index = count/2;
   349  
   350          /* If either list is empty, it means that all remaining features
   351           * are identical. Split in the middle to maintain a balanced tree.
   352           */
   353          if ((lim1==count)||(lim2==0)) index = count/2;
   354      }
   355  
   356  
   357      /**
   358       * Select the top RAND_DIM largest values from v and return the index of
   359       * one of these selected at random.
   360       */
   361      int selectDivision(DistanceType* v)
   362      {
   363          int num = 0;
   364          size_t topind[RAND_DIM];
   365  
   366          /* Create a list of the indices of the top RAND_DIM values. */
   367          for (size_t i = 0; i < veclen_; ++i) {
   368              if ((num < RAND_DIM)||(v[i] > v[topind[num-1]])) {
   369                  /* Put this element at end of topind. */
   370                  if (num < RAND_DIM) {
   371                      topind[num++] = i;            /* Add to list. */
   372                  }
   373                  else {
   374                      topind[num-1] = i;         /* Replace last element. */
   375                  }
   376                  /* Bubble end value down to right location by repeated swapping. */
   377                  int j = num - 1;
   378                  while (j > 0  &&  v[topind[j]] > v[topind[j-1]]) {
   379                      std::swap(topind[j], topind[j-1]);
   380                      --j;
   381                  }
   382              }
   383          }
   384          /* Select a random integer in range [0,num-1], and return that index. */
   385          int rnd = rand_int(num);
   386          return (int)topind[rnd];
   387      }
   388  
   389  
   390      /**
   391       *  Subdivide the list of points by a plane perpendicular on axe corresponding
   392       *  to the 'cutfeat' dimension at 'cutval' position.
   393       *
   394       *  On return:
   395       *  dataset[ind[0..lim1-1]][cutfeat]<cutval
   396       *  dataset[ind[lim1..lim2-1]][cutfeat]==cutval
   397       *  dataset[ind[lim2..count]][cutfeat]>cutval
   398       */
   399      void planeSplit(int* ind, int count, int cutfeat, DistanceType cutval, int& lim1, int& lim2)
   400      {
   401          /* Move vector indices for left subtree to front of list. */
   402          int left = 0;
   403          int right = count-1;
   404          for (;; ) {
   405              while (left<=right && dataset_[ind[left]][cutfeat]<cutval) ++left;
   406              while (left<=right && dataset_[ind[right]][cutfeat]>=cutval) --right;
   407              if (left>right) break;
   408              std::swap(ind[left], ind[right]); ++left; --right;
   409          }
   410          lim1 = left;
   411          right = count-1;
   412          for (;; ) {
   413              while (left<=right && dataset_[ind[left]][cutfeat]<=cutval) ++left;
   414              while (left<=right && dataset_[ind[right]][cutfeat]>cutval) --right;
   415              if (left>right) break;
   416              std::swap(ind[left], ind[right]); ++left; --right;
   417          }
   418          lim2 = left;
   419      }
   420  
   421      /**
   422       * Performs an exact nearest neighbor search. The exact search performs a full
   423       * traversal of the tree.
   424       */
   425      void getExactNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, float epsError)
   426      {
   427          //		checkID -= 1;  /* Set a different unique ID for each search. */
   428  
   429          if (trees_ > 1) {
   430              fprintf(stderr,"It doesn't make any sense to use more than one tree for exact search");
   431          }
   432          if (trees_>0) {
   433              searchLevelExact(result, vec, tree_roots_[0], 0.0, epsError);
   434          }
   435          CV_Assert(result.full());
   436      }
   437  
   438      /**
   439       * Performs the approximate nearest-neighbor search. The search is approximate
   440       * because the tree traversal is abandoned after a given number of descends in
   441       * the tree.
   442       */
   443      void getNeighbors(ResultSet<DistanceType>& result, const ElementType* vec,
   444                        int maxCheck, float epsError, bool explore_all_trees = false)
   445      {
   446          int i;
   447          BranchSt branch;
   448  
   449          int checkCount = 0;
   450          Heap<BranchSt>* heap = new Heap<BranchSt>((int)size_);
   451          DynamicBitset checked(size_);
   452  
   453          /* Search once through each tree down to root. */
   454          for (i = 0; i < trees_; ++i) {
   455              searchLevel(result, vec, tree_roots_[i], 0, checkCount, maxCheck,
   456                          epsError, heap, checked, explore_all_trees);
   457              if (!explore_all_trees && (checkCount >= maxCheck) && result.full())
   458                  break;
   459          }
   460  
   461          /* Keep searching other branches from heap until finished. */
   462          while ( heap->popMin(branch) && (checkCount < maxCheck || !result.full() )) {
   463              searchLevel(result, vec, branch.node, branch.mindist, checkCount, maxCheck,
   464                          epsError, heap, checked, false);
   465          }
   466  
   467          delete heap;
   468  
   469          CV_Assert(result.full());
   470      }
   471  
   472  
   473      /**
   474       *  Search starting from a given node of the tree.  Based on any mismatches at
   475       *  higher levels, all exemplars below this level must have a distance of
   476       *  at least "mindistsq".
   477       */
   478      void searchLevel(ResultSet<DistanceType>& result_set, const ElementType* vec, NodePtr node, DistanceType mindist, int& checkCount, int maxCheck,
   479                       float epsError, Heap<BranchSt>* heap, DynamicBitset& checked, bool explore_all_trees = false)
   480      {
   481          if (result_set.worstDist()<mindist) {
   482              //			printf("Ignoring branch, too far\n");
   483              return;
   484          }
   485  
   486          /* If this is a leaf node, then do check and return. */
   487          if ((node->child1 == NULL)&&(node->child2 == NULL)) {
   488              /*  Do not check same node more than once when searching multiple trees.
   489                  Once a vector is checked, we set its location in vind to the
   490                  current checkID.
   491               */
   492              int index = node->divfeat;
   493              if ( checked.test(index) ||
   494                   (!explore_all_trees && (checkCount>=maxCheck) && result_set.full()) ) {
   495                  return;
   496              }
   497              checked.set(index);
   498              checkCount++;
   499  
   500              DistanceType dist = distance_(dataset_[index], vec, veclen_);
   501              result_set.addPoint(dist,index);
   502  
   503              return;
   504          }
   505  
   506          /* Which child branch should be taken first? */
   507          ElementType val = vec[node->divfeat];
   508          DistanceType diff = val - node->divval;
   509          NodePtr bestChild = (diff < 0) ? node->child1 : node->child2;
   510          NodePtr otherChild = (diff < 0) ? node->child2 : node->child1;
   511  
   512          /* Create a branch record for the branch not taken.  Add distance
   513              of this feature boundary (we don't attempt to correct for any
   514              use of this feature in a parent node, which is unlikely to
   515              happen and would have only a small effect).  Don't bother
   516              adding more branches to heap after halfway point, as cost of
   517              adding exceeds their value.
   518           */
   519  
   520          DistanceType new_distsq = mindist + distance_.accum_dist(val, node->divval, node->divfeat);
   521          //		if (2 * checkCount < maxCheck  ||  !result.full()) {
   522          if ((new_distsq*epsError < result_set.worstDist())||  !result_set.full()) {
   523              heap->insert( BranchSt(otherChild, new_distsq) );
   524          }
   525  
   526          /* Call recursively to search next level down. */
   527          searchLevel(result_set, vec, bestChild, mindist, checkCount, maxCheck, epsError, heap, checked);
   528      }
   529  
   530      /**
   531       * Performs an exact search in the tree starting from a node.
   532       */
   533      void searchLevelExact(ResultSet<DistanceType>& result_set, const ElementType* vec, const NodePtr node, DistanceType mindist, const float epsError)
   534      {
   535          /* If this is a leaf node, then do check and return. */
   536          if ((node->child1 == NULL)&&(node->child2 == NULL)) {
   537              int index = node->divfeat;
   538              DistanceType dist = distance_(dataset_[index], vec, veclen_);
   539              result_set.addPoint(dist,index);
   540              return;
   541          }
   542  
   543          /* Which child branch should be taken first? */
   544          ElementType val = vec[node->divfeat];
   545          DistanceType diff = val - node->divval;
   546          NodePtr bestChild = (diff < 0) ? node->child1 : node->child2;
   547          NodePtr otherChild = (diff < 0) ? node->child2 : node->child1;
   548  
   549          /* Create a branch record for the branch not taken.  Add distance
   550              of this feature boundary (we don't attempt to correct for any
   551              use of this feature in a parent node, which is unlikely to
   552              happen and would have only a small effect).  Don't bother
   553              adding more branches to heap after halfway point, as cost of
   554              adding exceeds their value.
   555           */
   556  
   557          DistanceType new_distsq = mindist + distance_.accum_dist(val, node->divval, node->divfeat);
   558  
   559          /* Call recursively to search next level down. */
   560          searchLevelExact(result_set, vec, bestChild, mindist, epsError);
   561  
   562          if (new_distsq*epsError<=result_set.worstDist()) {
   563              searchLevelExact(result_set, vec, otherChild, new_distsq, epsError);
   564          }
   565      }
   566  
   567  
   568  private:
   569  
   570      enum
   571      {
   572          /**
   573           * To improve efficiency, only SAMPLE_MEAN random values are used to
   574           * compute the mean and variance at each level when building a tree.
   575           * A value of 100 seems to perform as well as using all values.
   576           */
   577          SAMPLE_MEAN = 100,
   578          /**
   579           * Top random dimensions to consider
   580           *
   581           * When creating random trees, the dimension on which to subdivide is
   582           * selected at random from among the top RAND_DIM dimensions with the
   583           * highest variance.  A value of 5 works well.
   584           */
   585          RAND_DIM=5
   586      };
   587  
   588  
   589      /**
   590       * Number of randomized trees that are used
   591       */
   592      int trees_;
   593  
   594      /**
   595       *  Array of indices to vectors in the dataset.
   596       */
   597      std::vector<int> vind_;
   598  
   599      /**
   600       * The dataset used by this index
   601       */
   602      const Matrix<ElementType> dataset_;
   603  
   604      IndexParams index_params_;
   605  
   606      size_t size_;
   607      size_t veclen_;
   608  
   609  
   610      DistanceType* mean_;
   611      DistanceType* var_;
   612  
   613  
   614      /**
   615       * Array of k-d trees used to find neighbours.
   616       */
   617      NodePtr* tree_roots_;
   618  
   619      /**
   620       * Pooled memory allocator.
   621       *
   622       * Using a pooled memory allocator is more efficient
   623       * than allocating memory directly when there is a large
   624       * number small of memory allocations.
   625       */
   626      PooledAllocator pool_;
   627  
   628      Distance distance_;
   629  
   630  
   631  };   // class KDTreeForest
   632  
   633  }
   634  
   635  //! @endcond
   636  
   637  #endif //OPENCV_FLANN_KDTREE_INDEX_H_