Berkeley SfM
naive_matcher_2d2d.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 
38 #include "naive_matcher_2d2d.h"
39 
40 namespace bsfm {
41 
43  int image_index1, int image_index2,
44  PairwiseImageMatch& image_match) {
45  image_match.feature_matches_.clear();
46  image_match.descriptor_indices1_.clear();
47  image_match.descriptor_indices2_.clear();
48 
49  // Get the descriptors corresponding to these two images.
50  std::vector<Descriptor>& descriptors1 =
51  this->image_descriptors_[image_index1];
52  std::vector<Descriptor>& descriptors2 =
53  this->image_descriptors_[image_index2];
54 
55  // Normalize descriptors if required by the distance metric.
58 
59  // Compute forward (and reverse, if applicable) matches.
60  LightFeatureMatchList light_feature_matches;
61  ComputePutativeMatches(descriptors1, descriptors2, light_feature_matches);
62 
63  // Check that we got enough matches here. If we didn't, reverse matches won't
64  // help us.
65  if (light_feature_matches.size() < this->options_.min_num_feature_matches) {
66  return false;
67  }
68 
70  LightFeatureMatchList reverse_light_feature_matches;
71  ComputePutativeMatches(descriptors2, descriptors1,
72  reverse_light_feature_matches);
73  this->SymmetricMatches(reverse_light_feature_matches,
74  light_feature_matches);
75  }
76 
77  if (light_feature_matches.size() < this->options_.min_num_feature_matches) {
78  return false;
79  }
80 
81  // Check how many features the user wants.
82  unsigned int num_features_out = light_feature_matches.size();
83  if (this->options_.only_keep_best_matches) {
84  num_features_out =
85  std::min(num_features_out, this->options_.num_best_matches);
86 
87  // Return relevant matches in sorted order.
88  std::partial_sort(light_feature_matches.begin(),
89  light_feature_matches.begin() + num_features_out,
90  light_feature_matches.end(),
92  }
93 
94  // Convert from LightFeatureMatchList to FeatureMatchList for the output.
95  for (int ii = 0; ii < num_features_out; ++ii) {
96  const auto& match = light_feature_matches[ii];
97 
98  const Feature& matched_feature1 =
99  this->image_features_[image_index1][match.feature_index1_];
100  const Feature& matched_feature2 =
101  this->image_features_[image_index2][match.feature_index2_];
102 
103  image_match.feature_matches_.emplace_back(matched_feature1,
104  matched_feature2);
105 
106  // Also store the index of each descriptor used for this match.
107  image_match.descriptor_indices1_.push_back(match.feature_index1_);
108  image_match.descriptor_indices2_.push_back(match.feature_index2_);
109  }
110 
111  return true;
112 }
113 
115  const std::vector<Descriptor>& descriptors1,
116  const std::vector<Descriptor>& descriptors2,
117  std::vector<LightFeatureMatch>& putative_matches) {
118  putative_matches.clear();
119 
120  // Get the singletone distance metric for descriptor comparison.
122 
123  // Set the maximum tolerable distance between descriptors, if applicable.
126  }
127 
128  // Store all matches and their distances.
129  for (size_t ii = 0; ii < descriptors1.size(); ++ii) {
130  LightFeatureMatchList one_way_matches;
131  for (size_t jj = 0; jj < descriptors2.size(); ++jj) {
132  double dist = distance(descriptors1[ii], descriptors2[jj]);
133 
134  // If max distance was not set above, distance.Max() will be infinity and
135  // this will always be true.
136  if (dist < distance.Max()) {
137  one_way_matches.emplace_back(ii, jj, dist);
138  }
139  }
140 
141  // Store the best match for this element of features2.
142  if (this->options_.use_lowes_ratio) {
143  // Sort by distance. We only care about the distances between the best 2
144  // matches for the Lowes ratio test.
145  std::partial_sort(one_way_matches.begin(),
146  one_way_matches.begin() + 1,
147  one_way_matches.end(),
149 
150  // The second best match must be within the lowes ratio of the best match.
151  double lowes_ratio_squared =
153  if (one_way_matches[0].distance_ <
154  lowes_ratio_squared * one_way_matches[1].distance_) {
155  putative_matches.emplace_back(one_way_matches[0]);
156  }
157  } else {
158  putative_matches.emplace_back(one_way_matches[0]);
159  }
160  }
161 }
162 
163 } //\namespace bsfm
virtual void SymmetricMatches(const std::vector< LightFeatureMatch > &feature_matches_lhs, std::vector< LightFeatureMatch > &feature_matches_rhs)
std::vector< std::vector< Feature > > image_features_
std::vector< LightFeatureMatch > LightFeatureMatchList
static DistanceMetric & Instance()
static bool SortByDistance(const LightFeatureMatch &lhs, const LightFeatureMatch &rhs)
Definition: feature_match.h:93
void SetMaximumDistance(double maximum_distance)
void ComputePutativeMatches(const std::vector< Descriptor > &descriptors1, const std::vector< Descriptor > &descriptors2, std::vector< LightFeatureMatch > &putative_matches)
FeatureMatchList feature_matches_
Definition: camera.cpp:50
virtual bool MatchImagePair(int image_index1, int image_index2, PairwiseImageMatch &feature_matches)
std::vector< std::vector< Descriptor > > image_descriptors_
bool MaybeNormalizeDescriptors(std::vector< Descriptor > &descriptors) const
std::vector< int > descriptor_indices1_
std::vector< int > descriptor_indices2_
FeatureMatcherOptions options_