123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543 |
- #ifndef OPENCV_FLANN_RESULTSET_H
- #define OPENCV_FLANN_RESULTSET_H
- #include <algorithm>
- #include <cstring>
- #include <iostream>
- #include <limits>
- #include <set>
- #include <vector>
- namespace cvflann
- {
- template <typename T, typename DistanceType>
- struct BranchStruct
- {
- T node;
- DistanceType mindist;
- BranchStruct() {}
- BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {}
- bool operator<(const BranchStruct<T, DistanceType>& rhs) const
- {
- return mindist<rhs.mindist;
- }
- };
- template <typename DistanceType>
- class ResultSet
- {
- public:
- virtual ~ResultSet() {}
- virtual bool full() const = 0;
- virtual void addPoint(DistanceType dist, int index) = 0;
- virtual DistanceType worstDist() const = 0;
- };
- template <typename DistanceType>
- class KNNSimpleResultSet : public ResultSet<DistanceType>
- {
- int* indices;
- DistanceType* dists;
- int capacity;
- int count;
- DistanceType worst_distance_;
- public:
- KNNSimpleResultSet(int capacity_) : capacity(capacity_), count(0)
- {
- }
- void init(int* indices_, DistanceType* dists_)
- {
- indices = indices_;
- dists = dists_;
- count = 0;
- worst_distance_ = (std::numeric_limits<DistanceType>::max)();
- dists[capacity-1] = worst_distance_;
- }
- size_t size() const
- {
- return count;
- }
- bool full() const
- {
- return count == capacity;
- }
- void addPoint(DistanceType dist, int index)
- {
- if (dist >= worst_distance_) return;
- int i;
- for (i=count; i>0; --i) {
- #ifdef FLANN_FIRST_MATCH
- if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) )
- #else
- if (dists[i-1]>dist)
- #endif
- {
- if (i<capacity) {
- dists[i] = dists[i-1];
- indices[i] = indices[i-1];
- }
- }
- else break;
- }
- if (count < capacity) ++count;
- dists[i] = dist;
- indices[i] = index;
- worst_distance_ = dists[capacity-1];
- }
- DistanceType worstDist() const
- {
- return worst_distance_;
- }
- };
- template <typename DistanceType>
- class KNNResultSet : public ResultSet<DistanceType>
- {
- int* indices;
- DistanceType* dists;
- int capacity;
- int count;
- DistanceType worst_distance_;
- public:
- KNNResultSet(int capacity_) : capacity(capacity_), count(0)
- {
- }
- void init(int* indices_, DistanceType* dists_)
- {
- indices = indices_;
- dists = dists_;
- count = 0;
- worst_distance_ = (std::numeric_limits<DistanceType>::max)();
- dists[capacity-1] = worst_distance_;
- }
- size_t size() const
- {
- return count;
- }
- bool full() const
- {
- return count == capacity;
- }
- void addPoint(DistanceType dist, int index)
- {
- if (dist >= worst_distance_) return;
- int i;
- for (i = count; i > 0; --i) {
- #ifdef FLANN_FIRST_MATCH
- if ( (dists[i-1]<=dist) && ((dist!=dists[i-1])||(indices[i-1]<=index)) )
- #else
- if (dists[i-1]<=dist)
- #endif
- {
-
- int j = i - 1;
- while ((j >= 0) && (dists[j] == dist)) {
- if (indices[j] == index) {
- return;
- }
- --j;
- }
- break;
- }
- }
- if (count < capacity) ++count;
- for (int j = count-1; j > i; --j) {
- dists[j] = dists[j-1];
- indices[j] = indices[j-1];
- }
- dists[i] = dist;
- indices[i] = index;
- worst_distance_ = dists[capacity-1];
- }
- DistanceType worstDist() const
- {
- return worst_distance_;
- }
- };
- template <typename DistanceType>
- class RadiusResultSet : public ResultSet<DistanceType>
- {
- DistanceType radius;
- int* indices;
- DistanceType* dists;
- size_t capacity;
- size_t count;
- public:
- RadiusResultSet(DistanceType radius_, int* indices_, DistanceType* dists_, int capacity_) :
- radius(radius_), indices(indices_), dists(dists_), capacity(capacity_)
- {
- init();
- }
- ~RadiusResultSet()
- {
- }
- void init()
- {
- count = 0;
- }
- size_t size() const
- {
- return count;
- }
- bool full() const
- {
- return true;
- }
- void addPoint(DistanceType dist, int index)
- {
- if (dist<radius) {
- if ((capacity>0)&&(count < capacity)) {
- dists[count] = dist;
- indices[count] = index;
- }
- count++;
- }
- }
- DistanceType worstDist() const
- {
- return radius;
- }
- };
- template<typename DistanceType>
- class UniqueResultSet : public ResultSet<DistanceType>
- {
- public:
- struct DistIndex
- {
- DistIndex(DistanceType dist, unsigned int index) :
- dist_(dist), index_(index)
- {
- }
- bool operator<(const DistIndex dist_index) const
- {
- return (dist_ < dist_index.dist_) || ((dist_ == dist_index.dist_) && index_ < dist_index.index_);
- }
- DistanceType dist_;
- unsigned int index_;
- };
-
- UniqueResultSet() :
- worst_distance_(std::numeric_limits<DistanceType>::max())
- {
- }
-
- inline bool full() const
- {
- return is_full_;
- }
-
- virtual void clear() = 0;
-
- virtual void copy(int* indices, DistanceType* dist, int n_neighbors = -1) const
- {
- if (n_neighbors < 0) {
- for (typename std::set<DistIndex>::const_iterator dist_index = dist_indices_.begin(), dist_index_end =
- dist_indices_.end(); dist_index != dist_index_end; ++dist_index, ++indices, ++dist) {
- *indices = dist_index->index_;
- *dist = dist_index->dist_;
- }
- }
- else {
- int i = 0;
- for (typename std::set<DistIndex>::const_iterator dist_index = dist_indices_.begin(), dist_index_end =
- dist_indices_.end(); (dist_index != dist_index_end) && (i < n_neighbors); ++dist_index, ++indices, ++dist, ++i) {
- *indices = dist_index->index_;
- *dist = dist_index->dist_;
- }
- }
- }
-
- virtual void sortAndCopy(int* indices, DistanceType* dist, int n_neighbors = -1) const
- {
- copy(indices, dist, n_neighbors);
- }
-
- size_t size() const
- {
- return dist_indices_.size();
- }
-
- inline DistanceType worstDist() const
- {
- return worst_distance_;
- }
- protected:
-
- bool is_full_;
-
- DistanceType worst_distance_;
-
- std::set<DistIndex> dist_indices_;
- };
- template<typename DistanceType>
- class KNNUniqueResultSet : public UniqueResultSet<DistanceType>
- {
- public:
-
- KNNUniqueResultSet(unsigned int capacity) : capacity_(capacity)
- {
- this->is_full_ = false;
- this->clear();
- }
-
- inline void addPoint(DistanceType dist, int index)
- {
-
- if (dist >= worst_distance_) return;
- dist_indices_.insert(DistIndex(dist, index));
- if (is_full_) {
- if (dist_indices_.size() > capacity_) {
- dist_indices_.erase(*dist_indices_.rbegin());
- worst_distance_ = dist_indices_.rbegin()->dist_;
- }
- }
- else if (dist_indices_.size() == capacity_) {
- is_full_ = true;
- worst_distance_ = dist_indices_.rbegin()->dist_;
- }
- }
-
- void clear()
- {
- dist_indices_.clear();
- worst_distance_ = std::numeric_limits<DistanceType>::max();
- is_full_ = false;
- }
- protected:
- typedef typename UniqueResultSet<DistanceType>::DistIndex DistIndex;
- using UniqueResultSet<DistanceType>::is_full_;
- using UniqueResultSet<DistanceType>::worst_distance_;
- using UniqueResultSet<DistanceType>::dist_indices_;
-
- unsigned int capacity_;
- };
- template<typename DistanceType>
- class RadiusUniqueResultSet : public UniqueResultSet<DistanceType>
- {
- public:
-
- RadiusUniqueResultSet(DistanceType radius) :
- radius_(radius)
- {
- is_full_ = true;
- }
-
- void addPoint(DistanceType dist, int index)
- {
- if (dist <= radius_) dist_indices_.insert(DistIndex(dist, index));
- }
-
- inline void clear()
- {
- dist_indices_.clear();
- }
-
- inline bool full() const
- {
- return true;
- }
-
- inline DistanceType worstDist() const
- {
- return radius_;
- }
- private:
- typedef typename UniqueResultSet<DistanceType>::DistIndex DistIndex;
- using UniqueResultSet<DistanceType>::dist_indices_;
- using UniqueResultSet<DistanceType>::is_full_;
-
- DistanceType radius_;
- };
- template<typename DistanceType>
- class KNNRadiusUniqueResultSet : public KNNUniqueResultSet<DistanceType>
- {
- public:
-
- KNNRadiusUniqueResultSet(unsigned int capacity, DistanceType radius)
- {
- this->capacity_ = capacity;
- this->radius_ = radius;
- this->dist_indices_.reserve(capacity_);
- this->clear();
- }
-
- void clear()
- {
- dist_indices_.clear();
- worst_distance_ = radius_;
- is_full_ = false;
- }
- private:
- using KNNUniqueResultSet<DistanceType>::dist_indices_;
- using KNNUniqueResultSet<DistanceType>::is_full_;
- using KNNUniqueResultSet<DistanceType>::worst_distance_;
-
- unsigned int capacity_;
-
- DistanceType radius_;
- };
- }
- #endif
|