| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include "ui/automatic_reconstruction_widget.h" |
| |
|
| | #include "ui/main_window.h" |
| |
|
| | namespace colmap { |
| |
|
| | AutomaticReconstructionWidget::AutomaticReconstructionWidget( |
| | MainWindow* main_window) |
| | : OptionsWidget(main_window), |
| | main_window_(main_window), |
| | thread_control_widget_(new ThreadControlWidget(this)) { |
| | setWindowTitle("Automatic reconstruction"); |
| |
|
| | AddOptionDirPath(&options_.workspace_path, "Workspace folder"); |
| | AddSpacer(); |
| | AddOptionDirPath(&options_.image_path, "Image folder"); |
| | AddSpacer(); |
| | AddOptionDirPath(&options_.mask_path, "Mask folder"); |
| | AddSpacer(); |
| | AddOptionFilePath(&options_.vocab_tree_path, "Vocabulary tree<br>(optional)"); |
| |
|
| | AddSpacer(); |
| |
|
| | QLabel* data_type_label = new QLabel(tr("Data type"), this); |
| | data_type_label->setFont(font()); |
| | data_type_label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); |
| | grid_layout_->addWidget(data_type_label, grid_layout_->rowCount(), 0); |
| |
|
| | data_type_cb_ = new QComboBox(this); |
| | data_type_cb_->addItem("Individual images"); |
| | data_type_cb_->addItem("Video frames"); |
| | data_type_cb_->addItem("Internet images"); |
| | grid_layout_->addWidget(data_type_cb_, grid_layout_->rowCount() - 1, 1); |
| |
|
| | QLabel* quality_label = new QLabel(tr("Quality"), this); |
| | quality_label->setFont(font()); |
| | quality_label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); |
| | grid_layout_->addWidget(quality_label, grid_layout_->rowCount(), 0); |
| |
|
| | quality_cb_ = new QComboBox(this); |
| | quality_cb_->addItem("Low"); |
| | quality_cb_->addItem("Medium"); |
| | quality_cb_->addItem("High"); |
| | quality_cb_->addItem("Extreme"); |
| | quality_cb_->setCurrentIndex(2); |
| | grid_layout_->addWidget(quality_cb_, grid_layout_->rowCount() - 1, 1); |
| |
|
| | AddSpacer(); |
| |
|
| | AddOptionBool(&options_.single_camera, "Shared intrinsics"); |
| | AddOptionBool(&options_.sparse, "Sparse model"); |
| | AddOptionBool(&options_.dense, "Dense model"); |
| |
|
| | QLabel* mesher_label = new QLabel(tr("Mesher"), this); |
| | mesher_label->setFont(font()); |
| | mesher_label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); |
| | grid_layout_->addWidget(mesher_label, grid_layout_->rowCount(), 0); |
| |
|
| | mesher_cb_ = new QComboBox(this); |
| | mesher_cb_->addItem("Poisson"); |
| | mesher_cb_->addItem("Delaunay"); |
| | mesher_cb_->setCurrentIndex(0); |
| | grid_layout_->addWidget(mesher_cb_, grid_layout_->rowCount() - 1, 1); |
| |
|
| | AddSpacer(); |
| |
|
| | AddOptionInt(&options_.num_threads, "num_threads", -1); |
| | AddOptionBool(&options_.use_gpu, "GPU"); |
| | AddOptionText(&options_.gpu_index, "gpu_index"); |
| |
|
| | AddSpacer(); |
| |
|
| | QPushButton* run_button = new QPushButton(tr("Run"), this); |
| | grid_layout_->addWidget(run_button, grid_layout_->rowCount(), 1); |
| | connect(run_button, &QPushButton::released, this, |
| | &AutomaticReconstructionWidget::Run); |
| |
|
| | render_result_ = new QAction(this); |
| | connect(render_result_, &QAction::triggered, this, |
| | &AutomaticReconstructionWidget::RenderResult, Qt::QueuedConnection); |
| | } |
| |
|
| | void AutomaticReconstructionWidget::Run() { |
| | WriteOptions(); |
| |
|
| | if (!ExistsDir(options_.workspace_path)) { |
| | QMessageBox::critical(this, "", tr("Invalid workspace folder")); |
| | return; |
| | } |
| |
|
| | if (!ExistsDir(options_.image_path)) { |
| | QMessageBox::critical(this, "", tr("Invalid image folder")); |
| | return; |
| | } |
| |
|
| | switch (data_type_cb_->currentIndex()) { |
| | case 0: |
| | options_.data_type = |
| | AutomaticReconstructionController::DataType::INDIVIDUAL; |
| | break; |
| | case 1: |
| | options_.data_type = AutomaticReconstructionController::DataType::VIDEO; |
| | break; |
| | case 2: |
| | options_.data_type = |
| | AutomaticReconstructionController::DataType::INTERNET; |
| | break; |
| | default: |
| | options_.data_type = |
| | AutomaticReconstructionController::DataType::INDIVIDUAL; |
| | break; |
| | } |
| |
|
| | switch (quality_cb_->currentIndex()) { |
| | case 0: |
| | options_.quality = AutomaticReconstructionController::Quality::LOW; |
| | break; |
| | case 1: |
| | options_.quality = AutomaticReconstructionController::Quality::MEDIUM; |
| | break; |
| | case 2: |
| | options_.quality = AutomaticReconstructionController::Quality::HIGH; |
| | break; |
| | case 3: |
| | options_.quality = AutomaticReconstructionController::Quality::EXTREME; |
| | break; |
| | default: |
| | options_.quality = AutomaticReconstructionController::Quality::HIGH; |
| | break; |
| | } |
| |
|
| | switch (mesher_cb_->currentIndex()) { |
| | case 0: |
| | options_.mesher = AutomaticReconstructionController::Mesher::POISSON; |
| | break; |
| | case 1: |
| | options_.mesher = AutomaticReconstructionController::Mesher::DELAUNAY; |
| | break; |
| | default: |
| | options_.mesher = AutomaticReconstructionController::Mesher::POISSON; |
| | break; |
| | } |
| |
|
| | main_window_->reconstruction_manager_.Clear(); |
| | main_window_->reconstruction_manager_widget_->Update(); |
| | main_window_->RenderClear(); |
| | main_window_->RenderNow(); |
| |
|
| | auto controller = std::make_unique<AutomaticReconstructionController>( |
| | options_, &main_window_->reconstruction_manager_); |
| | controller->AddCallback(Thread::FINISHED_CALLBACK, |
| | [this]() { render_result_->trigger(); }); |
| | thread_control_widget_->StartThread("Reconstructing...", true, |
| | std::move(controller)); |
| | } |
| |
|
| | void AutomaticReconstructionWidget::RenderResult() { |
| | if (main_window_->reconstruction_manager_.Size() > 0) { |
| | main_window_->reconstruction_manager_widget_->Update(); |
| | main_window_->RenderClear(); |
| | main_window_->RenderNow(); |
| | } |
| |
|
| | if (options_.sparse) { |
| | QMessageBox::information( |
| | this, "", |
| | tr("Imported the reconstructed sparse models for visualization. The " |
| | "models were also exported to the <i>sparse</i> sub-folder in the " |
| | "workspace.")); |
| | } |
| |
|
| | if (options_.dense) { |
| | QMessageBox::information( |
| | this, "", |
| | tr("To visualize the reconstructed dense point cloud, navigate to the " |
| | "<i>dense</i> sub-folder in your workspace with <i>File > Import " |
| | "model from...</i>. To visualize the meshed model, you must use an " |
| | "external viewer such as Meshlab.")); |
| | } |
| | } |
| |
|
| | } |
| |
|