EstervQrCode 1.1.1
Library for qr code manipulation
kdtree_index.h
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 
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 
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 
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 
111  ~KDTreeIndex()
112  {
113  if (tree_roots_!=NULL) {
114  delete[] tree_roots_;
115  }
116  delete[] mean_;
117  delete[] var_;
118  }
119 
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 
173  size_t size() const CV_OVERRIDE
174  {
175  return size_;
176  }
177 
181  size_t veclen() const CV_OVERRIDE
182  {
183  return veclen_;
184  }
185 
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 
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  {
232  int divfeat;
236  DistanceType divval;
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 
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 
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 
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 
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 
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 
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  int checkCount = 0;
449  DynamicBitset checked(size_);
450 
451  // Priority queue storing intermediate branches in the best-bin-first search
452  const cv::Ptr<Heap<BranchSt>>& heap = Heap<BranchSt>::getPooledInstance(cv::utils::getThreadID(), (int)size_);
453 
454  /* Search once through each tree down to root. */
455  for (i = 0; i < trees_; ++i) {
456  searchLevel(result, vec, tree_roots_[i], 0, checkCount, maxCheck,
457  epsError, heap, checked, explore_all_trees);
458  if (!explore_all_trees && (checkCount >= maxCheck) && result.full())
459  break;
460  }
461 
462  /* Keep searching other branches from heap until finished. */
463  while ( heap->popMin(branch) && (checkCount < maxCheck || !result.full() )) {
464  searchLevel(result, vec, branch.node, branch.mindist, checkCount, maxCheck,
465  epsError, heap, checked, false);
466  }
467 
468  CV_Assert(result.full());
469  }
470 
471 
477  void searchLevel(ResultSet<DistanceType>& result_set, const ElementType* vec, NodePtr node, DistanceType mindist, int& checkCount, int maxCheck,
478  float epsError, const cv::Ptr<Heap<BranchSt>>& heap, DynamicBitset& checked, bool explore_all_trees = false)
479  {
480  if (result_set.worstDist()<mindist) {
481  // printf("Ignoring branch, too far\n");
482  return;
483  }
484 
485  /* If this is a leaf node, then do check and return. */
486  if ((node->child1 == NULL)&&(node->child2 == NULL)) {
487  /* Do not check same node more than once when searching multiple trees.
488  Once a vector is checked, we set its location in vind to the
489  current checkID.
490  */
491  int index = node->divfeat;
492  if ( checked.test(index) ||
493  (!explore_all_trees && (checkCount>=maxCheck) && result_set.full()) ) {
494  return;
495  }
496  checked.set(index);
497  checkCount++;
498 
499  DistanceType dist = distance_(dataset_[index], vec, veclen_);
500  result_set.addPoint(dist,index);
501 
502  return;
503  }
504 
505  /* Which child branch should be taken first? */
506  ElementType val = vec[node->divfeat];
507  DistanceType diff = val - node->divval;
508  NodePtr bestChild = (diff < 0) ? node->child1 : node->child2;
509  NodePtr otherChild = (diff < 0) ? node->child2 : node->child1;
510 
511  /* Create a branch record for the branch not taken. Add distance
512  of this feature boundary (we don't attempt to correct for any
513  use of this feature in a parent node, which is unlikely to
514  happen and would have only a small effect). Don't bother
515  adding more branches to heap after halfway point, as cost of
516  adding exceeds their value.
517  */
518 
519  DistanceType new_distsq = mindist + distance_.accum_dist(val, node->divval, node->divfeat);
520  // if (2 * checkCount < maxCheck || !result.full()) {
521  if ((new_distsq*epsError < result_set.worstDist())|| !result_set.full()) {
522  heap->insert( BranchSt(otherChild, new_distsq) );
523  }
524 
525  /* Call recursively to search next level down. */
526  searchLevel(result_set, vec, bestChild, mindist, checkCount, maxCheck, epsError, heap, checked);
527  }
528 
532  void searchLevelExact(ResultSet<DistanceType>& result_set, const ElementType* vec, const NodePtr node, DistanceType mindist, const float epsError)
533  {
534  /* If this is a leaf node, then do check and return. */
535  if ((node->child1 == NULL)&&(node->child2 == NULL)) {
536  int index = node->divfeat;
537  DistanceType dist = distance_(dataset_[index], vec, veclen_);
538  result_set.addPoint(dist,index);
539  return;
540  }
541 
542  /* Which child branch should be taken first? */
543  ElementType val = vec[node->divfeat];
544  DistanceType diff = val - node->divval;
545  NodePtr bestChild = (diff < 0) ? node->child1 : node->child2;
546  NodePtr otherChild = (diff < 0) ? node->child2 : node->child1;
547 
548  /* Create a branch record for the branch not taken. Add distance
549  of this feature boundary (we don't attempt to correct for any
550  use of this feature in a parent node, which is unlikely to
551  happen and would have only a small effect). Don't bother
552  adding more branches to heap after halfway point, as cost of
553  adding exceeds their value.
554  */
555 
556  DistanceType new_distsq = mindist + distance_.accum_dist(val, node->divval, node->divfeat);
557 
558  /* Call recursively to search next level down. */
559  searchLevelExact(result_set, vec, bestChild, mindist, epsError);
560 
561  if (new_distsq*epsError<=result_set.worstDist()) {
562  searchLevelExact(result_set, vec, otherChild, new_distsq, epsError);
563  }
564  }
565 
566 
567 private:
568 
569  enum
570  {
576  SAMPLE_MEAN = 100,
584  RAND_DIM=5
585  };
586 
587 
591  int trees_;
592 
596  std::vector<int> vind_;
597 
601  const Matrix<ElementType> dataset_;
602 
603  IndexParams index_params_;
604 
605  size_t size_;
606  size_t veclen_;
607 
608 
609  DistanceType* mean_;
610  DistanceType* var_;
611 
612 
616  NodePtr* tree_roots_;
617 
625  PooledAllocator pool_;
626 
627  Distance distance_;
628 
629 
630 }; // class KDTreeForest
631 
632 }
633 
635 
636 #endif //OPENCV_FLANN_KDTREE_INDEX_H_
T fprintf(T... args)
CV_EXPORTS_W void randShuffle(InputOutputArray dst, double iterFactor=1., RNG *rng=0)
Shuffles the array elements randomly.
const int * idx
Definition: core_c.h:668
int index
Definition: core_c.h:634
CvSize size
Definition: core_c.h:112
int count
Definition: core_c.h:1413
const CvArr const CvArr CvArr * result
Definition: core_c.h:1423
#define CV_OVERRIDE
Definition: cvdef.h:792
#define CV_Assert(expr)
Checks a condition at runtime and throws exception if it fails.
Definition: base.hpp:342
CV_EXPORTS OutputArray int double double InputArray OutputArray int int bool double k
Definition: imgproc.hpp:2133
T memset(T... args)
T min(T... args)
CV_EXPORTS int getThreadID()
Definition: flann.hpp:60
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
T random_shuffle(T... args)
Definition: cvstd_wrapper.hpp:74
T swap(T... args)