ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
correspondence_graph.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 #include <unordered_map>
11 #include <vector>
12 
13 #include "base/database.h"
14 #include "util/types.h"
15 
16 namespace colmap {
17 
18 // Scene graph represents the graph of image to image and feature to feature
19 // correspondences of a dataset. It should be accessed from the DatabaseCache.
21 public:
22  struct Correspondence {
27 
28  // The identifier of the corresponding image.
30 
31  // The index of the corresponding point in the corresponding image.
33  };
34 
36 
37  // Number of added images.
38  inline size_t NumImages() const;
39 
40  // Number of added images.
41  inline size_t NumImagePairs() const;
42 
43  // Check whether image exists.
44  inline bool ExistsImage(const image_t image_id) const;
45 
46  // Get the number of observations in an image. An observation is an image
47  // point that has at least one correspondence.
48  inline point2D_t NumObservationsForImage(const image_t image_id) const;
49 
50  // Get the number of correspondences per image.
51  inline point2D_t NumCorrespondencesForImage(const image_t image_id) const;
52 
53  // Get the number of correspondences between a pair of images.
55  const image_t image_id1, const image_t image_id2) const;
56 
57  // Get the number of correspondences between all images.
58  std::unordered_map<image_pair_t, point2D_t>
60 
61  // Finalize the database manager.
62  //
63  // - Calculates the number of observations per image by counting the number
64  // of image points that have at least one correspondence.
65  // - Deletes images without observations, as they are useless for SfM.
66  // - Shrinks the correspondence vectors to their size to save memory.
67  void Finalize();
68 
69  // Add new image to the correspondence graph.
70  void AddImage(const image_t image_id, const size_t num_points2D);
71 
72  // Add correspondences between images. This function ignores invalid
73  // correspondences where the point indices are out of bounds or duplicate
74  // correspondences between the same image points. Whenever either of the two
75  // cases occur this function prints a warning to the standard output.
76  void AddCorrespondences(const image_t image_id1,
77  const image_t image_id2,
78  const FeatureMatches& matches);
79 
80  // Find the correspondence of an image observation to all other images.
81  inline const std::vector<Correspondence>& FindCorrespondences(
82  const image_t image_id, const point2D_t point2D_idx) const;
83 
84  // Find correspondences to the given observation.
85  //
86  // Transitively collects correspondences to the given observation by first
87  // finding correspondences to the given observation, then looking for
88  // correspondences to the collected correspondences in the first step, and
89  // so forth until the transitivity is exhausted or no more correspondences
90  // are found. The returned list does not contain duplicates and contains the
91  // given observation.
92  std::vector<Correspondence> FindTransitiveCorrespondences(
93  const image_t image_id,
94  const point2D_t point2D_idx,
95  const size_t transitivity) const;
96 
97  // Find all correspondences between two images.
99  const image_t image_id1, const image_t image_id2) const;
100 
101  // Check whether the image point has correspondences.
102  inline bool HasCorrespondences(const image_t image_id,
103  const point2D_t point2D_idx) const;
104 
105  // Check whether the given observation is part of a two-view track, i.e.
106  // it only has one correspondence and that correspondence has the given
107  // observation as its only correspondence.
108  bool IsTwoViewObservation(const image_t image_id,
109  const point2D_t point2D_idx) const;
110 
111 private:
112  struct Image {
113  // Number of 2D points with at least one correspondence to another
114  // image.
115  point2D_t num_observations = 0;
116 
117  // Total number of correspondences to other images. This measure is
118  // useful to find a good initial pair, that is connected to many images.
119  point2D_t num_correspondences = 0;
120 
121  // Correspondences to other images per image point.
122  std::vector<std::vector<Correspondence>> corrs;
123  };
124 
125  struct ImagePair {
126  // The number of correspondences between pairs of images.
127  point2D_t num_correspondences = 0;
128  };
129 
130  std::unordered_map<image_t, Image> images_;
131  std::unordered_map<image_pair_t, ImagePair> image_pairs_;
132 };
133 
135 // Implementation
137 
138 size_t CorrespondenceGraph::NumImages() const { return images_.size(); }
139 
141  return image_pairs_.size();
142 }
143 
144 bool CorrespondenceGraph::ExistsImage(const image_t image_id) const {
145  return images_.find(image_id) != images_.end();
146 }
147 
149  const image_t image_id) const {
150  return images_.at(image_id).num_observations;
151 }
152 
154  const image_t image_id) const {
155  return images_.at(image_id).num_correspondences;
156 }
157 
159  const image_t image_id1, const image_t image_id2) const {
160  const image_pair_t pair_id =
161  Database::ImagePairToPairId(image_id1, image_id2);
162  const auto it = image_pairs_.find(pair_id);
163  if (it == image_pairs_.end()) {
164  return 0;
165  } else {
166  return static_cast<point2D_t>(it->second.num_correspondences);
167  }
168 }
169 
170 const std::vector<CorrespondenceGraph::Correspondence>&
172  const point2D_t point2D_idx) const {
173  return images_.at(image_id).corrs.at(point2D_idx);
174 }
175 
177  const image_t image_id, const point2D_t point2D_idx) const {
178  return !images_.at(image_id).corrs.at(point2D_idx).empty();
179 }
180 
181 } // namespace colmap
bool HasCorrespondences(const image_t image_id, const point2D_t point2D_idx) const
bool ExistsImage(const image_t image_id) const
const std::vector< Correspondence > & FindCorrespondences(const image_t image_id, const point2D_t point2D_idx) const
void AddImage(const image_t image_id, const size_t num_points2D)
FeatureMatches FindCorrespondencesBetweenImages(const image_t image_id1, const image_t image_id2) const
std::vector< Correspondence > FindTransitiveCorrespondences(const image_t image_id, const point2D_t point2D_idx, const size_t transitivity) const
point2D_t NumCorrespondencesForImage(const image_t image_id) const
bool IsTwoViewObservation(const image_t image_id, const point2D_t point2D_idx) const
void AddCorrespondences(const image_t image_id1, const image_t image_id2, const FeatureMatches &matches)
point2D_t NumObservationsForImage(const image_t image_id) const
std::unordered_map< image_pair_t, point2D_t > NumCorrespondencesBetweenImages() const
static image_pair_t ImagePairToPairId(const image_t image_id1, const image_t image_id2)
Definition: database.h:339
uint64_t image_pair_t
Definition: types.h:64
uint32_t point2D_t
Definition: types.h:67
const point2D_t kInvalidPoint2DIdx
Definition: types.h:79
uint32_t image_t
Definition: types.h:61
const image_t kInvalidImageId
Definition: types.h:76
std::vector< FeatureMatch > FeatureMatches
Definition: types.h:80
Correspondence(const image_t image_id, const point2D_t point2D_idx)