ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
FeatureMatchingWidget.cpp
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 
9 
10 #include "ThreadControlWidget.h"
11 #include "feature/matching.h"
12 #include "ui/options_widget.h"
13 #include "util/misc.h"
14 #include "util/option_manager.h"
15 
16 namespace cloudViewer {
17 
18 using namespace colmap;
19 
20 class FeatureMatchingTab : public QWidget {
21 public:
22  FeatureMatchingTab(QWidget* parent, OptionManager* options);
23 
24  virtual void Run() = 0;
25 
26 protected:
27  void CreateGeneralOptions();
28 
31  QGridLayout* grid_layout_;
33 };
34 
36 public:
37  ExhaustiveMatchingTab(QWidget* parent, OptionManager* options);
38  void Run() override;
39 };
40 
42 public:
43  SequentialMatchingTab(QWidget* parent, OptionManager* options);
44  void Run() override;
45 };
46 
48 public:
49  VocabTreeMatchingTab(QWidget* parent, OptionManager* options);
50  void Run() override;
51 };
52 
54 public:
55  SpatialMatchingTab(QWidget* parent, OptionManager* options);
56  void Run() override;
57 };
58 
60 public:
61  TransitiveMatchingTab(QWidget* parent, OptionManager* options);
62  void Run() override;
63 };
64 
66 public:
67  CustomMatchingTab(QWidget* parent, OptionManager* options);
68  void Run() override;
69 
70 private:
71  std::string match_list_path_;
72  QComboBox* match_type_cb_;
73 };
74 
76  : QWidget(parent),
77  options_(options),
78  options_widget_(new OptionsWidget(this)),
79  grid_layout_(new QGridLayout(this)),
80  thread_control_widget_(new ThreadControlWidget(this)) {}
81 
85  options_widget_->AddSection("General Options");
87 
89  "num_threads", -1);
91  "use_gpu");
93  "gpu_index");
95  "max_ratio");
97  "max_distance");
99  "cross_check");
101  "max_num_matches");
103  "max_error");
105  "confidence", 0, 1, 0.00001, 5);
107  "max_num_trials");
109  "min_inlier_ratio", 0, 1, 0.001, 3);
111  "min_num_inliers");
113  "multiple_models");
115  "guided_matching");
116 
118 
119  QScrollArea* options_scroll_area = new QScrollArea(this);
120  options_scroll_area->setAlignment(Qt::AlignHCenter);
121  options_scroll_area->setWidget(options_widget_);
122  grid_layout_->addWidget(options_scroll_area, grid_layout_->rowCount(), 0);
123 
124  QPushButton* run_button = new QPushButton(tr("Run"), this);
125  grid_layout_->addWidget(run_button, grid_layout_->rowCount(), 0);
126  connect(run_button, &QPushButton::released, this, &FeatureMatchingTab::Run);
127 }
128 
130  OptionManager* options)
131  : FeatureMatchingTab(parent, options) {
133  "block_size", 2);
134 
136 }
137 
140 
141  Thread* matcher = new ExhaustiveFeatureMatcher(
144  thread_control_widget_->StartThread("Matching...", true, matcher);
145 }
146 
148  OptionManager* options)
149  : FeatureMatchingTab(parent, options) {
151  "overlap");
153  &options_->sequential_matching->quadratic_overlap,
154  "quadratic_overlap");
156  &options_->sequential_matching->loop_detection, "loop_detection");
158  &options_->sequential_matching->loop_detection_period,
159  "loop_detection_period");
161  &options_->sequential_matching->loop_detection_num_images,
162  "loop_detection_num_images");
165  ->loop_detection_num_nearest_neighbors,
166  "loop_detection_num_nearest_neighbors");
168  &options_->sequential_matching->loop_detection_num_checks,
169  "loop_detection_num_checks", 1);
172  ->loop_detection_num_images_after_verification,
173  "loop_detection_num_images_after_verification", 0);
175  &options_->sequential_matching->loop_detection_max_num_features,
176  "loop_detection_max_num_features", -1);
178  &options_->sequential_matching->vocab_tree_path, "vocab_tree_path");
179 
181 }
182 
185 
186  if (options_->sequential_matching->loop_detection &&
187  !ExistsFile(options_->sequential_matching->vocab_tree_path)) {
188  QMessageBox::critical(this, "", tr("Invalid vocabulary tree path."));
189  return;
190  }
191 
192  Thread* matcher = new SequentialFeatureMatcher(
195  thread_control_widget_->StartThread("Matching...", true, matcher);
196 }
197 
199  OptionManager* options)
200  : FeatureMatchingTab(parent, options) {
202  "num_images");
204  &options_->vocab_tree_matching->num_nearest_neighbors,
205  "num_nearest_neighbors");
207  "num_checks", 1);
209  &options_->vocab_tree_matching->num_images_after_verification,
210  "num_images_after_verification", 0);
212  &options_->vocab_tree_matching->max_num_features,
213  "max_num_features", -1);
215  &options_->vocab_tree_matching->vocab_tree_path, "vocab_tree_path");
216 
218 }
219 
222 
223  if (!ExistsFile(options_->vocab_tree_matching->vocab_tree_path)) {
224  QMessageBox::critical(this, "", tr("Invalid vocabulary tree path."));
225  return;
226  }
227 
228  Thread* matcher = new VocabTreeFeatureMatcher(
231  thread_control_widget_->StartThread("Matching...", true, matcher);
232 }
233 
235  : FeatureMatchingTab(parent, options) {
237  "is_gps");
239  "ignore_z");
241  &options_->spatial_matching->max_num_neighbors,
242  "max_num_neighbors");
244  "max_distance");
245 
247 }
248 
251 
255  thread_control_widget_->StartThread("Matching...", true, matcher);
256 }
257 
259  OptionManager* options)
260  : FeatureMatchingTab(parent, options) {
261  options_widget_->AddOptionInt(&options->transitive_matching->batch_size,
262  "batch_size");
263  options_widget_->AddOptionInt(&options->transitive_matching->num_iterations,
264  "num_iterations");
265 
267 }
268 
271 
272  Thread* matcher = new TransitiveFeatureMatcher(
275  thread_control_widget_->StartThread("Matching...", true, matcher);
276 }
277 
279  : FeatureMatchingTab(parent, options) {
280  match_type_cb_ = new QComboBox(this);
281  match_type_cb_->addItem(QString("Image pairs"));
282  match_type_cb_->addItem(QString("Raw feature matches"));
283  match_type_cb_->addItem(QString("Inlier feature matches"));
284  options_widget_->AddOptionRow("type", match_type_cb_, nullptr);
285 
286  options_widget_->AddOptionFilePath(&match_list_path_, "match_list_path");
288  "block_size", 2);
289 
291 }
292 
295 
296  if (!ExistsFile(match_list_path_)) {
297  QMessageBox::critical(this, "", tr("Path does not exist!"));
298  return;
299  }
300 
301  Thread* matcher = nullptr;
302  if (match_type_cb_->currentIndex() == 0) {
303  ImagePairsMatchingOptions matcher_options;
304  matcher_options.match_list_path = match_list_path_;
305  matcher = new ImagePairsFeatureMatcher(matcher_options,
308  } else {
309  FeaturePairsMatchingOptions matcher_options;
310  matcher_options.match_list_path = match_list_path_;
311  if (match_type_cb_->currentIndex() == 1) {
312  matcher_options.verify_matches = true;
313  } else if (match_type_cb_->currentIndex() == 2) {
314  matcher_options.verify_matches = false;
315  }
316 
317  matcher = new FeaturePairsFeatureMatcher(matcher_options,
320  }
321 
322  thread_control_widget_->StartThread("Matching...", true, matcher);
323 }
324 
326  OptionManager* options)
327  : parent_(parent) {
328  // Do not change flag, to make sure feature database is not accessed from
329  // multiple threads
330  setWindowFlags(Qt::Window);
331  setWindowTitle("Feature matching");
332 
333  QGridLayout* grid = new QGridLayout(this);
334 
335  tab_widget_ = new QTabWidget(this);
336  tab_widget_->addTab(new ExhaustiveMatchingTab(this, options),
337  tr("Exhaustive"));
338  tab_widget_->addTab(new SequentialMatchingTab(this, options),
339  tr("Sequential"));
340  tab_widget_->addTab(new VocabTreeMatchingTab(this, options),
341  tr("VocabTree"));
342  tab_widget_->addTab(new SpatialMatchingTab(this, options), tr("Spatial"));
343  tab_widget_->addTab(new TransitiveMatchingTab(this, options),
344  tr("Transitive"));
345  tab_widget_->addTab(new CustomMatchingTab(this, options), tr("Custom"));
346 
347  grid->addWidget(tab_widget_, 0, 0);
348 }
349 
350 void FeatureMatchingWidget::showEvent(QShowEvent* event) {
351  parent_->setDisabled(true);
352 }
353 
354 void FeatureMatchingWidget::hideEvent(QHideEvent* event) {
355  parent_->setEnabled(true);
356 }
357 
358 } // namespace cloudViewer
MouseEvent event
CustomMatchingTab(QWidget *parent, OptionManager *options)
ExhaustiveMatchingTab(QWidget *parent, OptionManager *options)
ThreadControlWidget * thread_control_widget_
FeatureMatchingWidget(QWidget *parent, OptionManager *options)
SequentialMatchingTab(QWidget *parent, OptionManager *options)
SpatialMatchingTab(QWidget *parent, OptionManager *options)
void StartThread(const QString &progress_text, const bool stoppable, colmap::Thread *thread)
TransitiveMatchingTab(QWidget *parent, OptionManager *options)
VocabTreeMatchingTab(QWidget *parent, OptionManager *options)
CustomMatchingTab(QWidget *parent, OptionManager *options)
ExhaustiveMatchingTab(QWidget *parent, OptionManager *options)
FeatureMatchingTab(QWidget *parent, OptionManager *options)
std::shared_ptr< SequentialMatchingOptions > sequential_matching
std::shared_ptr< TransitiveMatchingOptions > transitive_matching
std::shared_ptr< std::string > database_path
std::shared_ptr< SiftMatchingOptions > sift_matching
std::shared_ptr< VocabTreeMatchingOptions > vocab_tree_matching
std::shared_ptr< ExhaustiveMatchingOptions > exhaustive_matching
std::shared_ptr< SpatialMatchingOptions > spatial_matching
std::shared_ptr< ImagePairsMatchingOptions > image_pairs_matching
QLineEdit * AddOptionText(std::string *option, const std::string &label_text)
QLineEdit * AddOptionFilePath(std::string *option, const std::string &label_text)
QDoubleSpinBox * AddOptionDouble(double *option, const std::string &label_text, const double min=0, const double max=1e7, const double step=0.01, const int decimals=2)
QSpinBox * AddOptionInt(int *option, const std::string &label_text, const int min=0, const int max=static_cast< int >(1e7))
void AddOptionRow(const std::string &label_text, QWidget *widget, void *option)
void AddSection(const std::string &title)
QCheckBox * AddOptionBool(bool *option, const std::string &label_text)
SequentialMatchingTab(QWidget *parent, OptionManager *options)
SpatialMatchingTab(QWidget *parent, OptionManager *options)
TransitiveMatchingTab(QWidget *parent, OptionManager *options)
VocabTreeMatchingTab(QWidget *parent, OptionManager *options)
Generic file read and write utility for python interface.
bool ExistsFile(const std::string &path)
Definition: misc.cc:100