diff --git a/meshroom/aliceVision/SfmBootstrapping.py b/meshroom/aliceVision/SfmBootstrapping.py index 7924ef8cd3..2d5bd9df78 100644 --- a/meshroom/aliceVision/SfmBootstrapping.py +++ b/meshroom/aliceVision/SfmBootstrapping.py @@ -1,4 +1,4 @@ -__version__ = "4.0" +__version__ = "4.1" from meshroom.core import desc from meshroom.core.utils import VERBOSE_LEVEL @@ -37,13 +37,21 @@ class SfMBootStrapping(desc.AVCommandLineNode): value="", ), desc.FloatParam( - name="minAngleInitialPair", - label="Min Angle Initial Pair", - description="Minimum angle for the initial pair.", + name="minAngleSoftInitialPair", + label="Min Angle Initial Pair (Soft)", + description="Pair score is downgraded heavily if angle is under this value", value=5.0, range=(0.1, 10.0, 0.1), advanced=True, ), + desc.FloatParam( + name="minAngleHardInitialPair", + label="Min Angle Initial Pair (Hard)", + description="Minimum angle for the initial pair validation.", + value=1.0, + range=(0.1, 10.0, 0.1), + advanced=True, + ), desc.FloatParam( name="maxAngleInitialPair", label="Max Angle Initial Pair", diff --git a/meshroom/aliceVision/SfmExpanding.py b/meshroom/aliceVision/SfmExpanding.py index 5fadd74798..1e4eac264b 100644 --- a/meshroom/aliceVision/SfmExpanding.py +++ b/meshroom/aliceVision/SfmExpanding.py @@ -1,4 +1,4 @@ -__version__ = "2.0" +__version__ = "2.1" from meshroom.core import desc from meshroom.core.utils import VERBOSE_LEVEL @@ -131,11 +131,19 @@ class SfMExpanding(desc.AVCommandLineNode): desc.FloatParam( name="maxReprojectionError", label="Max Reprojection Error", - description="Maximum reprojection error.", + description="Maximum reprojection error in the bundle verification step.", value=4.0, range=(0.1, 10.0, 0.1), advanced=True, ), + desc.FloatParam( + name="maxTriangulationError", + label="Max Triangulation Error", + description="Maximum reprojection error in the triangulation process.", + value=8.0, + range=(0.1, 10.0, 0.1), + advanced=True, + ), desc.BoolParam( name="lockAllIntrinsics", label="Lock All Intrinsic Camera Parameters", diff --git a/meshroom/cameraTrackingExperimental.mg b/meshroom/cameraTrackingExperimental.mg index e33e363178..b6af7d8058 100644 --- a/meshroom/cameraTrackingExperimental.mg +++ b/meshroom/cameraTrackingExperimental.mg @@ -27,9 +27,9 @@ "Publish": "1.3", "RelativePoseEstimating": "3.0", "ScenePreview": "2.0", - "SfMBootStrapping": "4.0", + "SfMBootStrapping": "4.1", "SfMColorizing": "1.0", - "SfMExpanding": "2.0", + "SfMExpanding": "2.1", "SfMTransfer": "2.1", "SfMTransform": "3.1", "SfMTriangulation": "1.0", diff --git a/meshroom/cameraTrackingWithoutCalibrationExperimental.mg b/meshroom/cameraTrackingWithoutCalibrationExperimental.mg index 16b7a74c05..1ecc5c05a7 100644 --- a/meshroom/cameraTrackingWithoutCalibrationExperimental.mg +++ b/meshroom/cameraTrackingWithoutCalibrationExperimental.mg @@ -26,9 +26,9 @@ "Publish": "1.3", "RelativePoseEstimating": "3.0", "ScenePreview": "2.0", - "SfMBootStrapping": "4.0", + "SfMBootStrapping": "4.1", "SfMColorizing": "1.0", - "SfMExpanding": "2.0", + "SfMExpanding": "2.1", "SfMTransfer": "2.1", "SfMTransform": "3.1", "SfMTriangulation": "1.0", diff --git a/meshroom/photogrammetryAndCameraTrackingExperimental.mg b/meshroom/photogrammetryAndCameraTrackingExperimental.mg index 0a78a73e21..fbdd4bed26 100644 --- a/meshroom/photogrammetryAndCameraTrackingExperimental.mg +++ b/meshroom/photogrammetryAndCameraTrackingExperimental.mg @@ -27,9 +27,9 @@ "Publish": "1.3", "RelativePoseEstimating": "3.0", "ScenePreview": "2.0", - "SfMBootStrapping": "4.0", + "SfMBootStrapping": "4.1", "SfMColorizing": "1.0", - "SfMExpanding": "2.0", + "SfMExpanding": "2.1", "SfMTransfer": "2.1", "SfMTransform": "3.1", "Texturing": "6.0", diff --git a/meshroom/photogrammetryExperimental.mg b/meshroom/photogrammetryExperimental.mg index f1f2c7f6af..78ec1758c1 100644 --- a/meshroom/photogrammetryExperimental.mg +++ b/meshroom/photogrammetryExperimental.mg @@ -15,9 +15,9 @@ "Meshing": "7.0", "Publish": "1.3", "RelativePoseEstimating": "3.0", - "SfMBootStrapping": "4.0", + "SfMBootStrapping": "4.1", "SfMColorizing": "1.0", - "SfMExpanding": "2.0", + "SfMExpanding": "2.1", "SfMTransform": "3.1", "Texturing": "6.0", "TracksBuilding": "1.0" diff --git a/src/aliceVision/multiview/triangulation/TriangulationSphericalKernel.hpp b/src/aliceVision/multiview/triangulation/TriangulationSphericalKernel.hpp index 8dcc61422e..e39a70576c 100644 --- a/src/aliceVision/multiview/triangulation/TriangulationSphericalKernel.hpp +++ b/src/aliceVision/multiview/triangulation/TriangulationSphericalKernel.hpp @@ -21,16 +21,19 @@ class TriangulationSphericalKernel : public robustEstimation::IRansacKernel & observations, + const std::vector & weights, const std::vector& poses, std::vector> & intrinsics ) : _poses(poses) , _intrinsics(intrinsics) + , _weights(weights) { for (int id = 0; id < observations.size(); id++) { @@ -134,10 +137,10 @@ class TriangulationSphericalKernel : public robustEstimation::IRansacKernelresidual(_poses[sample], X, _observations[sample], false); - return residual.norm(); + return residual.norm() * w; } /** @@ -217,6 +222,7 @@ class TriangulationSphericalKernel : public robustEstimation::IRansacKernel _lifted; std::vector _observations; + std::vector _weights; const std::vector _poses; const std::vector> _intrinsics; multiview::TriangulateNViewsSphericalSolver _solver; diff --git a/src/aliceVision/sfm/pipeline/bootstrapping/PairsScoring.cpp b/src/aliceVision/sfm/pipeline/bootstrapping/PairsScoring.cpp index aa59b4af28..3ce3d4da96 100644 --- a/src/aliceVision/sfm/pipeline/bootstrapping/PairsScoring.cpp +++ b/src/aliceVision/sfm/pipeline/bootstrapping/PairsScoring.cpp @@ -18,7 +18,8 @@ IndexT findBestPair(const sfmData::SfMData & sfmData, const track::TracksPerView & tracksPerView, const std::set & filterIn, const std::set & filterOut, - double minAngle, + double hardMinAngle, + double softMinAngle, double maxAngle) { IndexT bestPair = UndefinedIndexT; @@ -74,26 +75,30 @@ IndexT findBestPair(const sfmData::SfMData & sfmData, continue; } - if (radianToDegree(angle) > maxAngle) + double degrees = radianToDegree(angle); + if (degrees > maxAngle) { continue; } - + if (degrees < hardMinAngle) + { + continue; + } const sfmData::View & vref = sfmData.getView(pair.reference); const sfmData::View & vnext = sfmData.getView(pair.next); int maxref = std::max(vref.getImage().getWidth(), vref.getImage().getHeight()); int maxnext = std::max(vnext.getImage().getWidth(), vnext.getImage().getHeight()); - double refScore = sfm::ExpansionPolicyLegacy::computeScore(tracksMap, usedTracks, pair.reference, maxref, 5); double nextScore = sfm::ExpansionPolicyLegacy::computeScore(tracksMap, usedTracks, pair.next, maxnext, 5); double score = std::min(refScore, nextScore) * std::max(1e-12, radianToDegree(angle)); - //If the angle is too small, then dramatically reduce its chances - if (radianToDegree(angle) < minAngle) + + //If the angle is too small, then dramatically reduce its chances + if (degrees < softMinAngle) { score = -1.0 / score; } diff --git a/src/aliceVision/sfm/pipeline/bootstrapping/PairsScoring.hpp b/src/aliceVision/sfm/pipeline/bootstrapping/PairsScoring.hpp index b60d2f477a..f752b9fbb8 100644 --- a/src/aliceVision/sfm/pipeline/bootstrapping/PairsScoring.hpp +++ b/src/aliceVision/sfm/pipeline/bootstrapping/PairsScoring.hpp @@ -22,7 +22,8 @@ namespace sfm { * @param tracksPerView tracks grouped by views * @param filterIn pair must contains one of the views inside this set (if non empty) * @param filterout pair must NOT contains one of the views inside this set (if non empty) -* @param minAngle minimal angle allowed +* @param hardMinAngle minimal angle allowed (rejected) +* @param softMinAngle minimal angle allowed (tolerated, but heavily downgraded) * @param maxAngle maximal angle allowed * @return index in "pairs" of the best pair or UndefinedIndexT if no pair found */ @@ -32,7 +33,8 @@ IndexT findBestPair(const sfmData::SfMData & sfmData, const track::TracksPerView & tracksPerView, const std::set & filterIn, const std::set & filterOut, - double minAngle, + double hardMinAngle, + double softMinAngle, double maxAngle); } diff --git a/src/aliceVision/sfm/pipeline/expanding/ExpansionChunk.hpp b/src/aliceVision/sfm/pipeline/expanding/ExpansionChunk.hpp index 3737d087bc..4fa12289de 100644 --- a/src/aliceVision/sfm/pipeline/expanding/ExpansionChunk.hpp +++ b/src/aliceVision/sfm/pipeline/expanding/ExpansionChunk.hpp @@ -69,7 +69,6 @@ class ExpansionChunk /** * @brief set the maximal error allowed for ransac resection module * @param error the error value or <= 0 for automatic decision - * @param count the number of points */ void setResectionMaxError(double error) { @@ -89,6 +88,15 @@ class ExpansionChunk _triangulationMinPoints = count; } + /** + * @brief set the maximal reprojection error in the triangulation process. + * @param count the number of points + */ + void setTriangulationMaxError(double error) + { + _maxTriangulationError = error; + } + /** * @brief set the minimal allowed parallax degree for triangulation * @param angle the angle in DEGREES diff --git a/src/aliceVision/sfm/pipeline/expanding/SfmTriangulation.cpp b/src/aliceVision/sfm/pipeline/expanding/SfmTriangulation.cpp index d7ab3746d3..75ea516b0b 100644 --- a/src/aliceVision/sfm/pipeline/expanding/SfmTriangulation.cpp +++ b/src/aliceVision/sfm/pipeline/expanding/SfmTriangulation.cpp @@ -106,6 +106,7 @@ bool SfmTriangulation::processTrack( { feature::EImageDescriberType descType = track.descType; + std::vector weights; std::vector observations; std::vector> intrinsics; std::vector poses; @@ -126,6 +127,9 @@ bool SfmTriangulation::processTrack( observations.push_back(coords); intrinsics.push_back(intrinsic); poses.push_back(pose); + + //Weight is dependent on the feature scale + weights.push_back(1.0 / trackItem.scale); indexedViewIds.push_back(viewId); } @@ -135,7 +139,7 @@ bool SfmTriangulation::processTrack( robustEstimation::MatrixModel model; std::vector inliers; robustEstimation::ScoreEvaluator scorer(_maxError); - multiview::TriangulationSphericalKernel kernel(observations, poses, intrinsics); + multiview::TriangulationSphericalKernel kernel(observations, weights, poses, intrinsics); if (observations.size() <= 0) { diff --git a/src/software/pipeline/main_sfmBootstrapping.cpp b/src/software/pipeline/main_sfmBootstrapping.cpp index a2b0403905..2b03cf6ca1 100644 --- a/src/software/pipeline/main_sfmBootstrapping.cpp +++ b/src/software/pipeline/main_sfmBootstrapping.cpp @@ -42,7 +42,7 @@ // These constants define the current software version. // They must be updated when the command line is changed. #define ALICEVISION_SOFTWARE_VERSION_MAJOR 4 -#define ALICEVISION_SOFTWARE_VERSION_MINOR 0 +#define ALICEVISION_SOFTWARE_VERSION_MINOR 1 using namespace aliceVision; @@ -136,7 +136,8 @@ int aliceVision_main(int argc, char** argv) // user optional parameters const double maxEpipolarDistance = 4.0; - double minAngle = 5.0; + double minAngleHard = 1.0; + double minAngleSoft = 5.0; double maxAngle = 40.0; std::pair initialPairString("", ""); @@ -155,7 +156,8 @@ int aliceVision_main(int argc, char** argv) po::options_description optionalParams("Required parameters"); optionalParams.add_options() ("outputViewsAndPoses", po::value(&outputSfMViewsAndPoses)->default_value(outputSfMViewsAndPoses), "Path to the output SfMData file (with only views and poses).") - ("minAngleInitialPair", po::value(&minAngle)->default_value(minAngle), "Minimum angle for the initial pair.") + ("minAngleSoftInitialPair", po::value(&minAngleSoft)->default_value(minAngleSoft), "Minimum angle for the initial pair (Score is downgraded heavily if angle is under this value).") + ("minAngleHardInitialPair", po::value(&minAngleHard)->default_value(minAngleHard), "Minimum angle for the initial pair validation.") ("maxAngleInitialPair", po::value(&maxAngle)->default_value(maxAngle), "Maximum angle for the initial pair.") ("meshFilename,t", po::value(&meshFilename)->required(), "Mesh object file.") ("initialPairA", po::value(&initialPairString.first)->default_value(initialPairString.first), "UID or filepath or filename of the first image.") @@ -342,7 +344,7 @@ int aliceVision_main(int argc, char** argv) IndexT bestPairId = findBestPair(sfmData, reconstructedPairs, tracksHandler.getAllTracks(), tracksHandler.getTracksPerView(), filterIn, filterOut, - minAngle, maxAngle); + minAngleHard, minAngleSoft, maxAngle); if (bestPairId == UndefinedIndexT) { diff --git a/src/software/pipeline/main_sfmExpanding.cpp b/src/software/pipeline/main_sfmExpanding.cpp index 4caed2c7f5..356aded1e1 100644 --- a/src/software/pipeline/main_sfmExpanding.cpp +++ b/src/software/pipeline/main_sfmExpanding.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 0 +#define ALICEVISION_SOFTWARE_VERSION_MINOR 1 using namespace aliceVision; @@ -97,6 +97,7 @@ int aliceVision_main(int argc, char** argv) double minAngleForTriangulation = 3.0; double minAngleForLandmark = 2.0; double maxReprojectionError = 4.0; + double maxTriangulationError = 8.0; bool lockAllIntrinsics = false; int minNbCamerasToRefinePrincipalPoint = 3; bool useRigConstraint = true; @@ -132,7 +133,8 @@ int aliceVision_main(int argc, char** argv) ("minNumberOfObservationsForTriangulation", po::value(&minNbObservationsForTriangulation)->default_value(minNbObservationsForTriangulation),"Minimum number of observations to triangulate a point") ("minAngleForTriangulation", po::value(&minAngleForTriangulation)->default_value(minAngleForTriangulation),"Minimum angle for triangulation.") ("minAngleForLandmark", po::value(&minAngleForLandmark)->default_value(minAngleForLandmark), "Minimum angle for landmark.") - ("maxReprojectionError", po::value(&maxReprojectionError)->default_value(maxReprojectionError), "Maximum reprojection error.") + ("maxTriangulationError", po::value(&maxTriangulationError)->default_value(maxTriangulationError), "Maximum reprojection error in the triangulation process.") + ("maxReprojectionError", po::value(&maxReprojectionError)->default_value(maxReprojectionError), "Maximum reprojection error in the bundle verification step.") ("lockAllIntrinsics", po::value(&lockAllIntrinsics)->default_value(lockAllIntrinsics), "Force lock of all camera intrinsic parameters, so they will not be refined during Bundle Adjustment.") ("minNbCamerasToRefinePrincipalPoint", po::value(&minNbCamerasToRefinePrincipalPoint)->default_value(minNbCamerasToRefinePrincipalPoint), "Minimal number of cameras to refine the principal point of the cameras (one of the intrinsic parameters of the camera). " @@ -242,6 +244,7 @@ int aliceVision_main(int argc, char** argv) expansionChunk->setExpansionHistoryHandler(expansionHistory); expansionChunk->setResectionMaxIterations(localizerEstimatorMaxIterations); expansionChunk->setResectionMaxError(localizerEstimatorError); + expansionChunk->setTriangulationMaxError(maxTriangulationError); expansionChunk->setTriangulationMinPoints(minNbObservationsForTriangulation); expansionChunk->setMinAngleTriangulation(minAngleForTriangulation); expansionChunk->setPointFetcherHandler(pointFetcherHandler);