From b3e2218ca18778c9178cbf0ef18f07494b525052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Thu, 13 Apr 2023 12:24:38 +0200 Subject: [PATCH 1/4] [sfm] Add new parameters to the SfM `Params` structure `nbFirstUnstableCameras` and `maxImagesPerGroup` were hard-coded variables set in the "findNextBestView" function which could not be modified in any way. They are now part of the `Params` structure and can thus be modified. --- .../ReconstructionEngine_sequentialSfM.cpp | 25 ++++++------------- .../ReconstructionEngine_sequentialSfM.hpp | 17 ++++++++++++- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp index edf6dbb15e..ed202f0976 100644 --- a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp +++ b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp @@ -1089,33 +1089,24 @@ bool ReconstructionEngine_sequentialSfM::findNextBestViews( } } - // The beginning of the incremental SfM is a well known risky and - // unstable step which has a big impact on the final result. - // The Bundle Adjustment is an intensive computing step so we only use it - // every N cameras. - // We make an exception for the first 'nbFirstUnstableCameras' cameras - // and perform a BA for each camera because it makes the results - // more stable and it's quite cheap because we have few data. - static const std::size_t nbFirstUnstableCameras = 30; - - if(_sfmData.getPoses().size() < nbFirstUnstableCameras && + // If the number of cameras is less than nbFirstUnstableCameras, then the bundle adjustment should be performed + // every time a new camera is added: it is not expensive as there is very little data and it gives more stable results. + if(_sfmData.getPoses().size() < _params.nbFirstUnstableCameras && !out_selectedViewIds.empty()) { // add images one by one to reconstruct the first cameras ALICEVISION_LOG_DEBUG("findNextBestViews: beginning of the incremental SfM" << std::endl << "Only the first image of the resection group is used." << std::endl << "\t- image view id : " << out_selectedViewIds.front() << std::endl - << "\t- # unstable poses : " << _sfmData.getPoses().size() << " / " << nbFirstUnstableCameras << std::endl); + << "\t- # unstable poses : " << _sfmData.getPoses().size() << " / " << _params.nbFirstUnstableCameras << std::endl); out_selectedViewIds.resize(1); } - // Limit to a maximum number of cameras added to ensure that - // we don't add too much data in one step without bundle adjustment. - static const std::size_t maxImagesPerGroup = 30; - - if(out_selectedViewIds.size() > maxImagesPerGroup) - out_selectedViewIds.resize(maxImagesPerGroup); + // No more than maxImagesPerGroup cameras should be added at once without performing the bundle adjustment (if set to + // 0, then there is no limit on the number of views that can be added at once) + if(_params.maxImagesPerGroup > 0 && out_selectedViewIds.size() > _params.maxImagesPerGroup) + out_selectedViewIds.resize(_params.maxImagesPerGroup); ALICEVISION_LOG_DEBUG( "Find next best views took: " << std::chrono::duration_cast(std::chrono::steady_clock::now() - chrono_start).count() << " msec\n" diff --git a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.hpp b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.hpp index 9c076bb500..06b335453e 100644 --- a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.hpp +++ b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.hpp @@ -63,13 +63,28 @@ class ReconstructionEngine_sequentialSfM : public ReconstructionEngine bool filterTrackForks = true; robustEstimation::ERobustEstimator localizerEstimator = robustEstimation::ERobustEstimator::ACRANSAC; double localizerEstimatorError = std::numeric_limits::infinity(); - size_t localizerEstimatorMaxIterations = 4096; + std::size_t localizerEstimatorMaxIterations = 4096; // Pyramid scoring const int pyramidBase = 2; const int pyramidDepth = 5; + // Bundle Adjustment triggering + + /// The beginning of the incremental SfM is a well known risky and + /// unstable step which has a big impact on the final result. + /// The Bundle Adjustment is an intensive computing step so we only use it + /// every N cameras. + /// We make an exception for the first 'nbFirstUnstableCameras' cameras + /// and perform a BA for each camera because it makes the results + /// more stable and it's quite cheap because we have few data. + std::size_t nbFirstUnstableCameras = 30; + + /// Limit to a maximum number of cameras added to ensure that + /// we don't add too much data in one step without bundle adjustment. + std::size_t maxImagesPerGroup = 30; + // Local Bundle Adjustment data /// The minimum number of shared matches to create an edge between two views (nodes) From 48a683c55649c3c69a149d6af5846e2e5cc97c71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 18 Apr 2023 18:52:35 +0200 Subject: [PATCH 2/4] [software] IncrementalSfM: Expose new parameters in the command line The `nbFirstUnstableCameras` and `maxImagesPerGroup` parameters, which respectively set the number of cameras for which the bundle adjustment is performed every time a camera is added and the maximum number of cameras that can be added before a new bundle adjustment has to be performed, are now exposed in the command line. --- src/software/pipeline/main_incrementalSfM.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/software/pipeline/main_incrementalSfM.cpp b/src/software/pipeline/main_incrementalSfM.cpp index ff0fb50152..a26b55d2d7 100644 --- a/src/software/pipeline/main_incrementalSfM.cpp +++ b/src/software/pipeline/main_incrementalSfM.cpp @@ -153,6 +153,13 @@ int aliceVision_main(int argc, char **argv) "It reduces the reconstruction time, especially for big datasets (500+ images).") ("localBAGraphDistance", po::value(&sfmParams.localBundelAdjustementGraphDistanceLimit)->default_value(sfmParams.localBundelAdjustementGraphDistanceLimit), "Graph-distance limit setting the Active region in the Local Bundle Adjustment strategy.") + ("nbFirstUnstableCameras", po::value(&sfmParams.nbFirstUnstableCameras)->default_value(sfmParams.nbFirstUnstableCameras), + "Number of cameras for which the bundle adjustment is performed every single time a camera is added, leading to more stable " + "results while the computations are not too expensive since there is not much data. Past this number, the bundle adjustment " + "will only be performed once for N added cameras.") + ("maxImagesPerGroup", po::value(&sfmParams.maxImagesPerGroup)->default_value(sfmParams.maxImagesPerGroup), + "Maximum number of cameras that can be added before the bundle adjustment is performed. This prevents adding too much data " + "at once without performing the bundle adjustment.") ("localizerEstimator", po::value(&sfmParams.localizerEstimator)->default_value(sfmParams.localizerEstimator), "Estimator type used to localize cameras (acransac (default), ransac, lsmeds, loransac, maxconsensus)") ("localizerEstimatorError", po::value(&sfmParams.localizerEstimatorError)->default_value(0.0), From d13f7afdd36cd2e6bd7b5dc927432d87586b2d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Thu, 13 Apr 2023 12:29:39 +0200 Subject: [PATCH 3/4] [software] IncrementalSfM: Update software's version --- src/software/pipeline/main_incrementalSfM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/software/pipeline/main_incrementalSfM.cpp b/src/software/pipeline/main_incrementalSfM.cpp index a26b55d2d7..b4a7cb8724 100644 --- a/src/software/pipeline/main_incrementalSfM.cpp +++ b/src/software/pipeline/main_incrementalSfM.cpp @@ -27,7 +27,7 @@ // These constants define the current software version. // They must be updated when the command line is changed. #define ALICEVISION_SOFTWARE_VERSION_MAJOR 2 -#define ALICEVISION_SOFTWARE_VERSION_MINOR 1 +#define ALICEVISION_SOFTWARE_VERSION_MINOR 2 using namespace aliceVision; From 3ef258c7c950d253eded86192bfd94c373ce67d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Thu, 13 Apr 2023 17:01:37 +0200 Subject: [PATCH 4/4] [sfm] Add extra debug logs when loading feature and match folders The logs are useful to determine whether all the provided folders are correctly loaded. --- src/aliceVision/sfm/pipeline/pairwiseMatchesIO.hpp | 8 ++++++++ src/aliceVision/sfm/pipeline/regionsIO.cpp | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/aliceVision/sfm/pipeline/pairwiseMatchesIO.hpp b/src/aliceVision/sfm/pipeline/pairwiseMatchesIO.hpp index c1b1efd2f6..71da3f46df 100644 --- a/src/aliceVision/sfm/pipeline/pairwiseMatchesIO.hpp +++ b/src/aliceVision/sfm/pipeline/pairwiseMatchesIO.hpp @@ -40,6 +40,10 @@ inline bool loadPairwiseMatches( { std::vector matchesFolders; + ALICEVISION_LOG_DEBUG("List of provided match folders:"); + for (auto it = folders.begin(); it != folders.end(); ++it) + ALICEVISION_LOG_DEBUG("\t - " << *it); + if(!useOnlyMatchesFromFolder) matchesFolders = sfmData.getMatchesFolders(); else @@ -47,6 +51,10 @@ inline bool loadPairwiseMatches( matchesFolders.insert(matchesFolders.end(), folders.begin(), folders.end()); + ALICEVISION_LOG_DEBUG("List of match folders to load:"); + for (auto it = matchesFolders.begin(); it != matchesFolders.end(); ++it) + ALICEVISION_LOG_DEBUG("\t - " << *it); + ALICEVISION_LOG_DEBUG("Loading matches"); if (!matching::Load(out_pairwiseMatches, sfmData.getViewsKeys(), matchesFolders, descTypes, maxNbMatches, minNbMatches)) { diff --git a/src/aliceVision/sfm/pipeline/regionsIO.cpp b/src/aliceVision/sfm/pipeline/regionsIO.cpp index 03e3fe607c..69cffe58cf 100644 --- a/src/aliceVision/sfm/pipeline/regionsIO.cpp +++ b/src/aliceVision/sfm/pipeline/regionsIO.cpp @@ -104,7 +104,7 @@ std::unique_ptr loadFeatures(const std::vector& f if(featFilename.empty()) throw std::runtime_error("Can't find view " + basename + " features file"); - ALICEVISION_LOG_TRACE("Features filename: " << featFilename); + ALICEVISION_LOG_DEBUG("Features filename: " << featFilename); std::unique_ptr regionsPtr; imageDescriber.allocate(regionsPtr); @@ -241,6 +241,14 @@ bool loadFeaturesPerView(feature::FeaturesPerView& featuresPerView, std::vector featuresFolders = sfmData.getFeaturesFolders(); // add sfm features folders featuresFolders.insert(featuresFolders.end(), folders.begin(), folders.end()); // add user features folders + ALICEVISION_LOG_DEBUG("List of provided feature folders:"); + for (auto it = folders.begin(); it != folders.end(); ++it) + ALICEVISION_LOG_DEBUG("\t - " << *it); + + ALICEVISION_LOG_DEBUG("List of feature folders to load:"); + for (auto it = featuresFolders.begin(); it != featuresFolders.end(); ++it) + ALICEVISION_LOG_DEBUG("\t - " << *it); + auto progressDisplay = system::createConsoleProgressDisplay(sfmData.getViews().size(), std::cout, "Loading features\n");