Berkeley SfM
flann_descriptor_kdtree.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, The Regents of the University of California (Regents).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer in the documentation and/or other materials provided
15  * with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Please contact the author(s) of this library if you have any questions.
34  * Authors: Erik Nelson ( eanelson@eecs.berkeley.edu )
35  * David Fridovich-Keil ( dfk@eecs.berkeley.edu )
36  */
37 
39 
40 namespace bsfm {
41 
43 
45  // Free memory from descriptors in the kd tree.
46  if (index_ != nullptr) {
47  for (size_t ii = 0; ii < index_->size(); ++ii) {
48  double* descriptor = index_->getPoint(ii);
49  delete[] descriptor;
50  }
51  }
52 }
53 
54 // Add descriptors to the index.
56 
57  // Copy the input descriptor into FLANN's Matrix type.
58  const size_t cols = descriptor.size();
59  flann::Matrix<double> flann_descriptor(new double[cols], 1, cols);
60  for (size_t ii = 0; ii < cols; ++ii) {
61  flann_descriptor[0][ii] = descriptor(ii);
62  }
63 
64  // If this is the first point in the index, create the index and exit.
65  if (index_ == nullptr) {
66  // Single kd-tree. No approximation.
67  const int kNumRandomizedKDTrees = 1;
68  index_.reset(new flann::Index<flann::L2<double> >(
69  flann_descriptor, flann::KDTreeIndexParams(kNumRandomizedKDTrees)));
70  index_->buildIndex();
71  return;
72  }
73 
74  // If the index is already created, add the data point to the index. Rebuild
75  // every time the index doubles in size to occasionally rebalance the kd tree.
76  const int kRebuildThreshold = 2;
77  index_->addPoints(flann_descriptor, kRebuildThreshold);
78 }
79 
80 // Add descriptors to the index.
82  std::vector<Descriptor>& descriptors) {
83  for (auto& descriptor : descriptors) {
84  AddDescriptor(descriptor);
85  }
86 }
87 
88 // Queries the kd tree for the nearest neighbor of 'query'.
90  double& nn_distance) {
91  if (index_ == nullptr) {
92  VLOG(1) << "Index has not been built. Descriptors must be added before "
93  "querying the kd tree";
94  return false;
95  }
96 
97  // Convert the input descriptor to the FLANN format. We can use Eigen's memory
98  // here, since we will have our answer before leaving function scope.
99  flann::Matrix<double> flann_query(query.data(), 1, index_->veclen());
100 
101  // Search the kd tree for the nearest neighbor to the query.
102  std::vector< std::vector<int> > query_match_indices;
103  std::vector< std::vector<double> > query_distances;
104 
105  const int kOneNearestNeighbor = 1;
106  int num_neighbors_found = index_->knnSearch(
107  flann_query, query_match_indices, query_distances, kOneNearestNeighbor,
108  flann::SearchParams(flann::FLANN_CHECKS_UNLIMITED) /* no approx */);
109 
110  // If we found a nearest neighbor, assign output.
111  if (num_neighbors_found > 0) {
112  nn_index = query_match_indices[0][0];
113  nn_distance = query_distances[0][0];
114  }
115 
116  return num_neighbors_found > 0;
117 }
118 
119 } //\namespace bsfm
void AddDescriptors(std::vector< Descriptor > &descriptors)
bool NearestNeighbor(Descriptor &query, int &nn_index, double &nn_distance)
std::shared_ptr< flann::Index< flann::L2< double > > > index_
Definition: camera.cpp:50
void AddDescriptor(Descriptor &descriptor)
::Eigen::Matrix< double, Eigen::Dynamic, 1 > Descriptor
Definition: types.h:83