Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef OPENCV_FLANN_RESULTSET_H
00032 #define OPENCV_FLANN_RESULTSET_H
00033
00034 #include <algorithm>
00035 #include <cstring>
00036 #include <iostream>
00037 #include <limits>
00038 #include <set>
00039 #include <vector>
00040
00041 namespace cvflann
00042 {
00043
00044
00045
00046
00047
00048
00049 template <typename T, typename DistanceType>
00050 struct BranchStruct
00051 {
00052 T node;
00053 DistanceType mindist;
00054
00055 BranchStruct() {}
00056 BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {}
00057
00058 bool operator<(const BranchStruct<T, DistanceType>& rhs) const
00059 {
00060 return mindist<rhs.mindist;
00061 }
00062 };
00063
00064
00065 template <typename DistanceType>
00066 class ResultSet
00067 {
00068 public:
00069 virtual ~ResultSet() {}
00070
00071 virtual bool full() const = 0;
00072
00073 virtual void addPoint(DistanceType dist, int index) = 0;
00074
00075 virtual DistanceType worstDist() const = 0;
00076
00077 };
00078
00084 template <typename DistanceType>
00085 class KNNSimpleResultSet : public ResultSet<DistanceType>
00086 {
00087 int* indices;
00088 DistanceType* dists;
00089 int capacity;
00090 int count;
00091 DistanceType worst_distance_;
00092
00093 public:
00094 KNNSimpleResultSet(int capacity_) : capacity(capacity_), count(0)
00095 {
00096 }
00097
00098 void init(int* indices_, DistanceType* dists_)
00099 {
00100 indices = indices_;
00101 dists = dists_;
00102 count = 0;
00103 worst_distance_ = (std::numeric_limits<DistanceType>::max)();
00104 dists[capacity-1] = worst_distance_;
00105 }
00106
00107 size_t size() const
00108 {
00109 return count;
00110 }
00111
00112 bool full() const
00113 {
00114 return count == capacity;
00115 }
00116
00117
00118 void addPoint(DistanceType dist, int index)
00119 {
00120 if (dist >= worst_distance_) return;
00121 int i;
00122 for (i=count; i>0; --i) {
00123 #ifdef FLANN_FIRST_MATCH
00124 if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) )
00125 #else
00126 if (dists[i-1]>dist)
00127 #endif
00128 {
00129 if (i<capacity) {
00130 dists[i] = dists[i-1];
00131 indices[i] = indices[i-1];
00132 }
00133 }
00134 else break;
00135 }
00136 if (count < capacity) ++count;
00137 dists[i] = dist;
00138 indices[i] = index;
00139 worst_distance_ = dists[capacity-1];
00140 }
00141
00142 DistanceType worstDist() const
00143 {
00144 return worst_distance_;
00145 }
00146 };
00147
00151 template <typename DistanceType>
00152 class KNNResultSet : public ResultSet<DistanceType>
00153 {
00154 int* indices;
00155 DistanceType* dists;
00156 int capacity;
00157 int count;
00158 DistanceType worst_distance_;
00159
00160 public:
00161 KNNResultSet(int capacity_) : capacity(capacity_), count(0)
00162 {
00163 }
00164
00165 void init(int* indices_, DistanceType* dists_)
00166 {
00167 indices = indices_;
00168 dists = dists_;
00169 count = 0;
00170 worst_distance_ = (std::numeric_limits<DistanceType>::max)();
00171 dists[capacity-1] = worst_distance_;
00172 }
00173
00174 size_t size() const
00175 {
00176 return count;
00177 }
00178
00179 bool full() const
00180 {
00181 return count == capacity;
00182 }
00183
00184
00185 void addPoint(DistanceType dist, int index)
00186 {
00187 if (dist >= worst_distance_) return;
00188 int i;
00189 for (i = count; i > 0; --i) {
00190 #ifdef FLANN_FIRST_MATCH
00191 if ( (dists[i-1]<=dist) && ((dist!=dists[i-1])||(indices[i-1]<=index)) )
00192 #else
00193 if (dists[i-1]<=dist)
00194 #endif
00195 {
00196
00197 int j = i - 1;
00198 while ((j >= 0) && (dists[j] == dist)) {
00199 if (indices[j] == index) {
00200 return;
00201 }
00202 --j;
00203 }
00204 break;
00205 }
00206 }
00207
00208 if (count < capacity) ++count;
00209 for (int j = count-1; j > i; --j) {
00210 dists[j] = dists[j-1];
00211 indices[j] = indices[j-1];
00212 }
00213 dists[i] = dist;
00214 indices[i] = index;
00215 worst_distance_ = dists[capacity-1];
00216 }
00217
00218 DistanceType worstDist() const
00219 {
00220 return worst_distance_;
00221 }
00222 };
00223
00224
00228 template <typename DistanceType>
00229 class RadiusResultSet : public ResultSet<DistanceType>
00230 {
00231 DistanceType radius;
00232 int* indices;
00233 DistanceType* dists;
00234 size_t capacity;
00235 size_t count;
00236
00237 public:
00238 RadiusResultSet(DistanceType radius_, int* indices_, DistanceType* dists_, int capacity_) :
00239 radius(radius_), indices(indices_), dists(dists_), capacity(capacity_)
00240 {
00241 init();
00242 }
00243
00244 ~RadiusResultSet()
00245 {
00246 }
00247
00248 void init()
00249 {
00250 count = 0;
00251 }
00252
00253 size_t size() const
00254 {
00255 return count;
00256 }
00257
00258 bool full() const
00259 {
00260 return true;
00261 }
00262
00263 void addPoint(DistanceType dist, int index)
00264 {
00265 if (dist<radius) {
00266 if ((capacity>0)&&(count < capacity)) {
00267 dists[count] = dist;
00268 indices[count] = index;
00269 }
00270 count++;
00271 }
00272 }
00273
00274 DistanceType worstDist() const
00275 {
00276 return radius;
00277 }
00278
00279 };
00280
00282
00286 template<typename DistanceType>
00287 class UniqueResultSet : public ResultSet<DistanceType>
00288 {
00289 public:
00290 struct DistIndex
00291 {
00292 DistIndex(DistanceType dist, unsigned int index) :
00293 dist_(dist), index_(index)
00294 {
00295 }
00296 bool operator<(const DistIndex dist_index) const
00297 {
00298 return (dist_ < dist_index.dist_) || ((dist_ == dist_index.dist_) && index_ < dist_index.index_);
00299 }
00300 DistanceType dist_;
00301 unsigned int index_;
00302 };
00303
00305 UniqueResultSet() :
00306 worst_distance_(std::numeric_limits<DistanceType>::max())
00307 {
00308 }
00309
00313 inline bool full() const
00314 {
00315 return is_full_;
00316 }
00317
00320 virtual void clear() = 0;
00321
00327 virtual void copy(int* indices, DistanceType* dist, int n_neighbors = -1) const
00328 {
00329 if (n_neighbors < 0) {
00330 for (typename std::set<DistIndex>::const_iterator dist_index = dist_indices_.begin(), dist_index_end =
00331 dist_indices_.end(); dist_index != dist_index_end; ++dist_index, ++indices, ++dist) {
00332 *indices = dist_index->index_;
00333 *dist = dist_index->dist_;
00334 }
00335 }
00336 else {
00337 int i = 0;
00338 for (typename std::set<DistIndex>::const_iterator dist_index = dist_indices_.begin(), dist_index_end =
00339 dist_indices_.end(); (dist_index != dist_index_end) && (i < n_neighbors); ++dist_index, ++indices, ++dist, ++i) {
00340 *indices = dist_index->index_;
00341 *dist = dist_index->dist_;
00342 }
00343 }
00344 }
00345
00351 virtual void sortAndCopy(int* indices, DistanceType* dist, int n_neighbors = -1) const
00352 {
00353 copy(indices, dist, n_neighbors);
00354 }
00355
00359 size_t size() const
00360 {
00361 return dist_indices_.size();
00362 }
00363
00368 inline DistanceType worstDist() const
00369 {
00370 return worst_distance_;
00371 }
00372 protected:
00374 bool is_full_;
00375
00377 DistanceType worst_distance_;
00378
00380 std::set<DistIndex> dist_indices_;
00381 };
00382
00384
00388 template<typename DistanceType>
00389 class KNNUniqueResultSet : public UniqueResultSet<DistanceType>
00390 {
00391 public:
00395 KNNUniqueResultSet(unsigned int capacity) : capacity_(capacity)
00396 {
00397 this->is_full_ = false;
00398 this->clear();
00399 }
00400
00405 inline void addPoint(DistanceType dist, int index)
00406 {
00407
00408 if (dist >= worst_distance_) return;
00409 dist_indices_.insert(DistIndex(dist, index));
00410
00411 if (is_full_) {
00412 if (dist_indices_.size() > capacity_) {
00413 dist_indices_.erase(*dist_indices_.rbegin());
00414 worst_distance_ = dist_indices_.rbegin()->dist_;
00415 }
00416 }
00417 else if (dist_indices_.size() == capacity_) {
00418 is_full_ = true;
00419 worst_distance_ = dist_indices_.rbegin()->dist_;
00420 }
00421 }
00422
00425 void clear()
00426 {
00427 dist_indices_.clear();
00428 worst_distance_ = std::numeric_limits<DistanceType>::max();
00429 is_full_ = false;
00430 }
00431
00432 protected:
00433 typedef typename UniqueResultSet<DistanceType>::DistIndex DistIndex;
00434 using UniqueResultSet<DistanceType>::is_full_;
00435 using UniqueResultSet<DistanceType>::worst_distance_;
00436 using UniqueResultSet<DistanceType>::dist_indices_;
00437
00439 unsigned int capacity_;
00440 };
00441
00443
00447 template<typename DistanceType>
00448 class RadiusUniqueResultSet : public UniqueResultSet<DistanceType>
00449 {
00450 public:
00454 RadiusUniqueResultSet(DistanceType radius) :
00455 radius_(radius)
00456 {
00457 is_full_ = true;
00458 }
00459
00464 void addPoint(DistanceType dist, int index)
00465 {
00466 if (dist <= radius_) dist_indices_.insert(DistIndex(dist, index));
00467 }
00468
00471 inline void clear()
00472 {
00473 dist_indices_.clear();
00474 }
00475
00476
00480 inline bool full() const
00481 {
00482 return true;
00483 }
00484
00489 inline DistanceType worstDist() const
00490 {
00491 return radius_;
00492 }
00493 private:
00494 typedef typename UniqueResultSet<DistanceType>::DistIndex DistIndex;
00495 using UniqueResultSet<DistanceType>::dist_indices_;
00496 using UniqueResultSet<DistanceType>::is_full_;
00497
00499 DistanceType radius_;
00500 };
00501
00503
00506 template<typename DistanceType>
00507 class KNNRadiusUniqueResultSet : public KNNUniqueResultSet<DistanceType>
00508 {
00509 public:
00513 KNNRadiusUniqueResultSet(unsigned int capacity, DistanceType radius)
00514 {
00515 this->capacity_ = capacity;
00516 this->radius_ = radius;
00517 this->dist_indices_.reserve(capacity_);
00518 this->clear();
00519 }
00520
00523 void clear()
00524 {
00525 dist_indices_.clear();
00526 worst_distance_ = radius_;
00527 is_full_ = false;
00528 }
00529 private:
00530 using KNNUniqueResultSet<DistanceType>::dist_indices_;
00531 using KNNUniqueResultSet<DistanceType>::is_full_;
00532 using KNNUniqueResultSet<DistanceType>::worst_distance_;
00533
00535 unsigned int capacity_;
00536
00538 DistanceType radius_;
00539 };
00540 }
00541
00542 #endif //OPENCV_FLANN_RESULTSET_H
00543