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_RESULTSET_H_
00032 #define _OPENCV_RESULTSET_H_
00033
00034
00035 #include <algorithm>
00036 #include <limits>
00037 #include <vector>
00038 #include "opencv2/flann/dist.h"
00039
00040 using namespace std;
00041
00042
00043 namespace cvflann
00044 {
00045
00046
00047
00048
00049
00050
00051 template <typename T>
00052 struct BranchStruct {
00053 T node;
00054 float mindistsq;
00055
00056 bool operator<(const BranchStruct<T>& rhs)
00057 {
00058 return mindistsq<rhs.mindistsq;
00059 }
00060
00061 static BranchStruct<T> make_branch(const T& aNode, float dist)
00062 {
00063 BranchStruct<T> branch;
00064 branch.node = aNode;
00065 branch.mindistsq = dist;
00066 return branch;
00067 }
00068 };
00069
00070
00071
00072
00073
00074 template <typename ELEM_TYPE>
00075 class ResultSet
00076 {
00077 protected:
00078
00079 public:
00080
00081 virtual ~ResultSet() {};
00082
00083 virtual void init(const ELEM_TYPE* target_, int veclen_) = 0;
00084
00085 virtual int* getNeighbors() = 0;
00086
00087 virtual float* getDistances() = 0;
00088
00089 virtual size_t size() const = 0;
00090
00091 virtual bool full() const = 0;
00092
00093 virtual bool addPoint(const ELEM_TYPE* point, int index) = 0;
00094
00095 virtual float worstDist() const = 0;
00096
00097 };
00098
00099
00100 template <typename ELEM_TYPE>
00101 class KNNResultSet : public ResultSet<ELEM_TYPE>
00102 {
00103 const ELEM_TYPE* target;
00104 const ELEM_TYPE* target_end;
00105 int veclen;
00106
00107 int* indices;
00108 float* dists;
00109 int capacity;
00110
00111 int count;
00112
00113 public:
00114 KNNResultSet(int capacity_, ELEM_TYPE* target_ = NULL, int veclen_ = 0 ) :
00115 target(target_), veclen(veclen_), capacity(capacity_), count(0)
00116 {
00117 target_end = target + veclen;
00118
00119 indices = new int[capacity_];
00120 dists = new float[capacity_];
00121 }
00122
00123 ~KNNResultSet()
00124 {
00125 delete[] indices;
00126 delete[] dists;
00127 }
00128
00129 void init(const ELEM_TYPE* target_, int veclen_)
00130 {
00131 target = target_;
00132 veclen = veclen_;
00133 target_end = target + veclen;
00134 count = 0;
00135 }
00136
00137
00138 int* getNeighbors()
00139 {
00140 return indices;
00141 }
00142
00143 float* getDistances()
00144 {
00145 return dists;
00146 }
00147
00148 size_t size() const
00149 {
00150 return count;
00151 }
00152
00153 bool full() const
00154 {
00155 return count == capacity;
00156 }
00157
00158
00159 bool addPoint(const ELEM_TYPE* point, int index)
00160 {
00161 for (int i=0;i<count;++i) {
00162 if (indices[i]==index) return false;
00163 }
00164 float dist = (float)flann_dist(target, target_end, point);
00165
00166 if (count<capacity) {
00167 indices[count] = index;
00168 dists[count] = dist;
00169 ++count;
00170 }
00171 else if (dist < dists[count-1] || (dist == dists[count-1] && index < indices[count-1])) {
00172
00173 indices[count-1] = index;
00174 dists[count-1] = dist;
00175 }
00176 else {
00177 return false;
00178 }
00179
00180 int i = count-1;
00181
00182 while (i>=1 && (dists[i]<dists[i-1] || (dists[i]==dists[i-1] && indices[i]<indices[i-1]) ) ) {
00183
00184 swap(indices[i],indices[i-1]);
00185 swap(dists[i],dists[i-1]);
00186 i--;
00187 }
00188
00189 return true;
00190 }
00191
00192 float worstDist() const
00193 {
00194 return (count<capacity) ? numeric_limits<float>::max() : dists[count-1];
00195 }
00196 };
00197
00198
00202 template <typename ELEM_TYPE>
00203 class RadiusResultSet : public ResultSet<ELEM_TYPE>
00204 {
00205 const ELEM_TYPE* target;
00206 const ELEM_TYPE* target_end;
00207 int veclen;
00208
00209 struct Item {
00210 int index;
00211 float dist;
00212
00213 bool operator<(Item rhs) {
00214 return dist<rhs.dist;
00215 }
00216 };
00217
00218 vector<Item> items;
00219 float radius;
00220
00221 bool sorted;
00222 int* indices;
00223 float* dists;
00224 size_t count;
00225
00226 private:
00227 void resize_vecs()
00228 {
00229 if (items.size()>count) {
00230 if (indices!=NULL) delete[] indices;
00231 if (dists!=NULL) delete[] dists;
00232 count = items.size();
00233 indices = new int[count];
00234 dists = new float[count];
00235 }
00236 }
00237
00238 public:
00239 RadiusResultSet(float radius_) :
00240 radius(radius_), indices(NULL), dists(NULL)
00241 {
00242 sorted = false;
00243 items.reserve(16);
00244 count = 0;
00245 }
00246
00247 ~RadiusResultSet()
00248 {
00249 if (indices!=NULL) delete[] indices;
00250 if (dists!=NULL) delete[] dists;
00251 }
00252
00253 void init(const ELEM_TYPE* target_, int veclen_)
00254 {
00255 target = target_;
00256 veclen = veclen_;
00257 target_end = target + veclen;
00258 items.clear();
00259 sorted = false;
00260 }
00261
00262 int* getNeighbors()
00263 {
00264 if (!sorted) {
00265 sorted = true;
00266 sort_heap(items.begin(), items.end());
00267 }
00268 resize_vecs();
00269 for (size_t i=0;i<items.size();++i) {
00270 indices[i] = items[i].index;
00271 }
00272 return indices;
00273 }
00274
00275 float* getDistances()
00276 {
00277 if (!sorted) {
00278 sorted = true;
00279 sort_heap(items.begin(), items.end());
00280 }
00281 resize_vecs();
00282 for (size_t i=0;i<items.size();++i) {
00283 dists[i] = items[i].dist;
00284 }
00285 return dists;
00286 }
00287
00288 size_t size() const
00289 {
00290 return items.size();
00291 }
00292
00293 bool full() const
00294 {
00295 return true;
00296 }
00297
00298 bool addPoint(const ELEM_TYPE* point, int index)
00299 {
00300 Item it;
00301 it.index = index;
00302 it.dist = (float)flann_dist(target, target_end, point);
00303 if (it.dist<=radius) {
00304 items.push_back(it);
00305 push_heap(items.begin(), items.end());
00306 return true;
00307 }
00308 return false;
00309 }
00310
00311 float worstDist() const
00312 {
00313 return radius;
00314 }
00315
00316 };
00317
00318 }
00319
00320 #endif //_OPENCV_RESULTSET_H_