1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31
32 #include "util/option_manager.h"
33
34 #include <boost/filesystem/operations.hpp>
35 #include <boost/property_tree/ini_parser.hpp>
36
37 #include "base/image_reader.h"
38 #include "controllers/incremental_mapper.h"
39 #include "feature/extraction.h"
40 #include "feature/matching.h"
41 #include "feature/sift.h"
42 #include "mvs/fusion.h"
43 #include "mvs/meshing.h"
44 #include "mvs/patch_match.h"
45 #include "optim/bundle_adjustment.h"
46 #include "ui/render_options.h"
47 #include "util/misc.h"
48 #include "util/random.h"
49 #include "util/version.h"
50
51 namespace config = boost::program_options;
52
53 namespace colmap {
54
OptionManager(bool add_project_options)55 OptionManager::OptionManager(bool add_project_options) {
56 project_path.reset(new std::string());
57 database_path.reset(new std::string());
58 image_path.reset(new std::string());
59
60 image_reader.reset(new ImageReaderOptions());
61 sift_extraction.reset(new SiftExtractionOptions());
62 sift_matching.reset(new SiftMatchingOptions());
63 exhaustive_matching.reset(new ExhaustiveMatchingOptions());
64 sequential_matching.reset(new SequentialMatchingOptions());
65 vocab_tree_matching.reset(new VocabTreeMatchingOptions());
66 spatial_matching.reset(new SpatialMatchingOptions());
67 transitive_matching.reset(new TransitiveMatchingOptions());
68 image_pairs_matching.reset(new ImagePairsMatchingOptions());
69 bundle_adjustment.reset(new BundleAdjustmentOptions());
70 mapper.reset(new IncrementalMapperOptions());
71 patch_match_stereo.reset(new mvs::PatchMatchOptions());
72 stereo_fusion.reset(new mvs::StereoFusionOptions());
73 poisson_meshing.reset(new mvs::PoissonMeshingOptions());
74 delaunay_meshing.reset(new mvs::DelaunayMeshingOptions());
75 render.reset(new RenderOptions());
76
77 Reset();
78
79 desc_->add_options()("help,h", "");
80
81 AddRandomOptions();
82 AddLogOptions();
83
84 if (add_project_options) {
85 desc_->add_options()("project_path", config::value<std::string>());
86 }
87 }
88
ModifyForIndividualData()89 void OptionManager::ModifyForIndividualData() {
90 mapper->min_focal_length_ratio = 0.1;
91 mapper->max_focal_length_ratio = 10;
92 mapper->max_extra_param = std::numeric_limits<double>::max();
93 }
94
ModifyForVideoData()95 void OptionManager::ModifyForVideoData() {
96 const bool kResetPaths = false;
97 ResetOptions(kResetPaths);
98 mapper->mapper.init_min_tri_angle /= 2;
99 mapper->ba_global_images_ratio = 1.4;
100 mapper->ba_global_points_ratio = 1.4;
101 mapper->min_focal_length_ratio = 0.1;
102 mapper->max_focal_length_ratio = 10;
103 mapper->max_extra_param = std::numeric_limits<double>::max();
104 stereo_fusion->min_num_pixels = 15;
105 }
106
ModifyForInternetData()107 void OptionManager::ModifyForInternetData() {
108 stereo_fusion->min_num_pixels = 10;
109 }
110
ModifyForLowQuality()111 void OptionManager::ModifyForLowQuality() {
112 sift_extraction->max_image_size = 1000;
113 sequential_matching->loop_detection_num_images /= 2;
114 vocab_tree_matching->num_images /= 2;
115 mapper->ba_local_max_num_iterations /= 2;
116 mapper->ba_global_max_num_iterations /= 2;
117 mapper->ba_global_images_ratio *= 1.2;
118 mapper->ba_global_points_ratio *= 1.2;
119 mapper->ba_global_max_refinements = 2;
120 patch_match_stereo->max_image_size = 1000;
121 patch_match_stereo->window_radius = 4;
122 patch_match_stereo->window_step = 2;
123 patch_match_stereo->num_samples /= 2;
124 patch_match_stereo->num_iterations = 3;
125 patch_match_stereo->geom_consistency = false;
126 stereo_fusion->check_num_images /= 2;
127 stereo_fusion->max_image_size = 1000;
128 }
129
ModifyForMediumQuality()130 void OptionManager::ModifyForMediumQuality() {
131 sift_extraction->max_image_size = 1600;
132 sequential_matching->loop_detection_num_images /= 1.5;
133 vocab_tree_matching->num_images /= 1.5;
134 mapper->ba_local_max_num_iterations /= 1.5;
135 mapper->ba_global_max_num_iterations /= 1.5;
136 mapper->ba_global_images_ratio *= 1.1;
137 mapper->ba_global_points_ratio *= 1.1;
138 mapper->ba_global_max_refinements = 2;
139 patch_match_stereo->max_image_size = 1600;
140 patch_match_stereo->window_radius = 4;
141 patch_match_stereo->window_step = 2;
142 patch_match_stereo->num_samples /= 1.5;
143 patch_match_stereo->num_iterations = 5;
144 patch_match_stereo->geom_consistency = false;
145 stereo_fusion->check_num_images /= 1.5;
146 stereo_fusion->max_image_size = 1600;
147 }
148
ModifyForHighQuality()149 void OptionManager::ModifyForHighQuality() {
150 sift_extraction->estimate_affine_shape = true;
151 sift_extraction->max_image_size = 2400;
152 sift_matching->guided_matching = true;
153 mapper->ba_local_max_num_iterations = 30;
154 mapper->ba_local_max_refinements = 3;
155 mapper->ba_global_max_num_iterations = 75;
156 patch_match_stereo->max_image_size = 2400;
157 stereo_fusion->max_image_size = 2400;
158 }
159
ModifyForExtremeQuality()160 void OptionManager::ModifyForExtremeQuality() {
161 // Most of the options are set to extreme quality by default.
162 sift_extraction->estimate_affine_shape = true;
163 sift_extraction->domain_size_pooling = true;
164 sift_matching->guided_matching = true;
165 mapper->ba_local_max_num_iterations = 40;
166 mapper->ba_local_max_refinements = 3;
167 mapper->ba_global_max_num_iterations = 100;
168 }
169
AddAllOptions()170 void OptionManager::AddAllOptions() {
171 AddLogOptions();
172 AddRandomOptions();
173 AddDatabaseOptions();
174 AddImageOptions();
175 AddExtractionOptions();
176 AddMatchingOptions();
177 AddExhaustiveMatchingOptions();
178 AddSequentialMatchingOptions();
179 AddVocabTreeMatchingOptions();
180 AddSpatialMatchingOptions();
181 AddTransitiveMatchingOptions();
182 AddImagePairsMatchingOptions();
183 AddBundleAdjustmentOptions();
184 AddMapperOptions();
185 AddPatchMatchStereoOptions();
186 AddStereoFusionOptions();
187 AddPoissonMeshingOptions();
188 AddDelaunayMeshingOptions();
189 AddRenderOptions();
190 }
191
AddLogOptions()192 void OptionManager::AddLogOptions() {
193 if (added_log_options_) {
194 return;
195 }
196 added_log_options_ = true;
197
198 AddAndRegisterDefaultOption("log_to_stderr", &FLAGS_logtostderr);
199 AddAndRegisterDefaultOption("log_level", &FLAGS_v);
200 }
201
AddRandomOptions()202 void OptionManager::AddRandomOptions() {
203 if (added_random_options_) {
204 return;
205 }
206 added_random_options_ = true;
207
208 AddAndRegisterDefaultOption("random_seed", &kDefaultPRNGSeed);
209 }
210
AddDatabaseOptions()211 void OptionManager::AddDatabaseOptions() {
212 if (added_database_options_) {
213 return;
214 }
215 added_database_options_ = true;
216
217 AddAndRegisterRequiredOption("database_path", database_path.get());
218 }
219
AddImageOptions()220 void OptionManager::AddImageOptions() {
221 if (added_image_options_) {
222 return;
223 }
224 added_image_options_ = true;
225
226 AddAndRegisterRequiredOption("image_path", image_path.get());
227 }
228
AddExtractionOptions()229 void OptionManager::AddExtractionOptions() {
230 if (added_extraction_options_) {
231 return;
232 }
233 added_extraction_options_ = true;
234
235 AddAndRegisterDefaultOption("ImageReader.mask_path",
236 &image_reader->mask_path);
237 AddAndRegisterDefaultOption("ImageReader.camera_model",
238 &image_reader->camera_model);
239 AddAndRegisterDefaultOption("ImageReader.single_camera",
240 &image_reader->single_camera);
241 AddAndRegisterDefaultOption("ImageReader.single_camera_per_folder",
242 &image_reader->single_camera_per_folder);
243 AddAndRegisterDefaultOption("ImageReader.existing_camera_id",
244 &image_reader->existing_camera_id);
245 AddAndRegisterDefaultOption("ImageReader.camera_params",
246 &image_reader->camera_params);
247 AddAndRegisterDefaultOption("ImageReader.default_focal_length_factor",
248 &image_reader->default_focal_length_factor);
249 AddAndRegisterDefaultOption("ImageReader.camera_mask_path",
250 &image_reader->camera_mask_path);
251
252 AddAndRegisterDefaultOption("SiftExtraction.num_threads",
253 &sift_extraction->num_threads);
254 AddAndRegisterDefaultOption("SiftExtraction.use_gpu",
255 &sift_extraction->use_gpu);
256 AddAndRegisterDefaultOption("SiftExtraction.gpu_index",
257 &sift_extraction->gpu_index);
258 AddAndRegisterDefaultOption("SiftExtraction.max_image_size",
259 &sift_extraction->max_image_size);
260 AddAndRegisterDefaultOption("SiftExtraction.max_num_features",
261 &sift_extraction->max_num_features);
262 AddAndRegisterDefaultOption("SiftExtraction.first_octave",
263 &sift_extraction->first_octave);
264 AddAndRegisterDefaultOption("SiftExtraction.num_octaves",
265 &sift_extraction->num_octaves);
266 AddAndRegisterDefaultOption("SiftExtraction.octave_resolution",
267 &sift_extraction->octave_resolution);
268 AddAndRegisterDefaultOption("SiftExtraction.peak_threshold",
269 &sift_extraction->peak_threshold);
270 AddAndRegisterDefaultOption("SiftExtraction.edge_threshold",
271 &sift_extraction->edge_threshold);
272 AddAndRegisterDefaultOption("SiftExtraction.estimate_affine_shape",
273 &sift_extraction->estimate_affine_shape);
274 AddAndRegisterDefaultOption("SiftExtraction.max_num_orientations",
275 &sift_extraction->max_num_orientations);
276 AddAndRegisterDefaultOption("SiftExtraction.upright",
277 &sift_extraction->upright);
278 AddAndRegisterDefaultOption("SiftExtraction.domain_size_pooling",
279 &sift_extraction->domain_size_pooling);
280 AddAndRegisterDefaultOption("SiftExtraction.dsp_min_scale",
281 &sift_extraction->dsp_min_scale);
282 AddAndRegisterDefaultOption("SiftExtraction.dsp_max_scale",
283 &sift_extraction->dsp_max_scale);
284 AddAndRegisterDefaultOption("SiftExtraction.dsp_num_scales",
285 &sift_extraction->dsp_num_scales);
286 }
287
AddMatchingOptions()288 void OptionManager::AddMatchingOptions() {
289 if (added_match_options_) {
290 return;
291 }
292 added_match_options_ = true;
293
294 AddAndRegisterDefaultOption("SiftMatching.num_threads",
295 &sift_matching->num_threads);
296 AddAndRegisterDefaultOption("SiftMatching.use_gpu", &sift_matching->use_gpu);
297 AddAndRegisterDefaultOption("SiftMatching.gpu_index",
298 &sift_matching->gpu_index);
299 AddAndRegisterDefaultOption("SiftMatching.max_ratio",
300 &sift_matching->max_ratio);
301 AddAndRegisterDefaultOption("SiftMatching.max_distance",
302 &sift_matching->max_distance);
303 AddAndRegisterDefaultOption("SiftMatching.cross_check",
304 &sift_matching->cross_check);
305 AddAndRegisterDefaultOption("SiftMatching.max_error",
306 &sift_matching->max_error);
307 AddAndRegisterDefaultOption("SiftMatching.max_num_matches",
308 &sift_matching->max_num_matches);
309 AddAndRegisterDefaultOption("SiftMatching.confidence",
310 &sift_matching->confidence);
311 AddAndRegisterDefaultOption("SiftMatching.max_num_trials",
312 &sift_matching->max_num_trials);
313 AddAndRegisterDefaultOption("SiftMatching.min_inlier_ratio",
314 &sift_matching->min_inlier_ratio);
315 AddAndRegisterDefaultOption("SiftMatching.min_num_inliers",
316 &sift_matching->min_num_inliers);
317 AddAndRegisterDefaultOption("SiftMatching.multiple_models",
318 &sift_matching->multiple_models);
319 AddAndRegisterDefaultOption("SiftMatching.guided_matching",
320 &sift_matching->guided_matching);
321 }
322
AddExhaustiveMatchingOptions()323 void OptionManager::AddExhaustiveMatchingOptions() {
324 if (added_exhaustive_match_options_) {
325 return;
326 }
327 added_exhaustive_match_options_ = true;
328
329 AddMatchingOptions();
330
331 AddAndRegisterDefaultOption("ExhaustiveMatching.block_size",
332 &exhaustive_matching->block_size);
333 }
334
AddSequentialMatchingOptions()335 void OptionManager::AddSequentialMatchingOptions() {
336 if (added_sequential_match_options_) {
337 return;
338 }
339 added_sequential_match_options_ = true;
340
341 AddMatchingOptions();
342
343 AddAndRegisterDefaultOption("SequentialMatching.overlap",
344 &sequential_matching->overlap);
345 AddAndRegisterDefaultOption("SequentialMatching.quadratic_overlap",
346 &sequential_matching->quadratic_overlap);
347 AddAndRegisterDefaultOption("SequentialMatching.loop_detection",
348 &sequential_matching->loop_detection);
349 AddAndRegisterDefaultOption("SequentialMatching.loop_detection_period",
350 &sequential_matching->loop_detection_period);
351 AddAndRegisterDefaultOption("SequentialMatching.loop_detection_num_images",
352 &sequential_matching->loop_detection_num_images);
353 AddAndRegisterDefaultOption(
354 "SequentialMatching.loop_detection_num_nearest_neighbors",
355 &sequential_matching->loop_detection_num_nearest_neighbors);
356 AddAndRegisterDefaultOption("SequentialMatching.loop_detection_num_checks",
357 &sequential_matching->loop_detection_num_checks);
358 AddAndRegisterDefaultOption(
359 "SequentialMatching.loop_detection_num_images_after_verification",
360 &sequential_matching->loop_detection_num_images_after_verification);
361 AddAndRegisterDefaultOption(
362 "SequentialMatching.loop_detection_max_num_features",
363 &sequential_matching->loop_detection_max_num_features);
364 AddAndRegisterDefaultOption("SequentialMatching.vocab_tree_path",
365 &sequential_matching->vocab_tree_path);
366 }
367
AddVocabTreeMatchingOptions()368 void OptionManager::AddVocabTreeMatchingOptions() {
369 if (added_vocab_tree_match_options_) {
370 return;
371 }
372 added_vocab_tree_match_options_ = true;
373
374 AddMatchingOptions();
375
376 AddAndRegisterDefaultOption("VocabTreeMatching.num_images",
377 &vocab_tree_matching->num_images);
378 AddAndRegisterDefaultOption("VocabTreeMatching.num_nearest_neighbors",
379 &vocab_tree_matching->num_nearest_neighbors);
380 AddAndRegisterDefaultOption("VocabTreeMatching.num_checks",
381 &vocab_tree_matching->num_checks);
382 AddAndRegisterDefaultOption(
383 "VocabTreeMatching.num_images_after_verification",
384 &vocab_tree_matching->num_images_after_verification);
385 AddAndRegisterDefaultOption("VocabTreeMatching.max_num_features",
386 &vocab_tree_matching->max_num_features);
387 AddAndRegisterDefaultOption("VocabTreeMatching.vocab_tree_path",
388 &vocab_tree_matching->vocab_tree_path);
389 AddAndRegisterDefaultOption("VocabTreeMatching.match_list_path",
390 &vocab_tree_matching->match_list_path);
391 }
392
AddSpatialMatchingOptions()393 void OptionManager::AddSpatialMatchingOptions() {
394 if (added_spatial_match_options_) {
395 return;
396 }
397 added_spatial_match_options_ = true;
398
399 AddMatchingOptions();
400
401 AddAndRegisterDefaultOption("SpatialMatching.is_gps",
402 &spatial_matching->is_gps);
403 AddAndRegisterDefaultOption("SpatialMatching.ignore_z",
404 &spatial_matching->ignore_z);
405 AddAndRegisterDefaultOption("SpatialMatching.max_num_neighbors",
406 &spatial_matching->max_num_neighbors);
407 AddAndRegisterDefaultOption("SpatialMatching.max_distance",
408 &spatial_matching->max_distance);
409 }
410
AddTransitiveMatchingOptions()411 void OptionManager::AddTransitiveMatchingOptions() {
412 if (added_transitive_match_options_) {
413 return;
414 }
415 added_transitive_match_options_ = true;
416
417 AddMatchingOptions();
418
419 AddAndRegisterDefaultOption("TransitiveMatching.batch_size",
420 &transitive_matching->batch_size);
421 AddAndRegisterDefaultOption("TransitiveMatching.num_iterations",
422 &transitive_matching->num_iterations);
423 }
424
AddImagePairsMatchingOptions()425 void OptionManager::AddImagePairsMatchingOptions() {
426 if (added_image_pairs_match_options_) {
427 return;
428 }
429 added_image_pairs_match_options_ = true;
430
431 AddMatchingOptions();
432
433 AddAndRegisterDefaultOption("ImagePairsMatching.block_size",
434 &image_pairs_matching->block_size);
435 }
436
AddBundleAdjustmentOptions()437 void OptionManager::AddBundleAdjustmentOptions() {
438 if (added_ba_options_) {
439 return;
440 }
441 added_ba_options_ = true;
442
443 AddAndRegisterDefaultOption(
444 "BundleAdjustment.max_num_iterations",
445 &bundle_adjustment->solver_options.max_num_iterations);
446 AddAndRegisterDefaultOption(
447 "BundleAdjustment.max_linear_solver_iterations",
448 &bundle_adjustment->solver_options.max_linear_solver_iterations);
449 AddAndRegisterDefaultOption(
450 "BundleAdjustment.function_tolerance",
451 &bundle_adjustment->solver_options.function_tolerance);
452 AddAndRegisterDefaultOption(
453 "BundleAdjustment.gradient_tolerance",
454 &bundle_adjustment->solver_options.gradient_tolerance);
455 AddAndRegisterDefaultOption(
456 "BundleAdjustment.parameter_tolerance",
457 &bundle_adjustment->solver_options.parameter_tolerance);
458 AddAndRegisterDefaultOption("BundleAdjustment.refine_focal_length",
459 &bundle_adjustment->refine_focal_length);
460 AddAndRegisterDefaultOption("BundleAdjustment.refine_principal_point",
461 &bundle_adjustment->refine_principal_point);
462 AddAndRegisterDefaultOption("BundleAdjustment.refine_extra_params",
463 &bundle_adjustment->refine_extra_params);
464 AddAndRegisterDefaultOption("BundleAdjustment.refine_extrinsics",
465 &bundle_adjustment->refine_extrinsics);
466 }
467
AddMapperOptions()468 void OptionManager::AddMapperOptions() {
469 if (added_mapper_options_) {
470 return;
471 }
472 added_mapper_options_ = true;
473
474 AddAndRegisterDefaultOption("Mapper.min_num_matches",
475 &mapper->min_num_matches);
476 AddAndRegisterDefaultOption("Mapper.ignore_watermarks",
477 &mapper->ignore_watermarks);
478 AddAndRegisterDefaultOption("Mapper.multiple_models",
479 &mapper->multiple_models);
480 AddAndRegisterDefaultOption("Mapper.max_num_models", &mapper->max_num_models);
481 AddAndRegisterDefaultOption("Mapper.max_model_overlap",
482 &mapper->max_model_overlap);
483 AddAndRegisterDefaultOption("Mapper.min_model_size", &mapper->min_model_size);
484 AddAndRegisterDefaultOption("Mapper.init_image_id1", &mapper->init_image_id1);
485 AddAndRegisterDefaultOption("Mapper.init_image_id2", &mapper->init_image_id2);
486 AddAndRegisterDefaultOption("Mapper.init_num_trials",
487 &mapper->init_num_trials);
488 AddAndRegisterDefaultOption("Mapper.extract_colors", &mapper->extract_colors);
489 AddAndRegisterDefaultOption("Mapper.num_threads", &mapper->num_threads);
490 AddAndRegisterDefaultOption("Mapper.min_focal_length_ratio",
491 &mapper->min_focal_length_ratio);
492 AddAndRegisterDefaultOption("Mapper.max_focal_length_ratio",
493 &mapper->max_focal_length_ratio);
494 AddAndRegisterDefaultOption("Mapper.max_extra_param",
495 &mapper->max_extra_param);
496 AddAndRegisterDefaultOption("Mapper.ba_refine_focal_length",
497 &mapper->ba_refine_focal_length);
498 AddAndRegisterDefaultOption("Mapper.ba_refine_principal_point",
499 &mapper->ba_refine_principal_point);
500 AddAndRegisterDefaultOption("Mapper.ba_refine_extra_params",
501 &mapper->ba_refine_extra_params);
502 AddAndRegisterDefaultOption(
503 "Mapper.ba_min_num_residuals_for_multi_threading",
504 &mapper->ba_min_num_residuals_for_multi_threading);
505 AddAndRegisterDefaultOption("Mapper.ba_local_num_images",
506 &mapper->ba_local_num_images);
507 AddAndRegisterDefaultOption("Mapper.ba_local_max_num_iterations",
508 &mapper->ba_local_max_num_iterations);
509 AddAndRegisterDefaultOption("Mapper.ba_global_use_pba",
510 &mapper->ba_global_use_pba);
511 AddAndRegisterDefaultOption("Mapper.ba_global_pba_gpu_index",
512 &mapper->ba_global_pba_gpu_index);
513 AddAndRegisterDefaultOption("Mapper.ba_global_images_ratio",
514 &mapper->ba_global_images_ratio);
515 AddAndRegisterDefaultOption("Mapper.ba_global_points_ratio",
516 &mapper->ba_global_points_ratio);
517 AddAndRegisterDefaultOption("Mapper.ba_global_images_freq",
518 &mapper->ba_global_images_freq);
519 AddAndRegisterDefaultOption("Mapper.ba_global_points_freq",
520 &mapper->ba_global_points_freq);
521 AddAndRegisterDefaultOption("Mapper.ba_global_max_num_iterations",
522 &mapper->ba_global_max_num_iterations);
523 AddAndRegisterDefaultOption("Mapper.ba_global_max_refinements",
524 &mapper->ba_global_max_refinements);
525 AddAndRegisterDefaultOption("Mapper.ba_global_max_refinement_change",
526 &mapper->ba_global_max_refinement_change);
527 AddAndRegisterDefaultOption("Mapper.ba_local_max_refinements",
528 &mapper->ba_local_max_refinements);
529 AddAndRegisterDefaultOption("Mapper.ba_local_max_refinement_change",
530 &mapper->ba_local_max_refinement_change);
531 AddAndRegisterDefaultOption("Mapper.snapshot_path", &mapper->snapshot_path);
532 AddAndRegisterDefaultOption("Mapper.snapshot_images_freq",
533 &mapper->snapshot_images_freq);
534 AddAndRegisterDefaultOption("Mapper.fix_existing_images",
535 &mapper->fix_existing_images);
536
537 // IncrementalMapper.
538 AddAndRegisterDefaultOption("Mapper.init_min_num_inliers",
539 &mapper->mapper.init_min_num_inliers);
540 AddAndRegisterDefaultOption("Mapper.init_max_error",
541 &mapper->mapper.init_max_error);
542 AddAndRegisterDefaultOption("Mapper.init_max_forward_motion",
543 &mapper->mapper.init_max_forward_motion);
544 AddAndRegisterDefaultOption("Mapper.init_min_tri_angle",
545 &mapper->mapper.init_min_tri_angle);
546 AddAndRegisterDefaultOption("Mapper.init_max_reg_trials",
547 &mapper->mapper.init_max_reg_trials);
548 AddAndRegisterDefaultOption("Mapper.abs_pose_max_error",
549 &mapper->mapper.abs_pose_max_error);
550 AddAndRegisterDefaultOption("Mapper.abs_pose_min_num_inliers",
551 &mapper->mapper.abs_pose_min_num_inliers);
552 AddAndRegisterDefaultOption("Mapper.abs_pose_min_inlier_ratio",
553 &mapper->mapper.abs_pose_min_inlier_ratio);
554 AddAndRegisterDefaultOption("Mapper.filter_max_reproj_error",
555 &mapper->mapper.filter_max_reproj_error);
556 AddAndRegisterDefaultOption("Mapper.filter_min_tri_angle",
557 &mapper->mapper.filter_min_tri_angle);
558 AddAndRegisterDefaultOption("Mapper.max_reg_trials",
559 &mapper->mapper.max_reg_trials);
560 AddAndRegisterDefaultOption("Mapper.local_ba_min_tri_angle",
561 &mapper->mapper.local_ba_min_tri_angle);
562
563 // IncrementalTriangulator.
564 AddAndRegisterDefaultOption("Mapper.tri_max_transitivity",
565 &mapper->triangulation.max_transitivity);
566 AddAndRegisterDefaultOption("Mapper.tri_create_max_angle_error",
567 &mapper->triangulation.create_max_angle_error);
568 AddAndRegisterDefaultOption("Mapper.tri_continue_max_angle_error",
569 &mapper->triangulation.continue_max_angle_error);
570 AddAndRegisterDefaultOption("Mapper.tri_merge_max_reproj_error",
571 &mapper->triangulation.merge_max_reproj_error);
572 AddAndRegisterDefaultOption("Mapper.tri_complete_max_reproj_error",
573 &mapper->triangulation.complete_max_reproj_error);
574 AddAndRegisterDefaultOption("Mapper.tri_complete_max_transitivity",
575 &mapper->triangulation.complete_max_transitivity);
576 AddAndRegisterDefaultOption("Mapper.tri_re_max_angle_error",
577 &mapper->triangulation.re_max_angle_error);
578 AddAndRegisterDefaultOption("Mapper.tri_re_min_ratio",
579 &mapper->triangulation.re_min_ratio);
580 AddAndRegisterDefaultOption("Mapper.tri_re_max_trials",
581 &mapper->triangulation.re_max_trials);
582 AddAndRegisterDefaultOption("Mapper.tri_min_angle",
583 &mapper->triangulation.min_angle);
584 AddAndRegisterDefaultOption("Mapper.tri_ignore_two_view_tracks",
585 &mapper->triangulation.ignore_two_view_tracks);
586 }
587
AddPatchMatchStereoOptions()588 void OptionManager::AddPatchMatchStereoOptions() {
589 if (added_patch_match_stereo_options_) {
590 return;
591 }
592 added_patch_match_stereo_options_ = true;
593
594 AddAndRegisterDefaultOption("PatchMatchStereo.max_image_size",
595 &patch_match_stereo->max_image_size);
596 AddAndRegisterDefaultOption("PatchMatchStereo.gpu_index",
597 &patch_match_stereo->gpu_index);
598 AddAndRegisterDefaultOption("PatchMatchStereo.depth_min",
599 &patch_match_stereo->depth_min);
600 AddAndRegisterDefaultOption("PatchMatchStereo.depth_max",
601 &patch_match_stereo->depth_max);
602 AddAndRegisterDefaultOption("PatchMatchStereo.window_radius",
603 &patch_match_stereo->window_radius);
604 AddAndRegisterDefaultOption("PatchMatchStereo.window_step",
605 &patch_match_stereo->window_step);
606 AddAndRegisterDefaultOption("PatchMatchStereo.sigma_spatial",
607 &patch_match_stereo->sigma_spatial);
608 AddAndRegisterDefaultOption("PatchMatchStereo.sigma_color",
609 &patch_match_stereo->sigma_color);
610 AddAndRegisterDefaultOption("PatchMatchStereo.num_samples",
611 &patch_match_stereo->num_samples);
612 AddAndRegisterDefaultOption("PatchMatchStereo.ncc_sigma",
613 &patch_match_stereo->ncc_sigma);
614 AddAndRegisterDefaultOption("PatchMatchStereo.min_triangulation_angle",
615 &patch_match_stereo->min_triangulation_angle);
616 AddAndRegisterDefaultOption("PatchMatchStereo.incident_angle_sigma",
617 &patch_match_stereo->incident_angle_sigma);
618 AddAndRegisterDefaultOption("PatchMatchStereo.num_iterations",
619 &patch_match_stereo->num_iterations);
620 AddAndRegisterDefaultOption("PatchMatchStereo.geom_consistency",
621 &patch_match_stereo->geom_consistency);
622 AddAndRegisterDefaultOption(
623 "PatchMatchStereo.geom_consistency_regularizer",
624 &patch_match_stereo->geom_consistency_regularizer);
625 AddAndRegisterDefaultOption("PatchMatchStereo.geom_consistency_max_cost",
626 &patch_match_stereo->geom_consistency_max_cost);
627 AddAndRegisterDefaultOption("PatchMatchStereo.filter",
628 &patch_match_stereo->filter);
629 AddAndRegisterDefaultOption("PatchMatchStereo.filter_min_ncc",
630 &patch_match_stereo->filter_min_ncc);
631 AddAndRegisterDefaultOption(
632 "PatchMatchStereo.filter_min_triangulation_angle",
633 &patch_match_stereo->filter_min_triangulation_angle);
634 AddAndRegisterDefaultOption("PatchMatchStereo.filter_min_num_consistent",
635 &patch_match_stereo->filter_min_num_consistent);
636 AddAndRegisterDefaultOption(
637 "PatchMatchStereo.filter_geom_consistency_max_cost",
638 &patch_match_stereo->filter_geom_consistency_max_cost);
639 AddAndRegisterDefaultOption("PatchMatchStereo.cache_size",
640 &patch_match_stereo->cache_size);
641 AddAndRegisterDefaultOption("PatchMatchStereo.write_consistency_graph",
642 &patch_match_stereo->write_consistency_graph);
643 }
644
AddStereoFusionOptions()645 void OptionManager::AddStereoFusionOptions() {
646 if (added_stereo_fusion_options_) {
647 return;
648 }
649 added_stereo_fusion_options_ = true;
650
651 AddAndRegisterDefaultOption("StereoFusion.max_image_size",
652 &stereo_fusion->max_image_size);
653 AddAndRegisterDefaultOption("StereoFusion.min_num_pixels",
654 &stereo_fusion->min_num_pixels);
655 AddAndRegisterDefaultOption("StereoFusion.max_num_pixels",
656 &stereo_fusion->max_num_pixels);
657 AddAndRegisterDefaultOption("StereoFusion.max_traversal_depth",
658 &stereo_fusion->max_traversal_depth);
659 AddAndRegisterDefaultOption("StereoFusion.max_reproj_error",
660 &stereo_fusion->max_reproj_error);
661 AddAndRegisterDefaultOption("StereoFusion.max_depth_error",
662 &stereo_fusion->max_depth_error);
663 AddAndRegisterDefaultOption("StereoFusion.max_normal_error",
664 &stereo_fusion->max_normal_error);
665 AddAndRegisterDefaultOption("StereoFusion.check_num_images",
666 &stereo_fusion->check_num_images);
667 AddAndRegisterDefaultOption("StereoFusion.cache_size",
668 &stereo_fusion->cache_size);
669 }
670
AddPoissonMeshingOptions()671 void OptionManager::AddPoissonMeshingOptions() {
672 if (added_poisson_meshing_options_) {
673 return;
674 }
675 added_poisson_meshing_options_ = true;
676
677 AddAndRegisterDefaultOption("PoissonMeshing.point_weight",
678 &poisson_meshing->point_weight);
679 AddAndRegisterDefaultOption("PoissonMeshing.depth", &poisson_meshing->depth);
680 AddAndRegisterDefaultOption("PoissonMeshing.color", &poisson_meshing->color);
681 AddAndRegisterDefaultOption("PoissonMeshing.trim", &poisson_meshing->trim);
682 AddAndRegisterDefaultOption("PoissonMeshing.num_threads",
683 &poisson_meshing->num_threads);
684 }
685
AddDelaunayMeshingOptions()686 void OptionManager::AddDelaunayMeshingOptions() {
687 if (added_delaunay_meshing_options_) {
688 return;
689 }
690 added_delaunay_meshing_options_ = true;
691
692 AddAndRegisterDefaultOption("DelaunayMeshing.max_proj_dist",
693 &delaunay_meshing->max_proj_dist);
694 AddAndRegisterDefaultOption("DelaunayMeshing.max_depth_dist",
695 &delaunay_meshing->max_depth_dist);
696 AddAndRegisterDefaultOption("DelaunayMeshing.distance_sigma_factor",
697 &delaunay_meshing->distance_sigma_factor);
698 AddAndRegisterDefaultOption("DelaunayMeshing.quality_regularization",
699 &delaunay_meshing->quality_regularization);
700 AddAndRegisterDefaultOption("DelaunayMeshing.max_side_length_factor",
701 &delaunay_meshing->max_side_length_factor);
702 AddAndRegisterDefaultOption("DelaunayMeshing.max_side_length_percentile",
703 &delaunay_meshing->max_side_length_percentile);
704 AddAndRegisterDefaultOption("DelaunayMeshing.num_threads",
705 &delaunay_meshing->num_threads);
706 }
707
AddRenderOptions()708 void OptionManager::AddRenderOptions() {
709 if (added_render_options_) {
710 return;
711 }
712 added_render_options_ = true;
713
714 AddAndRegisterDefaultOption("Render.min_track_len", &render->min_track_len);
715 AddAndRegisterDefaultOption("Render.max_error", &render->max_error);
716 AddAndRegisterDefaultOption("Render.refresh_rate", &render->refresh_rate);
717 AddAndRegisterDefaultOption("Render.adapt_refresh_rate",
718 &render->adapt_refresh_rate);
719 AddAndRegisterDefaultOption("Render.image_connections",
720 &render->image_connections);
721 AddAndRegisterDefaultOption("Render.projection_type",
722 &render->projection_type);
723 }
724
Reset()725 void OptionManager::Reset() {
726 FLAGS_logtostderr = false;
727 FLAGS_v = 2;
728
729 const bool kResetPaths = true;
730 ResetOptions(kResetPaths);
731
732 desc_.reset(new boost::program_options::options_description());
733
734 options_bool_.clear();
735 options_int_.clear();
736 options_double_.clear();
737 options_string_.clear();
738
739 added_log_options_ = false;
740 added_random_options_ = false;
741 added_database_options_ = false;
742 added_image_options_ = false;
743 added_extraction_options_ = false;
744 added_match_options_ = false;
745 added_exhaustive_match_options_ = false;
746 added_sequential_match_options_ = false;
747 added_vocab_tree_match_options_ = false;
748 added_spatial_match_options_ = false;
749 added_transitive_match_options_ = false;
750 added_image_pairs_match_options_ = false;
751 added_ba_options_ = false;
752 added_mapper_options_ = false;
753 added_patch_match_stereo_options_ = false;
754 added_stereo_fusion_options_ = false;
755 added_poisson_meshing_options_ = false;
756 added_delaunay_meshing_options_ = false;
757 added_render_options_ = false;
758 }
759
ResetOptions(const bool reset_paths)760 void OptionManager::ResetOptions(const bool reset_paths) {
761 if (reset_paths) {
762 *project_path = "";
763 *database_path = "";
764 *image_path = "";
765 }
766 *image_reader = ImageReaderOptions();
767 *sift_extraction = SiftExtractionOptions();
768 *sift_matching = SiftMatchingOptions();
769 *exhaustive_matching = ExhaustiveMatchingOptions();
770 *sequential_matching = SequentialMatchingOptions();
771 *vocab_tree_matching = VocabTreeMatchingOptions();
772 *spatial_matching = SpatialMatchingOptions();
773 *transitive_matching = TransitiveMatchingOptions();
774 *image_pairs_matching = ImagePairsMatchingOptions();
775 *bundle_adjustment = BundleAdjustmentOptions();
776 *mapper = IncrementalMapperOptions();
777 *patch_match_stereo = mvs::PatchMatchOptions();
778 *stereo_fusion = mvs::StereoFusionOptions();
779 *poisson_meshing = mvs::PoissonMeshingOptions();
780 *delaunay_meshing = mvs::DelaunayMeshingOptions();
781 *render = RenderOptions();
782 }
783
Check()784 bool OptionManager::Check() {
785 bool success = true;
786
787 if (added_database_options_) {
788 const auto database_parent_path = GetParentDir(*database_path);
789 success = success && CHECK_OPTION_IMPL(!ExistsDir(*database_path)) &&
790 CHECK_OPTION_IMPL(database_parent_path == "" ||
791 ExistsDir(database_parent_path));
792 }
793
794 if (added_image_options_)
795 success = success && CHECK_OPTION_IMPL(ExistsDir(*image_path));
796
797 if (image_reader) success = success && image_reader->Check();
798 if (sift_extraction) success = success && sift_extraction->Check();
799
800 if (sift_matching) success = success && sift_matching->Check();
801 if (exhaustive_matching) success = success && exhaustive_matching->Check();
802 if (sequential_matching) success = success && sequential_matching->Check();
803 if (vocab_tree_matching) success = success && vocab_tree_matching->Check();
804 if (spatial_matching) success = success && spatial_matching->Check();
805 if (transitive_matching) success = success && transitive_matching->Check();
806 if (image_pairs_matching) success = success && image_pairs_matching->Check();
807
808 if (bundle_adjustment) success = success && bundle_adjustment->Check();
809 if (mapper) success = success && mapper->Check();
810
811 if (patch_match_stereo) success = success && patch_match_stereo->Check();
812 if (stereo_fusion) success = success && stereo_fusion->Check();
813 if (poisson_meshing) success = success && poisson_meshing->Check();
814 if (delaunay_meshing) success = success && delaunay_meshing->Check();
815
816 if (render) success = success && render->Check();
817
818 return success;
819 }
820
Parse(const int argc,char ** argv)821 void OptionManager::Parse(const int argc, char** argv) {
822 config::variables_map vmap;
823
824 try {
825 config::store(config::parse_command_line(argc, argv, *desc_), vmap);
826
827 if (vmap.count("help")) {
828 std::cout << StringPrintf("%s (%s)", GetVersionInfo().c_str(),
829 GetBuildInfo().c_str())
830 << std::endl
831 << std::endl;
832 std::cout
833 << "Options can either be specified via command-line or by defining"
834 << std::endl
835 << "them in a .ini project file passed to `--project_path`."
836 << std::endl
837 << std::endl;
838 std::cout << *desc_ << std::endl;
839 exit(EXIT_SUCCESS);
840 }
841
842 if (vmap.count("project_path")) {
843 *project_path = vmap["project_path"].as<std::string>();
844 if (!Read(*project_path)) {
845 exit(EXIT_FAILURE);
846 }
847 } else {
848 vmap.notify();
849 }
850 } catch (std::exception& exc) {
851 std::cerr << "ERROR: Failed to parse options - " << exc.what() << "."
852 << std::endl;
853 exit(EXIT_FAILURE);
854 } catch (...) {
855 std::cerr << "ERROR: Failed to parse options for unknown reason."
856 << std::endl;
857 exit(EXIT_FAILURE);
858 }
859
860 if (!Check()) {
861 std::cerr << "ERROR: Invalid options provided." << std::endl;
862 exit(EXIT_FAILURE);
863 }
864 }
865
Read(const std::string & path)866 bool OptionManager::Read(const std::string& path) {
867 config::variables_map vmap;
868
869 if (!ExistsFile(path)) {
870 std::cout << "ERROR: Configuration file does not exist." << std::endl;
871 return false;
872 }
873
874 try {
875 std::ifstream file(path);
876 CHECK(file.is_open()) << path;
877 config::store(config::parse_config_file(file, *desc_), vmap);
878 vmap.notify();
879 } catch (std::exception& e) {
880 std::cout << "ERROR: Failed to parse options " << e.what() << "."
881 << std::endl;
882 return false;
883 } catch (...) {
884 std::cout << "ERROR: Failed to parse options for unknown reason."
885 << std::endl;
886 return false;
887 }
888
889 return Check();
890 }
891
ReRead(const std::string & path)892 bool OptionManager::ReRead(const std::string& path) {
893 Reset();
894 AddAllOptions();
895 return Read(path);
896 }
897
Write(const std::string & path) const898 void OptionManager::Write(const std::string& path) const {
899 boost::property_tree::ptree pt;
900
901 // First, put all options without a section and then those with a section.
902 // This is necessary as otherwise older Boost versions will write the
903 // options without a section in between other sections and therefore
904 // the errors will be assigned to the wrong section if read later.
905
906 for (const auto& option : options_bool_) {
907 if (!StringContains(option.first, ".")) {
908 pt.put(option.first, *option.second);
909 }
910 }
911
912 for (const auto& option : options_int_) {
913 if (!StringContains(option.first, ".")) {
914 pt.put(option.first, *option.second);
915 }
916 }
917
918 for (const auto& option : options_double_) {
919 if (!StringContains(option.first, ".")) {
920 pt.put(option.first, *option.second);
921 }
922 }
923
924 for (const auto& option : options_string_) {
925 if (!StringContains(option.first, ".")) {
926 pt.put(option.first, *option.second);
927 }
928 }
929
930 for (const auto& option : options_bool_) {
931 if (StringContains(option.first, ".")) {
932 pt.put(option.first, *option.second);
933 }
934 }
935
936 for (const auto& option : options_int_) {
937 if (StringContains(option.first, ".")) {
938 pt.put(option.first, *option.second);
939 }
940 }
941
942 for (const auto& option : options_double_) {
943 if (StringContains(option.first, ".")) {
944 pt.put(option.first, *option.second);
945 }
946 }
947
948 for (const auto& option : options_string_) {
949 if (StringContains(option.first, ".")) {
950 pt.put(option.first, *option.second);
951 }
952 }
953
954 boost::property_tree::write_ini(path, pt);
955 }
956
957 } // namespace colmap
958