github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/opencv4/include/opencv2/flann/result_set.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_RESULTSET_H
    32  #define OPENCV_FLANN_RESULTSET_H
    33  
    34  //! @cond IGNORED
    35  
    36  #include <algorithm>
    37  #include <cstring>
    38  #include <iostream>
    39  #include <limits>
    40  #include <set>
    41  #include <vector>
    42  
    43  namespace cvflann
    44  {
    45  
    46  /* This record represents a branch point when finding neighbors in
    47      the tree.  It contains a record of the minimum distance to the query
    48      point, as well as the node at which the search resumes.
    49   */
    50  
    51  template <typename T, typename DistanceType>
    52  struct BranchStruct
    53  {
    54      T node;           /* Tree node at which search resumes */
    55      DistanceType mindist;     /* Minimum distance to query for all nodes below. */
    56  
    57      BranchStruct() {}
    58      BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {}
    59  
    60      bool operator<(const BranchStruct<T, DistanceType>& rhs) const
    61      {
    62          return mindist<rhs.mindist;
    63      }
    64  };
    65  
    66  
    67  template <typename DistanceType>
    68  class ResultSet
    69  {
    70  public:
    71      virtual ~ResultSet() {}
    72  
    73      virtual bool full() const = 0;
    74  
    75      virtual void addPoint(DistanceType dist, int index) = 0;
    76  
    77      virtual DistanceType worstDist() const = 0;
    78  
    79  };
    80  
    81  /**
    82   * KNNSimpleResultSet does not ensure that the element it holds are unique.
    83   * Is used in those cases where the nearest neighbour algorithm used does not
    84   * attempt to insert the same element multiple times.
    85   */
    86  template <typename DistanceType>
    87  class KNNSimpleResultSet : public ResultSet<DistanceType>
    88  {
    89      int* indices;
    90      DistanceType* dists;
    91      int capacity;
    92      int count;
    93      DistanceType worst_distance_;
    94  
    95  public:
    96      KNNSimpleResultSet(int capacity_) : capacity(capacity_), count(0)
    97      {
    98      }
    99  
   100      void init(int* indices_, DistanceType* dists_)
   101      {
   102          indices = indices_;
   103          dists = dists_;
   104          count = 0;
   105          worst_distance_ = (std::numeric_limits<DistanceType>::max)();
   106          dists[capacity-1] = worst_distance_;
   107      }
   108  
   109      size_t size() const
   110      {
   111          return count;
   112      }
   113  
   114      bool full() const CV_OVERRIDE
   115      {
   116          return count == capacity;
   117      }
   118  
   119  
   120      void addPoint(DistanceType dist, int index) CV_OVERRIDE
   121      {
   122          if (dist >= worst_distance_) return;
   123          int i;
   124          for (i=count; i>0; --i) {
   125  #ifdef FLANN_FIRST_MATCH
   126              if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) )
   127  #else
   128              if (dists[i-1]>dist)
   129  #endif
   130              {
   131                  if (i<capacity) {
   132                      dists[i] = dists[i-1];
   133                      indices[i] = indices[i-1];
   134                  }
   135              }
   136              else break;
   137          }
   138          if (count < capacity) ++count;
   139          dists[i] = dist;
   140          indices[i] = index;
   141          worst_distance_ = dists[capacity-1];
   142      }
   143  
   144      DistanceType worstDist() const CV_OVERRIDE
   145      {
   146          return worst_distance_;
   147      }
   148  };
   149  
   150  /**
   151   * K-Nearest neighbour result set. Ensures that the elements inserted are unique
   152   */
   153  template <typename DistanceType>
   154  class KNNResultSet : public ResultSet<DistanceType>
   155  {
   156      int* indices;
   157      DistanceType* dists;
   158      int capacity;
   159      int count;
   160      DistanceType worst_distance_;
   161  
   162  public:
   163      KNNResultSet(int capacity_)
   164          : indices(NULL), dists(NULL), capacity(capacity_), count(0), worst_distance_(0)
   165      {
   166      }
   167  
   168      void init(int* indices_, DistanceType* dists_)
   169      {
   170          indices = indices_;
   171          dists = dists_;
   172          count = 0;
   173          worst_distance_ = (std::numeric_limits<DistanceType>::max)();
   174          dists[capacity-1] = worst_distance_;
   175      }
   176  
   177      size_t size() const
   178      {
   179          return count;
   180      }
   181  
   182      bool full() const CV_OVERRIDE
   183      {
   184          return count == capacity;
   185      }
   186  
   187  
   188      void addPoint(DistanceType dist, int index) CV_OVERRIDE
   189      {
   190          CV_DbgAssert(indices);
   191          CV_DbgAssert(dists);
   192          if (dist >= worst_distance_) return;
   193          int i;
   194          for (i = count; i > 0; --i) {
   195  #ifdef FLANN_FIRST_MATCH
   196              if ( (dists[i-1]<=dist) && ((dist!=dists[i-1])||(indices[i-1]<=index)) )
   197  #else
   198              if (dists[i-1]<=dist)
   199  #endif
   200              {
   201                  // Check for duplicate indices
   202                  for (int j = i; dists[j] == dist && j--;) {
   203                      if (indices[j] == index) {
   204                          return;
   205                      }
   206                  }
   207                  break;
   208              }
   209          }
   210  
   211          if (count < capacity) ++count;
   212          for (int j = count-1; j > i; --j) {
   213              dists[j] = dists[j-1];
   214              indices[j] = indices[j-1];
   215          }
   216          dists[i] = dist;
   217          indices[i] = index;
   218          worst_distance_ = dists[capacity-1];
   219      }
   220  
   221      DistanceType worstDist() const CV_OVERRIDE
   222      {
   223          return worst_distance_;
   224      }
   225  };
   226  
   227  
   228  /**
   229   * A result-set class used when performing a radius based search.
   230   */
   231  template <typename DistanceType>
   232  class RadiusResultSet : public ResultSet<DistanceType>
   233  {
   234      DistanceType radius;
   235      int* indices;
   236      DistanceType* dists;
   237      size_t capacity;
   238      size_t count;
   239  
   240  public:
   241      RadiusResultSet(DistanceType radius_, int* indices_, DistanceType* dists_, int capacity_) :
   242          radius(radius_), indices(indices_), dists(dists_), capacity(capacity_)
   243      {
   244          init();
   245      }
   246  
   247      ~RadiusResultSet()
   248      {
   249      }
   250  
   251      void init()
   252      {
   253          count = 0;
   254      }
   255  
   256      size_t size() const
   257      {
   258          return count;
   259      }
   260  
   261      bool full() const
   262      {
   263          return true;
   264      }
   265  
   266      void addPoint(DistanceType dist, int index)
   267      {
   268          if (dist<radius) {
   269              if ((capacity>0)&&(count < capacity)) {
   270                  dists[count] = dist;
   271                  indices[count] = index;
   272              }
   273              count++;
   274          }
   275      }
   276  
   277      DistanceType worstDist() const
   278      {
   279          return radius;
   280      }
   281  
   282  };
   283  
   284  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   285  
   286  /** Class that holds the k NN neighbors
   287   * Faster than KNNResultSet as it uses a binary heap and does not maintain two arrays
   288   */
   289  template<typename DistanceType>
   290  class UniqueResultSet : public ResultSet<DistanceType>
   291  {
   292  public:
   293      struct DistIndex
   294      {
   295          DistIndex(DistanceType dist, unsigned int index) :
   296              dist_(dist), index_(index)
   297          {
   298          }
   299          bool operator<(const DistIndex dist_index) const
   300          {
   301              return (dist_ < dist_index.dist_) || ((dist_ == dist_index.dist_) && index_ < dist_index.index_);
   302          }
   303          DistanceType dist_;
   304          unsigned int index_;
   305      };
   306  
   307      /** Default constructor */
   308      UniqueResultSet() :
   309          is_full_(false), worst_distance_(std::numeric_limits<DistanceType>::max())
   310      {
   311      }
   312  
   313      /** Check the status of the set
   314       * @return true if we have k NN
   315       */
   316      inline bool full() const CV_OVERRIDE
   317      {
   318          return is_full_;
   319      }
   320  
   321      /** Remove all elements in the set
   322       */
   323      virtual void clear() = 0;
   324  
   325      /** Copy the set to two C arrays
   326       * @param indices pointer to a C array of indices
   327       * @param dist pointer to a C array of distances
   328       * @param n_neighbors the number of neighbors to copy
   329       */
   330      virtual void copy(int* indices, DistanceType* dist, int n_neighbors = -1) const
   331      {
   332          if (n_neighbors < 0) {
   333              for (typename std::set<DistIndex>::const_iterator dist_index = dist_indices_.begin(), dist_index_end =
   334                       dist_indices_.end(); dist_index != dist_index_end; ++dist_index, ++indices, ++dist) {
   335                  *indices = dist_index->index_;
   336                  *dist = dist_index->dist_;
   337              }
   338          }
   339          else {
   340              int i = 0;
   341              for (typename std::set<DistIndex>::const_iterator dist_index = dist_indices_.begin(), dist_index_end =
   342                       dist_indices_.end(); (dist_index != dist_index_end) && (i < n_neighbors); ++dist_index, ++indices, ++dist, ++i) {
   343                  *indices = dist_index->index_;
   344                  *dist = dist_index->dist_;
   345              }
   346          }
   347      }
   348  
   349      /** Copy the set to two C arrays but sort it according to the distance first
   350       * @param indices pointer to a C array of indices
   351       * @param dist pointer to a C array of distances
   352       * @param n_neighbors the number of neighbors to copy
   353       */
   354      virtual void sortAndCopy(int* indices, DistanceType* dist, int n_neighbors = -1) const
   355      {
   356          copy(indices, dist, n_neighbors);
   357      }
   358  
   359      /** The number of neighbors in the set
   360       * @return
   361       */
   362      size_t size() const
   363      {
   364          return dist_indices_.size();
   365      }
   366  
   367      /** The distance of the furthest neighbor
   368       * If we don't have enough neighbors, it returns the max possible value
   369       * @return
   370       */
   371      inline DistanceType worstDist() const CV_OVERRIDE
   372      {
   373          return worst_distance_;
   374      }
   375  protected:
   376      /** Flag to say if the set is full */
   377      bool is_full_;
   378  
   379      /** The worst distance found so far */
   380      DistanceType worst_distance_;
   381  
   382      /** The best candidates so far */
   383      std::set<DistIndex> dist_indices_;
   384  };
   385  
   386  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   387  
   388  /** Class that holds the k NN neighbors
   389   * Faster than KNNResultSet as it uses a binary heap and does not maintain two arrays
   390   */
   391  template<typename DistanceType>
   392  class KNNUniqueResultSet : public UniqueResultSet<DistanceType>
   393  {
   394  public:
   395      /** Constructor
   396       * @param capacity the number of neighbors to store at max
   397       */
   398      KNNUniqueResultSet(unsigned int capacity) : capacity_(capacity)
   399      {
   400          this->is_full_ = false;
   401          this->clear();
   402      }
   403  
   404      /** Add a possible candidate to the best neighbors
   405       * @param dist distance for that neighbor
   406       * @param index index of that neighbor
   407       */
   408      inline void addPoint(DistanceType dist, int index) CV_OVERRIDE
   409      {
   410          // Don't do anything if we are worse than the worst
   411          if (dist >= worst_distance_) return;
   412          dist_indices_.insert(DistIndex(dist, index));
   413  
   414          if (is_full_) {
   415              if (dist_indices_.size() > capacity_) {
   416                  dist_indices_.erase(*dist_indices_.rbegin());
   417                  worst_distance_ = dist_indices_.rbegin()->dist_;
   418              }
   419          }
   420          else if (dist_indices_.size() == capacity_) {
   421              is_full_ = true;
   422              worst_distance_ = dist_indices_.rbegin()->dist_;
   423          }
   424      }
   425  
   426      /** Remove all elements in the set
   427       */
   428      void clear() CV_OVERRIDE
   429      {
   430          dist_indices_.clear();
   431          worst_distance_ = std::numeric_limits<DistanceType>::max();
   432          is_full_ = false;
   433      }
   434  
   435  protected:
   436      typedef typename UniqueResultSet<DistanceType>::DistIndex DistIndex;
   437      using UniqueResultSet<DistanceType>::is_full_;
   438      using UniqueResultSet<DistanceType>::worst_distance_;
   439      using UniqueResultSet<DistanceType>::dist_indices_;
   440  
   441      /** The number of neighbors to keep */
   442      unsigned int capacity_;
   443  };
   444  
   445  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   446  
   447  /** Class that holds the radius nearest neighbors
   448   * It is more accurate than RadiusResult as it is not limited in the number of neighbors
   449   */
   450  template<typename DistanceType>
   451  class RadiusUniqueResultSet : public UniqueResultSet<DistanceType>
   452  {
   453  public:
   454      /** Constructor
   455       * @param radius the maximum distance of a neighbor
   456       */
   457      RadiusUniqueResultSet(DistanceType radius) :
   458          radius_(radius)
   459      {
   460          is_full_ = true;
   461      }
   462  
   463      /** Add a possible candidate to the best neighbors
   464       * @param dist distance for that neighbor
   465       * @param index index of that neighbor
   466       */
   467      void addPoint(DistanceType dist, int index) CV_OVERRIDE
   468      {
   469          if (dist <= radius_) dist_indices_.insert(DistIndex(dist, index));
   470      }
   471  
   472      /** Remove all elements in the set
   473       */
   474      inline void clear() CV_OVERRIDE
   475      {
   476          dist_indices_.clear();
   477      }
   478  
   479  
   480      /** Check the status of the set
   481       * @return alwys false
   482       */
   483      inline bool full() const CV_OVERRIDE
   484      {
   485          return true;
   486      }
   487  
   488      /** The distance of the furthest neighbor
   489       * If we don't have enough neighbors, it returns the max possible value
   490       * @return
   491       */
   492      inline DistanceType worstDist() const CV_OVERRIDE
   493      {
   494          return radius_;
   495      }
   496  private:
   497      typedef typename UniqueResultSet<DistanceType>::DistIndex DistIndex;
   498      using UniqueResultSet<DistanceType>::dist_indices_;
   499      using UniqueResultSet<DistanceType>::is_full_;
   500  
   501      /** The furthest distance a neighbor can be */
   502      DistanceType radius_;
   503  };
   504  
   505  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   506  
   507  /** Class that holds the k NN neighbors within a radius distance
   508   */
   509  template<typename DistanceType>
   510  class KNNRadiusUniqueResultSet : public KNNUniqueResultSet<DistanceType>
   511  {
   512  public:
   513      /** Constructor
   514       * @param capacity the number of neighbors to store at max
   515       * @param radius the maximum distance of a neighbor
   516       */
   517      KNNRadiusUniqueResultSet(unsigned int capacity, DistanceType radius)
   518      {
   519          this->capacity_ = capacity;
   520          this->radius_ = radius;
   521          this->dist_indices_.reserve(capacity_);
   522          this->clear();
   523      }
   524  
   525      /** Remove all elements in the set
   526       */
   527      void clear()
   528      {
   529          dist_indices_.clear();
   530          worst_distance_ = radius_;
   531          is_full_ = false;
   532      }
   533  private:
   534      using KNNUniqueResultSet<DistanceType>::dist_indices_;
   535      using KNNUniqueResultSet<DistanceType>::is_full_;
   536      using KNNUniqueResultSet<DistanceType>::worst_distance_;
   537  
   538      /** The maximum number of neighbors to consider */
   539      unsigned int capacity_;
   540  
   541      /** The maximum distance of a neighbor */
   542      DistanceType radius_;
   543  };
   544  }
   545  
   546  //! @endcond
   547  
   548  #endif //OPENCV_FLANN_RESULTSET_H