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 #ifndef COLMAP_SRC_UTIL_OPTION_MANAGER_H_
33 #define COLMAP_SRC_UTIL_OPTION_MANAGER_H_
34 
35 #include <memory>
36 
37 #include <boost/program_options.hpp>
38 
39 #include "util/logging.h"
40 
41 namespace colmap {
42 
43 struct ImageReaderOptions;
44 struct SiftExtractionOptions;
45 struct SiftMatchingOptions;
46 struct ExhaustiveMatchingOptions;
47 struct SequentialMatchingOptions;
48 struct VocabTreeMatchingOptions;
49 struct SpatialMatchingOptions;
50 struct TransitiveMatchingOptions;
51 struct ImagePairsMatchingOptions;
52 struct BundleAdjustmentOptions;
53 struct IncrementalMapperOptions;
54 struct RenderOptions;
55 
56 namespace mvs {
57 struct PatchMatchOptions;
58 struct StereoFusionOptions;
59 struct PoissonMeshingOptions;
60 struct DelaunayMeshingOptions;
61 }  // namespace mvs
62 
63 class OptionManager {
64  public:
65   OptionManager(bool add_project_options = true);
66 
67   // Create "optimal" set of options for different reconstruction scenarios.
68   // Note that the existing options are modified, so if your parameters are
69   // already low quality, they will be further modified.
70   void ModifyForIndividualData();
71   void ModifyForVideoData();
72   void ModifyForInternetData();
73 
74   // Create "optimal" set of options for different quality settings.
75   // Note that the existing options are modified, so if your parameters are
76   // already low quality, they will be further degraded.
77   void ModifyForLowQuality();
78   void ModifyForMediumQuality();
79   void ModifyForHighQuality();
80   void ModifyForExtremeQuality();
81 
82   void AddAllOptions();
83   void AddLogOptions();
84   void AddRandomOptions();
85   void AddDatabaseOptions();
86   void AddImageOptions();
87   void AddExtractionOptions();
88   void AddMatchingOptions();
89   void AddExhaustiveMatchingOptions();
90   void AddSequentialMatchingOptions();
91   void AddVocabTreeMatchingOptions();
92   void AddSpatialMatchingOptions();
93   void AddTransitiveMatchingOptions();
94   void AddImagePairsMatchingOptions();
95   void AddBundleAdjustmentOptions();
96   void AddMapperOptions();
97   void AddPatchMatchStereoOptions();
98   void AddStereoFusionOptions();
99   void AddPoissonMeshingOptions();
100   void AddDelaunayMeshingOptions();
101   void AddRenderOptions();
102 
103   template <typename T>
104   void AddRequiredOption(const std::string& name, T* option,
105                          const std::string& help_text = "");
106   template <typename T>
107   void AddDefaultOption(const std::string& name, T* option,
108                         const std::string& help_text = "");
109 
110   void Reset();
111   void ResetOptions(const bool reset_paths);
112 
113   bool Check();
114 
115   void Parse(const int argc, char** argv);
116   bool Read(const std::string& path);
117   bool ReRead(const std::string& path);
118   void Write(const std::string& path) const;
119 
120   std::shared_ptr<std::string> project_path;
121   std::shared_ptr<std::string> database_path;
122   std::shared_ptr<std::string> image_path;
123 
124   std::shared_ptr<ImageReaderOptions> image_reader;
125   std::shared_ptr<SiftExtractionOptions> sift_extraction;
126 
127   std::shared_ptr<SiftMatchingOptions> sift_matching;
128   std::shared_ptr<ExhaustiveMatchingOptions> exhaustive_matching;
129   std::shared_ptr<SequentialMatchingOptions> sequential_matching;
130   std::shared_ptr<VocabTreeMatchingOptions> vocab_tree_matching;
131   std::shared_ptr<SpatialMatchingOptions> spatial_matching;
132   std::shared_ptr<TransitiveMatchingOptions> transitive_matching;
133   std::shared_ptr<ImagePairsMatchingOptions> image_pairs_matching;
134 
135   std::shared_ptr<BundleAdjustmentOptions> bundle_adjustment;
136   std::shared_ptr<IncrementalMapperOptions> mapper;
137 
138   std::shared_ptr<mvs::PatchMatchOptions> patch_match_stereo;
139   std::shared_ptr<mvs::StereoFusionOptions> stereo_fusion;
140   std::shared_ptr<mvs::PoissonMeshingOptions> poisson_meshing;
141   std::shared_ptr<mvs::DelaunayMeshingOptions> delaunay_meshing;
142 
143   std::shared_ptr<RenderOptions> render;
144 
145  private:
146   template <typename T>
147   void AddAndRegisterRequiredOption(const std::string& name, T* option,
148                                     const std::string& help_text = "");
149   template <typename T>
150   void AddAndRegisterDefaultOption(const std::string& name, T* option,
151                                    const std::string& help_text = "");
152 
153   template <typename T>
154   void RegisterOption(const std::string& name, const T* option);
155 
156   std::shared_ptr<boost::program_options::options_description> desc_;
157 
158   std::vector<std::pair<std::string, const bool*>> options_bool_;
159   std::vector<std::pair<std::string, const int*>> options_int_;
160   std::vector<std::pair<std::string, const double*>> options_double_;
161   std::vector<std::pair<std::string, const std::string*>> options_string_;
162 
163   bool added_log_options_;
164   bool added_random_options_;
165   bool added_database_options_;
166   bool added_image_options_;
167   bool added_extraction_options_;
168   bool added_match_options_;
169   bool added_exhaustive_match_options_;
170   bool added_sequential_match_options_;
171   bool added_vocab_tree_match_options_;
172   bool added_spatial_match_options_;
173   bool added_transitive_match_options_;
174   bool added_image_pairs_match_options_;
175   bool added_ba_options_;
176   bool added_mapper_options_;
177   bool added_patch_match_stereo_options_;
178   bool added_stereo_fusion_options_;
179   bool added_poisson_meshing_options_;
180   bool added_delaunay_meshing_options_;
181   bool added_render_options_;
182 };
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 // Implementation
186 ////////////////////////////////////////////////////////////////////////////////
187 
188 template <typename T>
AddRequiredOption(const std::string & name,T * option,const std::string & help_text)189 void OptionManager::AddRequiredOption(const std::string& name, T* option,
190                                       const std::string& help_text) {
191   desc_->add_options()(name.c_str(),
192                        boost::program_options::value<T>(option)->required(),
193                        help_text.c_str());
194 }
195 
196 template <typename T>
AddDefaultOption(const std::string & name,T * option,const std::string & help_text)197 void OptionManager::AddDefaultOption(const std::string& name, T* option,
198                                      const std::string& help_text) {
199   desc_->add_options()(
200       name.c_str(),
201       boost::program_options::value<T>(option)->default_value(*option),
202       help_text.c_str());
203 }
204 
205 template <typename T>
AddAndRegisterRequiredOption(const std::string & name,T * option,const std::string & help_text)206 void OptionManager::AddAndRegisterRequiredOption(const std::string& name,
207                                                  T* option,
208                                                  const std::string& help_text) {
209   desc_->add_options()(name.c_str(),
210                        boost::program_options::value<T>(option)->required(),
211                        help_text.c_str());
212   RegisterOption(name, option);
213 }
214 
215 template <typename T>
AddAndRegisterDefaultOption(const std::string & name,T * option,const std::string & help_text)216 void OptionManager::AddAndRegisterDefaultOption(const std::string& name,
217                                                 T* option,
218                                                 const std::string& help_text) {
219   desc_->add_options()(
220       name.c_str(),
221       boost::program_options::value<T>(option)->default_value(*option),
222       help_text.c_str());
223   RegisterOption(name, option);
224 }
225 
226 template <typename T>
RegisterOption(const std::string & name,const T * option)227 void OptionManager::RegisterOption(const std::string& name, const T* option) {
228   if (std::is_same<T, bool>::value) {
229     options_bool_.emplace_back(name, reinterpret_cast<const bool*>(option));
230   } else if (std::is_same<T, int>::value) {
231     options_int_.emplace_back(name, reinterpret_cast<const int*>(option));
232   } else if (std::is_same<T, double>::value) {
233     options_double_.emplace_back(name, reinterpret_cast<const double*>(option));
234   } else if (std::is_same<T, std::string>::value) {
235     options_string_.emplace_back(name,
236                                  reinterpret_cast<const std::string*>(option));
237   } else {
238     LOG(FATAL) << "Unsupported option type";
239   }
240 }
241 
242 }  // namespace colmap
243 
244 #endif  // COLMAP_SRC_UTIL_OPTION_MANAGER_H_
245