48 const std::vector<LandmarkIndex>& landmark_indices) {
54 if (view ==
nullptr) {
55 LOG(WARNING) <<
"Cannot perform 2D<-->3D matching. View must not be null.";
60 std::vector<Descriptor> descriptors_2d;
61 std::vector<size_t> observation_indices;
62 std::vector<Observation::Ptr> observations = view->Observations();
63 for (
size_t ii = 0; ii < observations.size(); ++ii) {
64 CHECK_NOTNULL(observations[ii].
get());
65 if (!observations[ii]->IsIncorporated()) {
66 descriptors_2d.push_back(observations[ii]->
Descriptor());
67 observation_indices.push_back(ii);
72 std::vector<Descriptor> descriptors_3d;
73 descriptors_3d.reserve(landmark_indices.size());
74 for (
size_t ii = 0; ii < landmark_indices.size(); ii++) {
76 CHECK_NOTNULL(landmark.get());
77 descriptors_3d.push_back(landmark->Descriptor());
85 std::vector<LightFeatureMatch> forward_matches;
93 std::vector<LightFeatureMatch> reverse_matches;
103 size_t num_features_out = forward_matches.size();
109 std::partial_sort(forward_matches.begin(),
110 forward_matches.begin() + num_features_out,
111 forward_matches.end(),
117 for (
size_t ii = 0; ii < forward_matches.size(); ii++) {
118 const size_t observation_index =
119 observation_indices[forward_matches[ii].feature_index1_];
121 landmark_indices[forward_matches[ii].feature_index2_];
123 observations[observation_index]->SetMatchedLandmark(landmark_index);
134 const std::vector<Descriptor>& descriptors1,
135 const std::vector<Descriptor>& descriptors2,
136 std::vector<LightFeatureMatch>& matches) {
148 for (
size_t ii = 0; ii < descriptors1.size(); ++ii) {
150 for (
size_t jj = 0; jj < descriptors2.size(); ++jj) {
151 double dist = distance(descriptors1[ii], descriptors2[jj]);
155 if (dist < distance.
Max()) {
156 one_way_matches.emplace_back(ii, jj, dist);
164 std::partial_sort(one_way_matches.begin(),
165 one_way_matches.begin() + 1,
166 one_way_matches.end(),
170 double lowes_ratio_squared =
172 if (one_way_matches[0].distance_ <
173 lowes_ratio_squared * one_way_matches[1].distance_) {
174 matches.emplace_back(one_way_matches[0]);
177 matches.emplace_back(one_way_matches[0]);
186 const std::vector<LightFeatureMatch>& feature_matches_lhs,
187 std::vector<LightFeatureMatch>& feature_matches_rhs) {
189 std::unordered_map<int, int> feature_indices;
190 feature_indices.reserve(feature_matches_lhs.size());
193 for (
const auto& feature_match : feature_matches_lhs) {
194 feature_indices.insert(std::make_pair(feature_match.feature_index1_,
195 feature_match.feature_index2_));
200 auto rhs_iter = feature_matches_rhs.begin();
201 while (rhs_iter != feature_matches_rhs.end()) {
202 const auto& lhs_matched_iter =
203 feature_indices.find(rhs_iter->feature_index2_);
206 if (lhs_matched_iter != feature_indices.end()) {
207 if (lhs_matched_iter->second == rhs_iter->feature_index1_) {
214 feature_matches_rhs.erase(rhs_iter);
static Landmark::Ptr GetLandmark(LandmarkIndex landmark_index)
unsigned int LandmarkIndex
bool enforce_maximum_descriptor_distance
bool Match(const FeatureMatcherOptions &options, const ViewIndex &view_index, const std::vector< LandmarkIndex > &landmark_indices)
std::vector< LightFeatureMatch > LightFeatureMatchList
static DistanceMetric & Instance()
static bool SortByDistance(const LightFeatureMatch &lhs, const LightFeatureMatch &rhs)
void SetMaximumDistance(double maximum_distance)
unsigned int num_best_matches
void ComputeSymmetricMatches(const std::vector< LightFeatureMatch > &feature_matches_lhs, std::vector< LightFeatureMatch > &feature_matches_rhs)
unsigned int min_num_feature_matches
static View::Ptr GetView(ViewIndex view_index)
std::shared_ptr< Landmark > Ptr
std::shared_ptr< View > Ptr
double maximum_descriptor_distance
void ComputeOneWayMatches(const std::vector< Descriptor > &descriptors1, const std::vector< Descriptor > &descriptors2, std::vector< LightFeatureMatch > &matches)
bool MaybeNormalizeDescriptors(std::vector< Descriptor > &descriptors) const
::Eigen::Matrix< double, Eigen::Dynamic, 1 > Descriptor
bool only_keep_best_matches
FeatureMatcherOptions options_
bool require_symmetric_matches