diff --git a/src/aliceVision/sfm/pipeline/expanding/SfmBundle.cpp b/src/aliceVision/sfm/pipeline/expanding/SfmBundle.cpp index 224e26f50b..bd3e724714 100644 --- a/src/aliceVision/sfm/pipeline/expanding/SfmBundle.cpp +++ b/src/aliceVision/sfm/pipeline/expanding/SfmBundle.cpp @@ -1,4 +1,5 @@ // This file is part of the AliceVision project. +// Copyright (c) 2025 AliceVision contributors. // Copyright (c) 2024 AliceVision contributors. // This Source Code Form is subject to the terms of the Mozilla Public License, // v. 2.0. If a copy of the MPL was not distributed with this file, @@ -54,16 +55,20 @@ bool SfmBundle::cleanup(sfmData::SfMData & sfmData) // Remove landmarks without enough observed parallax const std::size_t nbOutliersAngleErr = removeOutliersWithAngleError(sfmData, _minAngleForLandmark); + // Remove constraints which are too far away from landmark + const std::size_t nbOutliersConstraints = removeConstraints(sfmData, _maxConstraintDistance); + // Remove poses without enough observations in an interative fashion const std::size_t nbOutliers = nbOutliersResidualErr + nbOutliersAngleErr; std::set removedViewsIdIteration; bool somethingErased = eraseUnstablePosesAndObservations(sfmData, _minPointsPerPose, _minTrackLength, &removedViewsIdIteration); - bool somethingChanged = /*somethingErased || */(nbOutliers > _bundleAdjustmentMaxOutlier); + bool somethingChanged = /*somethingErased || */(nbOutliers > _bundleAdjustmentMaxOutlier) || (nbOutliersConstraints > 0); ALICEVISION_LOG_INFO("SfmBundle::cleanup : "); ALICEVISION_LOG_INFO(" - nbOutliersResidualErr : " << nbOutliersResidualErr); ALICEVISION_LOG_INFO(" - nbOutliersAngleErr : " << nbOutliersAngleErr); + ALICEVISION_LOG_INFO(" - nbOutliersConstraints : " << nbOutliersConstraints); ALICEVISION_LOG_INFO(" - somethingErased : " << somethingErased); ALICEVISION_LOG_INFO(" - somethingChanged : " << somethingChanged); diff --git a/src/aliceVision/sfm/pipeline/expanding/SfmBundle.hpp b/src/aliceVision/sfm/pipeline/expanding/SfmBundle.hpp index 445617ff8f..9ae3b73212 100644 --- a/src/aliceVision/sfm/pipeline/expanding/SfmBundle.hpp +++ b/src/aliceVision/sfm/pipeline/expanding/SfmBundle.hpp @@ -1,4 +1,5 @@ // This file is part of the AliceVision project. +// Copyright (c) 2025 AliceVision contributors. // Copyright (c) 2024 AliceVision contributors. // This Source Code Form is subject to the terms of the Mozilla Public License, // v. 2.0. If a copy of the MPL was not distributed with this file, @@ -94,6 +95,7 @@ class SfmBundle EFeatureConstraint _featureConstraint = EFeatureConstraint::SCALE; double _maxReprojectionError = 4.0; double _minAngleForLandmark = 2.0; + double _maxConstraintDistance = 1.0; size_t _minTrackLength = 2; size_t _minPointsPerPose = 30; size_t _bundleAdjustmentMaxOutlier = 50; diff --git a/src/aliceVision/sfm/sfmFilters.cpp b/src/aliceVision/sfm/sfmFilters.cpp index bbe74e1a23..ba6b14aaf3 100644 --- a/src/aliceVision/sfm/sfmFilters.cpp +++ b/src/aliceVision/sfm/sfmFilters.cpp @@ -280,5 +280,46 @@ bool eraseUnstablePosesAndObservations(sfmData::SfMData& sfmData, return removedPoses || removedObservations; } +IndexT removeConstraints(sfmData::SfMData& sfmData, double maxDist) +{ + const auto & landmarks = sfmData.getLandmarks(); + auto & constraints = sfmData.getConstraintsPoint(); + + // Remove all constraints which are very far from associated landmark + + size_t count = 0; + auto itConstraints = constraints.begin(); + while (itConstraints != constraints.end()) + { + IndexT trackId = itConstraints->first; + + auto landmarkIt = landmarks.find(trackId); + + //If the associated landmark does not exists anymore, remove the constraint + if (landmarkIt == landmarks.end()) + { + itConstraints = constraints.erase(itConstraints); + count++; + continue; + } + + const Vec3 & lpt = landmarkIt->second.X; + double dist = (itConstraints->second.point - lpt).norm(); + + //Remove if the landmark is too far away + if (dist > maxDist) + { + itConstraints = constraints.erase(itConstraints); + count++; + } + else + { + ++itConstraints; + } + } + + return count; +} + } // namespace sfm } // namespace aliceVision diff --git a/src/aliceVision/sfm/sfmFilters.hpp b/src/aliceVision/sfm/sfmFilters.hpp index a2da677b2a..c5924dc4fa 100644 --- a/src/aliceVision/sfm/sfmFilters.hpp +++ b/src/aliceVision/sfm/sfmFilters.hpp @@ -42,6 +42,14 @@ IndexT removeOutliersWithPixelResidualError(sfmData::SfMData& sfmData, // Return the number of removed tracks IndexT removeOutliersWithAngleError(sfmData::SfMData& sfmData, const double dMinAcceptedAngle); +/** + * @Brief remove all point constraints which are too far away from their associated landmark + * @param sfmData the sfmData to update + * @param maxDist the maximal allowed distance between the landmark and the constraint + * @return the number of constraints removed + */ +IndexT removeConstraints(sfmData::SfMData& sfmData, const double maxDist); + bool eraseUnstablePoses(sfmData::SfMData& sfmData, const IndexT minPointsPerPose, std::set* outRemovedViewsId = NULL); bool eraseObservationsWithMissingPoses(sfmData::SfMData& sfmData, const IndexT minPointsPerLandmark);