From 8dabd11ba51369f69f8142fb6ed02ce2b567b332 Mon Sep 17 00:00:00 2001 From: Matthew Woehlke Date: Wed, 2 Jun 2021 09:23:21 -0400 Subject: [PATCH 1/2] Initial ability to reconstruct from manual tracks Introduce an action to attempt reconstruction using camera registration points (i.e. manual feature tracks). This is partly implemented; it runs and, in theory, extracts cameras. However, as I have not yet been able to get it to run successfully, I am unable to verify the functionality. Also, converting the reconstructed landmarks to GCPs is not yet implemented (for similar reasons). --- CMake/telesculptor-external-kwiver.cmake | 2 +- config/gui_manual_initialize.conf | 7 +++ gui/MainWindow.cxx | 61 +++++++++++++++++++++++- gui/MainWindow.h | 1 + gui/MainWindow.ui | 10 ++++ 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 config/gui_manual_initialize.conf diff --git a/CMake/telesculptor-external-kwiver.cmake b/CMake/telesculptor-external-kwiver.cmake index 0fee12c10..5ecb68df8 100644 --- a/CMake/telesculptor-external-kwiver.cmake +++ b/CMake/telesculptor-external-kwiver.cmake @@ -18,7 +18,7 @@ ExternalProject_Add(kwiver BINARY_DIR ${TELESCULPTOR_EXTERNAL_DIR}/kwiver-build STAMP_DIR ${TELESCULPTOR_STAMP_DIR} GIT_REPOSITORY "https://github.com/Kitware/kwiver.git" - GIT_TAG 68709c321bd23cf541b9b3acbf8ef728754df5bc + GIT_TAG 0dc3f67c58df77909f463864f18068db6e645679 #GIT_SHALLOW 1 CMAKE_CACHE_ARGS -DBUILD_SHARED_LIBS:BOOL=ON diff --git a/config/gui_manual_initialize.conf b/config/gui_manual_initialize.conf new file mode 100644 index 000000000..f1c6620eb --- /dev/null +++ b/config/gui_manual_initialize.conf @@ -0,0 +1,7 @@ +# Default configuration for the "Estimate Cameras/Landmarks" algorithm used in the GUI + +default_camera_config := gui_default_camera_intrinsics.conf + +block initializer + mvg:min_frame_to_frame_matches = 10 +endblock diff --git a/gui/MainWindow.cxx b/gui/MainWindow.cxx index 891b840c1..8cb6800ee 100644 --- a/gui/MainWindow.cxx +++ b/gui/MainWindow.cxx @@ -1355,6 +1355,7 @@ void MainWindowPrivate::setActiveTool(AbstractTool* tool) tool->setEnabled(enableTools); } this->UI.actionCancelComputation->setEnabled(enableCancel); + this->UI.actionRebuildScene->setEnabled(enableTools); this->UI.actionOpenProject->setEnabled(enableTools); // FIXME disable import actions } @@ -1500,7 +1501,7 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags) d->toolMenu = d->UI.menuCompute; d->toolSeparator = - d->UI.menuCompute->insertSeparator(d->UI.actionCancelComputation); + d->UI.menuCompute->insertSeparator(d->UI.actionRebuildScene); QAction * runAllSep = d->UI.menuCompute->insertSeparator(d->toolSeparator); d->addTool(new TrackFeaturesTool(this), this); @@ -1700,6 +1701,8 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags) }); connect(d->UI.cameraView, &CameraView::cameraComputationRequested, this, &MainWindow::computeCamera); + connect(d->UI.actionRebuildScene, &QAction::triggered, + this, &MainWindow::rebuildScene); // Ruler widget d->rulerHelper = new RulerHelper(this); @@ -3576,6 +3579,62 @@ void MainWindow::computeCamera() } } +//----------------------------------------------------------------------------- +void MainWindow::rebuildScene() +{ + QTE_D(); + + if (!d->activeTool) + { + InitCamerasLandmarksTool tool{this}; + QEventLoop eventLoop; + + QObject::connect(&tool, &AbstractTool::completed, + &eventLoop, &QEventLoop::quit); + QObject::connect(&tool, &AbstractTool::failed, + &eventLoop, &QEventLoop::quit); + QObject::connect(&tool, &AbstractTool::failed, + this, &MainWindow::reportToolError); + + auto const constraints = + std::make_shared(*d->sfmConstraints); + constraints->set_metadata(nullptr); + + auto features = d->groundControlPointsHelper->registrationTracks(); + auto landmarks = d->groundControlPointsHelper->registrationLandmarks(); + + tool.setTracks(features); + tool.setLandmarks(landmarks); + tool.setSfmConstraints(constraints); + tool.setVideoPath(stdString(d->videoPath)); + tool.setMaskPath(stdString(d->maskPath)); + + auto config = readConfig("gui_manual_initialize.conf"); + config->merge_config(d->project->config); + + tool.setConfig(config); + + if (tool.execute()) + { + d->setActiveTool(&tool); + d->updateProgress(&tool, tool.description(), 0); + + eventLoop.exec(); + + if (auto const& data = tool.data()) + { + if (data->cameras && data->cameras->size()) + { + d->updateCameras(data->cameras); + } + } + + d->setActiveTool(nullptr); + d->updateProgress(&tool, tool.description(), 100); + } + } +} + //----------------------------------------------------------------------------- void MainWindow::updateToolProgress(QString const& desc, int progress) { diff --git a/gui/MainWindow.h b/gui/MainWindow.h index df6d76432..d91eaab53 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -85,6 +85,7 @@ public slots: void applySimilarityTransform(); void computeCamera(); + void rebuildScene(); void saveWebGLScene(); diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index e33c98849..792c482ca 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -122,6 +122,8 @@ + + @@ -670,6 +672,14 @@ . + + + Reb&uild Scene + + + Reconstruct cameras and ground control points from camera registration points + + From e68996b6e5d2e15e08fcd1a4fc6b869af793a34a Mon Sep 17 00:00:00 2001 From: Matthew Woehlke Date: Mon, 7 Jun 2021 13:17:40 -0400 Subject: [PATCH 2/2] Hook up landmarks from reconstruction Add ability to set the (world) location of a ground control point (which may or may not already exist) to the helper. Use this to implement accepting reconstructed world locations from reconstruction using manual annotations, as added by the previous commit. Although "real" reconstruction is not functioning as of this commit, the logic has been tested by replacing the actual algorithm with creation of random cameras and landmarks. --- gui/GroundControlPointsHelper.cxx | 57 +++++++++++++++++++++++++++++++ gui/GroundControlPointsHelper.h | 1 + gui/MainWindow.cxx | 15 ++++++++ 3 files changed, 73 insertions(+) diff --git a/gui/GroundControlPointsHelper.cxx b/gui/GroundControlPointsHelper.cxx index bb8ead46e..4897b64ca 100644 --- a/gui/GroundControlPointsHelper.cxx +++ b/gui/GroundControlPointsHelper.cxx @@ -1162,6 +1162,63 @@ void GroundControlPointsHelper::setGroundControlPoints( emit this->pointCountChanged(d->groundControlPoints.size()); } +//----------------------------------------------------------------------------- +void GroundControlPointsHelper::setGroundControlPoint( + id_t id, kwiver::vital::vector_3d const& loc) +{ + QTE_D(); + + if (auto* const gcp = qtGet(d->groundControlPoints, id)) + { + if (gcp->second.gcp) + { + if (auto* const hp = qtGet(d->gcpIdToHandleMap, id)) + { + auto const handleId = d->worldWidget->findHandleWidget(hp->second); + if (handleId < 0) + { + qWarning() + << "Failed to find the VTK ID associated with the VTK handle" + << hp->second << " and the point with ID" << id; + return; + } + + d->movePoint(handleId, d->worldWidget, loc); + if (auto* const camera = d->mainWindow->activeCamera()) + { + double cameraPt[2]; + camera->ProjectPoint(loc, cameraPt); + d->movePoint( + handleId, d->cameraWidget, { cameraPt[0], cameraPt[1], 0.0 }); + } + else + { + d->updatePoint(handleId); + } + } + else + { + qWarning() << "Failed to find the VTK handle associated with " + "the point with ID" << id; + } + + return; + } + } + + auto const oldNextId = d->nextId; + + auto gcp = std::make_shared(); + gcp->set_loc(loc); + + d->addPoint(id, gcp); + + d->nextId = std::max(id + 1, oldNextId); + + emit this->pointAdded(id); + emit this->pointCountChanged(d->groundControlPoints.size()); +} + //----------------------------------------------------------------------------- bool GroundControlPointsHelper::isEmpty() const { diff --git a/gui/GroundControlPointsHelper.h b/gui/GroundControlPointsHelper.h index 3d77e948a..6094c7dd2 100644 --- a/gui/GroundControlPointsHelper.h +++ b/gui/GroundControlPointsHelper.h @@ -39,6 +39,7 @@ class GroundControlPointsHelper : public QObject // Set ground control points void setGroundControlPoints(kwiver::vital::ground_control_point_map const&); + void setGroundControlPoint(id_t, kwiver::vital::vector_3d const&); // Get ground control points std::vector groundControlPoints() const; diff --git a/gui/MainWindow.cxx b/gui/MainWindow.cxx index 8cb6800ee..717592f0d 100644 --- a/gui/MainWindow.cxx +++ b/gui/MainWindow.cxx @@ -3627,6 +3627,21 @@ void MainWindow::rebuildScene() { d->updateCameras(data->cameras); } + if (data->landmarks && data->landmarks->size()) + { + auto lm = data->landmarks->landmarks(); + for (auto const& li : lm) + { + if (li.second) + { + using gcp_id_t = kwiver::vital::ground_control_point_id_t; + + auto const i = li.first; + d->groundControlPointsHelper->setGroundControlPoint( + static_cast(i), li.second->loc()); + } + } + } } d->setActiveTool(nullptr);