ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
feature.cc
Go to the documentation of this file.
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 "exe/feature.h"
33 
34 #include "base/camera_models.h"
35 #include "base/image_reader.h"
36 #include "exe/gui.h"
37 #include "feature/extraction.h"
38 #include "feature/matching.h"
39 #include "util/misc.h"
40 #include "util/opengl_utils.h"
41 #include "util/option_manager.h"
42 
43 namespace colmap {
44 namespace {
45 
46 bool VerifyCameraParams(const std::string& camera_model,
47  const std::string& params) {
48  if (!ExistsCameraModelWithName(camera_model)) {
49  std::cerr << "ERROR: Camera model does not exist" << std::endl;
50  return false;
51  }
52 
53  const std::vector<double> camera_params = CSVToVector<double>(params);
54  const int camera_model_id = CameraModelNameToId(camera_model);
55 
56  if (camera_params.size() > 0 &&
57  !CameraModelVerifyParams(camera_model_id, camera_params)) {
58  std::cerr << "ERROR: Invalid camera parameters" << std::endl;
59  return false;
60  }
61  return true;
62 }
63 
64 bool VerifySiftGPUParams(const bool use_gpu) {
65 #if !defined(CUDA_ENABLED) && !defined(OPENGL_ENABLED)
66  if (use_gpu) {
67  std::cerr << "ERROR: Cannot use Sift GPU without CUDA or OpenGL support; "
68  "set SiftExtraction.use_gpu or SiftMatching.use_gpu to false."
69  << std::endl;
70  return false;
71  }
72 #endif
73  return true;
74 }
75 
76 // This enum can be used as optional input for feature_extractor and
77 // feature_importer to ensure that the camera flags of ImageReader are set in an
78 // exclusive and unambigous way. The table below explains the corespondence of
79 // each setting with the flags
80 //
81 // -----------------------------------------------------------------------------------
82 // | | ImageReaderOptions |
83 // | CameraMode | single_camera | single_camera_per_folder | single_camera_per_image |
84 // |------------|---------------|--------------------------|-------------------------|
85 // | AUTO | false | false | false |
86 // | SINGLE | true | false | false |
87 // | PER_FOLDER | false | true | false |
88 // | PER_IMAGE | false | false | true |
89 // -----------------------------------------------------------------------------------
90 //
91 // Note: When using AUTO mode a camera model will be uniquely identified by the
92 // following 5 parameters from EXIF tags:
93 // 1. Camera Make
94 // 2. Camera Model
95 // 3. Focal Length
96 // 4. Image Width
97 // 5. Image Height
98 //
99 // If any of the tags is missing then a camera model is considered invalid and a
100 // new camera is created similar to the PER_IMAGE mode.
101 //
102 // If these considered fields are not sufficient to uniquely identify a camera
103 // then using the AUTO mode will lead to incorrect setup for the cameras, e.g.
104 // the same camera is used with same focal length but different principal point
105 // between captures. In these cases it is recommended to either use the
106 // PER_FOLDER or PER_IMAGE settings.
107 enum class CameraMode { AUTO = 0, SINGLE = 1, PER_FOLDER = 2, PER_IMAGE = 3 };
108 
109 void UpdateImageReaderOptionsFromCameraMode(ImageReaderOptions& options,
110  CameraMode mode) {
111  switch (mode) {
112  case CameraMode::AUTO:
113  options.single_camera = false;
114  options.single_camera_per_folder = false;
115  options.single_camera_per_image = false;
116  break;
117  case CameraMode::SINGLE:
118  options.single_camera = true;
119  options.single_camera_per_folder = false;
120  options.single_camera_per_image = false;
121  break;
122  case CameraMode::PER_FOLDER:
123  options.single_camera = false;
124  options.single_camera_per_folder = true;
125  options.single_camera_per_image = false;
126  break;
127  case CameraMode::PER_IMAGE:
128  options.single_camera = false;
129  options.single_camera_per_folder = false;
130  options.single_camera_per_image = true;
131  break;
132  }
133 }
134 
135 } // namespace
136 
137 int RunFeatureExtractor(int argc, char** argv) {
138  std::string image_list_path;
139  int camera_mode = -1;
140 
141  OptionManager options;
142  options.AddDatabaseOptions();
143  options.AddImageOptions();
144  options.AddDefaultOption("camera_mode", &camera_mode);
145  options.AddDefaultOption("image_list_path", &image_list_path);
146  options.AddExtractionOptions();
147  options.Parse(argc, argv);
148 
149  ImageReaderOptions reader_options = *options.image_reader;
150  reader_options.database_path = *options.database_path;
151  reader_options.image_path = *options.image_path;
152 
153  if (camera_mode >= 0) {
154  UpdateImageReaderOptionsFromCameraMode(reader_options,
155  (CameraMode)camera_mode);
156  }
157 
158  if (!image_list_path.empty()) {
159  reader_options.image_list = ReadTextFileLines(image_list_path);
160  if (reader_options.image_list.empty()) {
161  return EXIT_SUCCESS;
162  }
163  }
164 
165  if (!ExistsCameraModelWithName(reader_options.camera_model)) {
166  std::cerr << "ERROR: Camera model does not exist" << std::endl;
167  }
168 
169  if (!VerifyCameraParams(reader_options.camera_model,
170  reader_options.camera_params)) {
171  return EXIT_FAILURE;
172  }
173 
174  if (!VerifySiftGPUParams(options.sift_extraction->use_gpu)) {
175  return EXIT_FAILURE;
176  }
177 
178  std::unique_ptr<QApplication> app;
179  if (options.sift_extraction->use_gpu && kUseOpenGL) {
180  app.reset(new QApplication(argc, argv));
181  }
182 
183  SiftFeatureExtractor feature_extractor(reader_options,
184  *options.sift_extraction);
185 
186  if (options.sift_extraction->use_gpu && kUseOpenGL) {
187  RunThreadWithOpenGLContext(&feature_extractor);
188  } else {
189  feature_extractor.Start();
190  feature_extractor.Wait();
191  }
192 
193  return EXIT_SUCCESS;
194 }
195 
196 int RunFeatureImporter(int argc, char** argv) {
197  std::string import_path;
198  std::string image_list_path;
199  int camera_mode = -1;
200 
201  OptionManager options;
202  options.AddDatabaseOptions();
203  options.AddImageOptions();
204  options.AddDefaultOption("camera_mode", &camera_mode);
205  options.AddRequiredOption("import_path", &import_path);
206  options.AddDefaultOption("image_list_path", &image_list_path);
207  options.AddExtractionOptions();
208  options.Parse(argc, argv);
209 
210  ImageReaderOptions reader_options = *options.image_reader;
211  reader_options.database_path = *options.database_path;
212  reader_options.image_path = *options.image_path;
213 
214  if (camera_mode >= 0) {
215  UpdateImageReaderOptionsFromCameraMode(reader_options,
216  (CameraMode)camera_mode);
217  }
218 
219  if (!image_list_path.empty()) {
220  reader_options.image_list = ReadTextFileLines(image_list_path);
221  if (reader_options.image_list.empty()) {
222  return EXIT_SUCCESS;
223  }
224  }
225 
226  if (!VerifyCameraParams(reader_options.camera_model,
227  reader_options.camera_params)) {
228  return EXIT_FAILURE;
229  }
230 
231  FeatureImporter feature_importer(reader_options, import_path);
232  feature_importer.Start();
233  feature_importer.Wait();
234 
235  return EXIT_SUCCESS;
236 }
237 
238 int RunMatchesImporter(int argc, char** argv) {
239  std::string match_list_path;
240  std::string match_type = "pairs";
241 
242  OptionManager options;
243  options.AddDatabaseOptions();
244  options.AddRequiredOption("match_list_path", &match_list_path);
245  options.AddDefaultOption("match_type", &match_type,
246  "{'pairs', 'raw', 'inliers'}");
247  options.AddMatchingOptions();
248  options.Parse(argc, argv);
249 
250  if (!VerifySiftGPUParams(options.sift_matching->use_gpu)) {
251  return EXIT_FAILURE;
252  }
253 
254  std::unique_ptr<QApplication> app;
255  if (options.sift_matching->use_gpu && kUseOpenGL) {
256  app.reset(new QApplication(argc, argv));
257  }
258 
259  std::unique_ptr<Thread> feature_matcher;
260  if (match_type == "pairs") {
261  ImagePairsMatchingOptions matcher_options;
262  matcher_options.match_list_path = match_list_path;
263  feature_matcher.reset(new ImagePairsFeatureMatcher(
264  matcher_options, *options.sift_matching, *options.database_path));
265  } else if (match_type == "raw" || match_type == "inliers") {
266  FeaturePairsMatchingOptions matcher_options;
267  matcher_options.match_list_path = match_list_path;
268  matcher_options.verify_matches = match_type == "raw";
269  feature_matcher.reset(new FeaturePairsFeatureMatcher(
270  matcher_options, *options.sift_matching, *options.database_path));
271  } else {
272  std::cerr << "ERROR: Invalid `match_type`";
273  return EXIT_FAILURE;
274  }
275 
276  if (options.sift_matching->use_gpu && kUseOpenGL) {
277  RunThreadWithOpenGLContext(feature_matcher.get());
278  } else {
279  feature_matcher->Start();
280  feature_matcher->Wait();
281  }
282 
283  return EXIT_SUCCESS;
284 }
285 
286 int RunExhaustiveMatcher(int argc, char** argv) {
287  OptionManager options;
288  options.AddDatabaseOptions();
290  options.Parse(argc, argv);
291 
292  if (!VerifySiftGPUParams(options.sift_matching->use_gpu)) {
293  return EXIT_FAILURE;
294  }
295 
296  std::unique_ptr<QApplication> app;
297  if (options.sift_matching->use_gpu && kUseOpenGL) {
298  app.reset(new QApplication(argc, argv));
299  }
300 
301  ExhaustiveFeatureMatcher feature_matcher(*options.exhaustive_matching,
302  *options.sift_matching,
303  *options.database_path);
304 
305  if (options.sift_matching->use_gpu && kUseOpenGL) {
306  RunThreadWithOpenGLContext(&feature_matcher);
307  } else {
308  feature_matcher.Start();
309  feature_matcher.Wait();
310  }
311 
312  return EXIT_SUCCESS;
313 }
314 
315 int RunSequentialMatcher(int argc, char** argv) {
316  OptionManager options;
317  options.AddDatabaseOptions();
319  options.Parse(argc, argv);
320 
321  if (!VerifySiftGPUParams(options.sift_matching->use_gpu)) {
322  return EXIT_FAILURE;
323  }
324 
325  std::unique_ptr<QApplication> app;
326  if (options.sift_matching->use_gpu && kUseOpenGL) {
327  app.reset(new QApplication(argc, argv));
328  }
329 
330  SequentialFeatureMatcher feature_matcher(*options.sequential_matching,
331  *options.sift_matching,
332  *options.database_path);
333 
334  if (options.sift_matching->use_gpu && kUseOpenGL) {
335  RunThreadWithOpenGLContext(&feature_matcher);
336  } else {
337  feature_matcher.Start();
338  feature_matcher.Wait();
339  }
340 
341  return EXIT_SUCCESS;
342 }
343 
344 int RunSpatialMatcher(int argc, char** argv) {
345  OptionManager options;
346  options.AddDatabaseOptions();
347  options.AddSpatialMatchingOptions();
348  options.Parse(argc, argv);
349 
350  if (!VerifySiftGPUParams(options.sift_matching->use_gpu)) {
351  return EXIT_FAILURE;
352  }
353 
354  std::unique_ptr<QApplication> app;
355  if (options.sift_matching->use_gpu && kUseOpenGL) {
356  app.reset(new QApplication(argc, argv));
357  }
358 
359  SpatialFeatureMatcher feature_matcher(*options.spatial_matching,
360  *options.sift_matching,
361  *options.database_path);
362 
363  if (options.sift_matching->use_gpu && kUseOpenGL) {
364  RunThreadWithOpenGLContext(&feature_matcher);
365  } else {
366  feature_matcher.Start();
367  feature_matcher.Wait();
368  }
369 
370  return EXIT_SUCCESS;
371 }
372 
373 int RunTransitiveMatcher(int argc, char** argv) {
374  OptionManager options;
375  options.AddDatabaseOptions();
377  options.Parse(argc, argv);
378 
379  if (!VerifySiftGPUParams(options.sift_matching->use_gpu)) {
380  return EXIT_FAILURE;
381  }
382 
383  std::unique_ptr<QApplication> app;
384  if (options.sift_matching->use_gpu && kUseOpenGL) {
385  app.reset(new QApplication(argc, argv));
386  }
387 
388  TransitiveFeatureMatcher feature_matcher(*options.transitive_matching,
389  *options.sift_matching,
390  *options.database_path);
391 
392  if (options.sift_matching->use_gpu && kUseOpenGL) {
393  RunThreadWithOpenGLContext(&feature_matcher);
394  } else {
395  feature_matcher.Start();
396  feature_matcher.Wait();
397  }
398 
399  return EXIT_SUCCESS;
400 }
401 
402 int RunVocabTreeMatcher(int argc, char** argv) {
403  OptionManager options;
404  options.AddDatabaseOptions();
405  options.AddVocabTreeMatchingOptions();
406  options.Parse(argc, argv);
407 
408  if (!VerifySiftGPUParams(options.sift_matching->use_gpu)) {
409  return EXIT_FAILURE;
410  }
411 
412  std::unique_ptr<QApplication> app;
413  if (options.sift_matching->use_gpu && kUseOpenGL) {
414  app.reset(new QApplication(argc, argv));
415  }
416 
417  VocabTreeFeatureMatcher feature_matcher(*options.vocab_tree_matching,
418  *options.sift_matching,
419  *options.database_path);
420 
421  if (options.sift_matching->use_gpu && kUseOpenGL) {
422  RunThreadWithOpenGLContext(&feature_matcher);
423  } else {
424  feature_matcher.Start();
425  feature_matcher.Wait();
426  }
427 
428  return EXIT_SUCCESS;
429 }
430 
431 } // namespace colmap
std::shared_ptr< SequentialMatchingOptions > sequential_matching
std::shared_ptr< TransitiveMatchingOptions > transitive_matching
void AddRequiredOption(const std::string &name, T *option, const std::string &help_text="")
void AddDefaultOption(const std::string &name, T *option, const std::string &help_text="")
std::shared_ptr< std::string > database_path
std::shared_ptr< SiftMatchingOptions > sift_matching
std::shared_ptr< SiftExtractionOptions > sift_extraction
std::shared_ptr< ImageReaderOptions > image_reader
std::shared_ptr< VocabTreeMatchingOptions > vocab_tree_matching
void Parse(const int argc, char **argv)
std::shared_ptr< ExhaustiveMatchingOptions > exhaustive_matching
std::shared_ptr< SpatialMatchingOptions > spatial_matching
std::shared_ptr< std::string > image_path
virtual void Start()
Definition: threading.cc:50
virtual void Wait()
Definition: threading.cc:86
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
const bool kUseOpenGL
Definition: gui.h:25
void RunThreadWithOpenGLContext(Thread *thread)
Definition: opengl_utils.h:81
int RunMatchesImporter(int argc, char **argv)
Definition: feature.cc:238
bool ExistsCameraModelWithName(const std::string &model_name)
int RunSequentialMatcher(int argc, char **argv)
Definition: feature.cc:315
bool CameraModelVerifyParams(const int model_id, const std::vector< double > &params)
int RunFeatureExtractor(int argc, char **argv)
Definition: feature.cc:137
int RunTransitiveMatcher(int argc, char **argv)
Definition: feature.cc:373
std::vector< std::string > ReadTextFileLines(const std::string &path)
Definition: misc.cc:308
int RunSpatialMatcher(int argc, char **argv)
Definition: feature.cc:344
int RunFeatureImporter(int argc, char **argv)
Definition: feature.cc:196
int RunVocabTreeMatcher(int argc, char **argv)
Definition: feature.cc:402
int RunExhaustiveMatcher(int argc, char **argv)
Definition: feature.cc:286
int CameraModelNameToId(const std::string &model_name)
std::vector< std::string > image_list
Definition: image_reader.h:36