ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
incremental_mapper.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 "base/database.h"
11 #include "base/database_cache.h"
12 #include "base/reconstruction.h"
15 #include "util/alignment.h"
16 
17 namespace colmap {
18 
19 // Class that provides all functionality for the incremental reconstruction
20 // procedure. Example usage:
21 //
22 // IncrementalMapper mapper(&database_cache);
23 // mapper.BeginReconstruction(&reconstruction);
24 // CHECK(mapper.FindInitialImagePair(options, image_id1, image_id2));
25 // CHECK(mapper.RegisterInitialImagePair(options, image_id1, image_id2));
26 // while (...) {
27 // const auto next_image_ids = mapper.FindNextImages(options);
28 // for (const auto image_id : next_image_ids) {
29 // CHECK(mapper.RegisterNextImage(options, image_id));
30 // if (...) {
31 // mapper.AdjustLocalBundle(...);
32 // } else {
33 // mapper.AdjustGlobalBundle(...);
34 // }
35 // }
36 // }
37 // mapper.EndReconstruction(false);
38 //
40 public:
41  struct Options {
42  // Minimum number of inliers for initial image pair.
44 
45  // Maximum error in pixels for two-view geometry estimation for initial
46  // image pair.
47  double init_max_error = 4.0;
48 
49  // Maximum forward motion for initial image pair.
50  double init_max_forward_motion = 0.95;
51 
52  // Minimum triangulation angle for initial image pair.
53  double init_min_tri_angle = 16.0;
54 
55  // Maximum number of trials to use an image for initialization.
57 
58  // Maximum reprojection error in absolute pose estimation.
59  double abs_pose_max_error = 12.0;
60 
61  // Minimum number of inliers in absolute pose estimation.
63 
64  // Minimum inlier ratio in absolute pose estimation.
66 
67  // Whether to estimate the focal length in absolute pose estimation.
69 
70  // Whether to estimate the extra parameters in absolute pose estimation.
72 
73  // Number of images to optimize in local bundle adjustment.
75 
76  // Minimum triangulation for images to be chosen in local bundle
77  // adjustment.
78  double local_ba_min_tri_angle = 6.0;
79 
80  // Thresholds for bogus camera parameters. Images with bogus camera
81  // parameters are filtered and ignored in triangulation.
82  double min_focal_length_ratio = 0.1; // Opening angle of ~130deg
83  double max_focal_length_ratio = 10.0; // Opening angle of ~5deg
84  double max_extra_param = 1.0;
85 
86  // Maximum reprojection error in pixels for observations.
88 
89  // Minimum triangulation angle in degrees for stable 3D points.
90  double filter_min_tri_angle = 1.5;
91 
92  // Maximum number of trials to register an image.
93  int max_reg_trials = 3;
94 
95  // If reconstruction is provided as input, fix the existing image poses.
96  bool fix_existing_images = false;
97 
98  // Number of threads.
99  int num_threads = -1;
100 
101  // Method to find and select next best image to register.
102  enum class ImageSelectionMethod {
106  };
109 
110  bool Check() const;
111  };
112 
118  };
119 
120  // Create incremental mapper. The database cache must live for the entire
121  // life-time of the incremental mapper.
122  explicit IncrementalMapper(const DatabaseCache* database_cache);
123 
124  // Prepare the mapper for a new reconstruction, which might have existing
125  // registered images (in which case `RegisterNextImage` must be called) or
126  // which is empty (in which case `RegisterInitialImagePair` must be called).
127  void BeginReconstruction(Reconstruction* reconstruction);
128 
129  // Cleanup the mapper after the current reconstruction is done. If the
130  // model is discarded, the number of total and shared registered images will
131  // be updated accordingly.
132  void EndReconstruction(const bool discard);
133 
134  // Find initial image pair to seed the incremental reconstruction. The image
135  // pairs should be passed to `RegisterInitialImagePair`. This function
136  // automatically ignores image pairs that failed to register previously.
137  bool FindInitialImagePair(const Options& options,
138  image_t* image_id1,
139  image_t* image_id2);
140 
141  // Find best next image to register in the incremental reconstruction. The
142  // images should be passed to `RegisterNextImage`. This function
143  // automatically ignores images that failed to registered for
144  // `max_reg_trials`.
145  std::vector<image_t> FindNextImages(const Options& options);
146 
147  // Attempt to seed the reconstruction from an image pair.
148  bool RegisterInitialImagePair(const Options& options,
149  const image_t image_id1,
150  const image_t image_id2);
151 
152  // Attempt to register image to the existing model. This requires that
153  // a previous call to `RegisterInitialImagePair` was successful.
154  bool RegisterNextImage(const Options& options, const image_t image_id);
155 
156  // Triangulate observations of image.
157  size_t TriangulateImage(const IncrementalTriangulator::Options& tri_options,
158  const image_t image_id);
159 
160  // Retriangulate image pairs that should have common observations according
161  // to the scene graph but don't due to drift, etc. To handle drift, the
162  // employed reprojection error thresholds should be relatively large. If the
163  // thresholds are too large, non-robust bundle adjustment will break down;
164  // if the thresholds are too small, we cannot fix drift effectively.
165  size_t Retriangulate(const IncrementalTriangulator::Options& tri_options);
166 
167  // Complete tracks by transitively following the scene graph
168  // correspondences. This is especially effective after bundle adjustment,
169  // since many cameras and point locations might have improved. Completion of
170  // tracks enables better subsequent registration of new images.
171  size_t CompleteTracks(const IncrementalTriangulator::Options& tri_options);
172 
173  // Merge tracks by using scene graph correspondences. Similar to
174  // `CompleteTracks`, this is effective after bundle adjustment and improves
175  // the redundancy in subsequent bundle adjustments.
176  size_t MergeTracks(const IncrementalTriangulator::Options& tri_options);
177 
178  // Adjust locally connected images and points of a reference image. In
179  // addition, refine the provided 3D points. Only images connected to the
180  // reference image are optimized. If the provided 3D points are not locally
181  // connected to the reference image, their observing images are set as
182  // constant in the adjustment.
184  const Options& options,
185  const BundleAdjustmentOptions& ba_options,
186  const IncrementalTriangulator::Options& tri_options,
187  const image_t image_id,
188  const std::unordered_set<point3D_t>& point3D_ids);
189 
190  // Global bundle adjustment using Ceres Solver or PBA.
191  bool AdjustGlobalBundle(const Options& options,
192  const BundleAdjustmentOptions& ba_options);
193 #ifdef PBA_ENABLED
194  bool AdjustParallelGlobalBundle(
195  const BundleAdjustmentOptions& ba_options,
196  const ParallelBundleAdjuster::Options& parallel_ba_options);
197 #endif
198  // Filter images and point observations.
199  size_t FilterImages(const Options& options);
200  size_t FilterPoints(const Options& options);
201 
202  const Reconstruction& GetReconstruction() const;
203 
204  // Number of images that are registered in at least on reconstruction.
205  size_t NumTotalRegImages() const;
206 
207  // Number of shared images between current reconstruction and all other
208  // previous reconstructions.
209  size_t NumSharedRegImages() const;
210 
211  // Get changed 3D points, since the last call to `ClearModifiedPoints3D`.
212  const std::unordered_set<point3D_t>& GetModifiedPoints3D();
213 
214  // Clear the collection of changed 3D points.
215  void ClearModifiedPoints3D();
216 
217 private:
218  // Find seed images for incremental reconstruction. Suitable seed images
219  // have a large number of correspondences and have camera calibration
220  // priors. The returned list is ordered such that most suitable images are
221  // in the front.
222  std::vector<image_t> FindFirstInitialImage(const Options& options) const;
223 
224  // For a given first seed image, find other images that are connected to the
225  // first image. Suitable second images have a large number of
226  // correspondences to the first image and have camera calibration priors.
227  // The returned list is ordered such that most suitable images are in the
228  // front.
229  std::vector<image_t> FindSecondInitialImage(const Options& options,
230  const image_t image_id1) const;
231 
232  // Find local bundle for given image in the reconstruction. The local bundle
233  // is defined as the images that are most connected, i.e. maximum number of
234  // shared 3D points, to the given image.
235  std::vector<image_t> FindLocalBundle(const Options& options,
236  const image_t image_id) const;
237 
238  // Register / De-register image in current reconstruction and update
239  // the number of shared images between all reconstructions.
240  void RegisterImageEvent(const image_t image_id);
241  void DeRegisterImageEvent(const image_t image_id);
242 
243  bool EstimateInitialTwoViewGeometry(const Options& options,
244  const image_t image_id1,
245  const image_t image_id2);
246 
247  // Class that holds all necessary data from database in memory.
248  const DatabaseCache* database_cache_;
249 
250  // Class that holds data of the reconstruction.
251  Reconstruction* reconstruction_;
252 
253  // Class that is responsible for incremental triangulation.
254  std::unique_ptr<IncrementalTriangulator> triangulator_;
255 
256  // Number of images that are registered in at least on reconstruction.
257  size_t num_total_reg_images_;
258 
259  // Number of shared images between current reconstruction and all other
260  // previous reconstructions.
261  size_t num_shared_reg_images_;
262 
263  // Estimated two-view geometry of last call to `FindFirstInitialImage`,
264  // used as a cache for a subsequent call to `RegisterInitialImagePair`.
265  image_pair_t prev_init_image_pair_id_;
266  TwoViewGeometry prev_init_two_view_geometry_;
267 
268  // Images and image pairs that have been used for initialization. Each image
269  // and image pair is only tried once for initialization.
270  std::unordered_map<image_t, size_t> init_num_reg_trials_;
271  std::unordered_set<image_pair_t> init_image_pairs_;
272 
273  // The number of registered images per camera. This information is used
274  // to avoid duplicate refinement of camera parameters and degradation of
275  // already refined camera parameters in local bundle adjustment when
276  // multiple images share intrinsics.
277  std::unordered_map<camera_t, size_t> num_reg_images_per_camera_;
278 
279  // The number of reconstructions in which images are registered.
280  std::unordered_map<image_t, size_t> num_registrations_;
281 
282  // Images that have been filtered in current reconstruction.
283  std::unordered_set<image_t> filtered_images_;
284 
285  // Number of trials to register image in current reconstruction. Used to set
286  // an upper bound to the number of trials to register an image.
287  std::unordered_map<image_t, size_t> num_reg_trials_;
288 
289  // Images that were registered before beginning the reconstruction.
290  // This image list will be non-empty, if the reconstruction is continued
291  // from an existing reconstruction.
292  std::unordered_set<image_t> existing_image_ids_;
293 };
294 
295 } // namespace colmap
LocalBundleAdjustmentReport AdjustLocalBundle(const Options &options, const BundleAdjustmentOptions &ba_options, const IncrementalTriangulator::Options &tri_options, const image_t image_id, const std::unordered_set< point3D_t > &point3D_ids)
bool FindInitialImagePair(const Options &options, image_t *image_id1, image_t *image_id2)
void EndReconstruction(const bool discard)
size_t MergeTracks(const IncrementalTriangulator::Options &tri_options)
void BeginReconstruction(Reconstruction *reconstruction)
bool RegisterNextImage(const Options &options, const image_t image_id)
const std::unordered_set< point3D_t > & GetModifiedPoints3D()
bool RegisterInitialImagePair(const Options &options, const image_t image_id1, const image_t image_id2)
size_t Retriangulate(const IncrementalTriangulator::Options &tri_options)
bool AdjustGlobalBundle(const Options &options, const BundleAdjustmentOptions &ba_options)
size_t FilterImages(const Options &options)
std::vector< image_t > FindNextImages(const Options &options)
size_t TriangulateImage(const IncrementalTriangulator::Options &tri_options, const image_t image_id)
const Reconstruction & GetReconstruction() const
size_t CompleteTracks(const IncrementalTriangulator::Options &tri_options)
IncrementalMapper(const DatabaseCache *database_cache)
size_t FilterPoints(const Options &options)
uint64_t image_pair_t
Definition: types.h:64
uint32_t image_t
Definition: types.h:61
ImageSelectionMethod image_selection_method