Skip to content

Commit 126baff

Browse files
almaroukcbentejac
authored andcommitted
[incrementalSfM] add option to enable/disable track merging based on duplicate features
1 parent fdd68ed commit 126baff

File tree

3 files changed

+62
-53
lines changed

3 files changed

+62
-53
lines changed

src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,10 @@ std::size_t ReconstructionEngine_sequentialSfM::fuseMatchesIntoTracks()
246246
const aliceVision::matching::PairwiseMatches& matches = *_pairwiseMatches;
247247

248248
ALICEVISION_LOG_DEBUG("Track building");
249-
tracksBuilder.build(matches, _featuresPerView->getData());
249+
if (_params.mergeTracks)
250+
tracksBuilder.build(matches, _featuresPerView->getData());
251+
else
252+
tracksBuilder.build(matches);
250253

251254
ALICEVISION_LOG_DEBUG("Track filtering");
252255
tracksBuilder.filter(_params.filterTrackForks, _params.minInputTrackLength);

src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class ReconstructionEngine_sequentialSfM : public ReconstructionEngine
6363
EFeatureConstraint featureConstraint = EFeatureConstraint::BASIC;
6464
float minAngleInitialPair = 5.0f;
6565
float maxAngleInitialPair = 40.0f;
66+
bool mergeTracks = false;
6667
bool filterTrackForks = true;
6768
robustEstimation::ERobustEstimator localizerEstimator = robustEstimation::ERobustEstimator::ACRANSAC;
6869
double localizerEstimatorError = std::numeric_limits<double>::infinity();

src/software/pipeline/main_incrementalSfM.cpp

+57-52
Original file line numberDiff line numberDiff line change
@@ -107,93 +107,98 @@ int aliceVision_main(int argc, char **argv)
107107
po::options_description optionalParams("Optional parameters");
108108
optionalParams.add_options()
109109
("featuresFolders,f", po::value<std::vector<std::string>>(&featuresFolders)->multitoken(),
110-
"Path to folder(s) containing the extracted features.")
110+
"Path to folder(s) containing the extracted features.")
111111
("matchesFolders,m", po::value<std::vector<std::string>>(&matchesFolders)->multitoken(),
112-
"Path to folder(s) in which computed matches are stored.")
112+
"Path to folder(s) in which computed matches are stored.")
113113
("outputViewsAndPoses", po::value<std::string>(&outputSfMViewsAndPoses)->default_value(outputSfMViewsAndPoses),
114-
"Path to the output SfMData file (with only views and poses).")
114+
"Path to the output SfMData file (with only views and poses).")
115115
("extraInfoFolder", po::value<std::string>(&extraInfoFolder)->default_value(extraInfoFolder),
116-
"Folder for intermediate reconstruction files and additional reconstruction information files.")
116+
"Folder for intermediate reconstruction files and additional reconstruction information files.")
117117
("describerTypes,d", po::value<std::string>(&describerTypesName)->default_value(describerTypesName),
118-
feature::EImageDescriberType_informations().c_str())
118+
feature::EImageDescriberType_informations().c_str())
119119
("interFileExtension", po::value<std::string>(&sfmParams.sfmStepFileExtension)->default_value(sfmParams.sfmStepFileExtension),
120-
"Extension of the intermediate file export.")
120+
"Extension of the intermediate file export.")
121121
("maxNumberOfMatches", po::value<int>(&maxNbMatches)->default_value(maxNbMatches),
122-
"Maximum number of matches per image pair (and per feature type). "
123-
"This can be useful to have a quick reconstruction overview. 0 means no limit.")
122+
"Maximum number of matches per image pair (and per feature type). "
123+
"This can be useful to have a quick reconstruction overview. 0 means no limit.")
124124
("minNumberOfMatches", po::value<int>(&minNbMatches)->default_value(minNbMatches),
125-
"Minimum number of matches per image pair (and per feature type). "
126-
"This can be useful to have a meaningful reconstruction with accurate keypoints. 0 means no limit.")
125+
"Minimum number of matches per image pair (and per feature type). "
126+
"This can be useful to have a meaningful reconstruction with accurate keypoints. 0 means no limit.")
127127
("minInputTrackLength", po::value<int>(&sfmParams.minInputTrackLength)->default_value(sfmParams.minInputTrackLength),
128-
"Minimum track length in input of SfM.")
128+
"Minimum track length in input of SfM.")
129129
("minAngleForTriangulation", po::value<double>(&sfmParams.minAngleForTriangulation)->default_value(sfmParams.minAngleForTriangulation),
130-
"Minimum angle for triangulation.")
130+
"Minimum angle for triangulation.")
131131
("minAngleForLandmark", po::value<double>(&sfmParams.minAngleForLandmark)->default_value(sfmParams.minAngleForLandmark),
132-
"Minimum angle for landmark.")
132+
"Minimum angle for landmark.")
133133
("maxReprojectionError", po::value<double>(&sfmParams.maxReprojectionError)->default_value(sfmParams.maxReprojectionError),
134-
"Maximum reprojection error.")
134+
"Maximum reprojection error.")
135135
("minAngleInitialPair", po::value<float>(&sfmParams.minAngleInitialPair)->default_value(sfmParams.minAngleInitialPair),
136-
"Minimum angle for the initial pair.")
136+
"Minimum angle for the initial pair.")
137137
("maxAngleInitialPair", po::value<float>(&sfmParams.maxAngleInitialPair)->default_value(sfmParams.maxAngleInitialPair),
138-
"Maximum angle for the initial pair.")
139-
("minNumberOfObservationsForTriangulation", po::value<std::size_t>(&sfmParams.minNbObservationsForTriangulation)->default_value(sfmParams.minNbObservationsForTriangulation),
140-
"Minimum number of observations to triangulate a point.\n"
141-
"Set it to 3 (or more) reduces drastically the noise in the point cloud, but the number of final poses is a little bit reduced (from 1.5% to 11% on the tested datasets).\n"
142-
"Note: set it to 0 or 1 to use the old triangulation algorithm (using 2 views only) during resection.")
138+
"Maximum angle for the initial pair.")
139+
("minNumberOfObservationsForTriangulation",
140+
po::value<std::size_t>(&sfmParams.minNbObservationsForTriangulation)->default_value(sfmParams.minNbObservationsForTriangulation),
141+
"Minimum number of observations to triangulate a point.\n"
142+
"Set it to 3 (or more) reduces drastically the noise in the point cloud, but the number of final poses is a little bit reduced (from 1.5% to 11% "
143+
"on the tested datasets).\n"
144+
"Note: set it to 0 or 1 to use the old triangulation algorithm (using 2 views only) during resection.")
143145
("initialPairA", po::value<std::string>(&initialPairString.first)->default_value(initialPairString.first),
144-
"UID or filepath or filename of the first image.")
146+
"UID or filepath or filename of the first image.")
145147
("initialPairB", po::value<std::string>(&initialPairString.second)->default_value(initialPairString.second),
146-
"UID or filepath or filename of the second image.")
148+
"UID or filepath or filename of the second image.")
147149
("lockAllIntrinsics", po::value<bool>(&sfmParams.lockAllIntrinsics)->default_value(sfmParams.lockAllIntrinsics),
148-
"Force lock of all camera intrinsic parameters, so they will not be refined during Bundle Adjustment.")
150+
"Force lock of all camera intrinsic parameters, so they will not be refined during Bundle Adjustment.")
149151
("minNbCamerasToRefinePrincipalPoint", po::value<int>(&sfmParams.minNbCamerasToRefinePrincipalPoint)->default_value(sfmParams.minNbCamerasToRefinePrincipalPoint),
150-
"Minimal number of cameras to refine the principal point of the cameras (one of the intrinsic parameters of the camera). "
151-
"If we do not have enough cameras, the principal point in consider is considered in the center of the image. "
152-
"If minNbCamerasToRefinePrincipalPoint<=0, the principal point is never refined. "
153-
"If minNbCamerasToRefinePrincipalPoint==1, the principal point is always refined.")
152+
"Minimal number of cameras to refine the principal point of the cameras (one of the intrinsic parameters of the camera). "
153+
"If we do not have enough cameras, the principal point in consider is considered in the center of the image. "
154+
"If minNbCamerasToRefinePrincipalPoint<=0, the principal point is never refined. "
155+
"If minNbCamerasToRefinePrincipalPoint==1, the principal point is always refined.")
154156
("useLocalBA,l", po::value<bool>(&sfmParams.useLocalBundleAdjustment)->default_value(sfmParams.useLocalBundleAdjustment),
155-
"Enable/Disable the Local bundle adjustment strategy.\n"
156-
"It reduces the reconstruction time, especially for big datasets (500+ images).")
157+
"Enable/Disable the Local bundle adjustment strategy.\n"
158+
"It reduces the reconstruction time, especially for big datasets (500+ images).")
157159
("localBAGraphDistance", po::value<int>(&sfmParams.localBundelAdjustementGraphDistanceLimit)->default_value(sfmParams.localBundelAdjustementGraphDistanceLimit),
158-
"Graph-distance limit setting the Active region in the Local Bundle Adjustment strategy.")
160+
"Graph-distance limit setting the Active region in the Local Bundle Adjustment strategy.")
159161
("nbFirstUnstableCameras", po::value<std::size_t>(&sfmParams.nbFirstUnstableCameras)->default_value(sfmParams.nbFirstUnstableCameras),
160-
"Number of cameras for which the bundle adjustment is performed every single time a camera is added, leading to more stable "
161-
"results while the computations are not too expensive since there is not much data. Past this number, the bundle adjustment "
162-
"will only be performed once for N added cameras.")
162+
"Number of cameras for which the bundle adjustment is performed every single time a camera is added, leading to more stable "
163+
"results while the computations are not too expensive since there is not much data. Past this number, the bundle adjustment "
164+
"will only be performed once for N added cameras.")
163165
("maxImagesPerGroup", po::value<std::size_t>(&sfmParams.maxImagesPerGroup)->default_value(sfmParams.maxImagesPerGroup),
164-
"Maximum number of cameras that can be added before the bundle adjustment is performed. This prevents adding too much data "
165-
"at once without performing the bundle adjustment.")
166+
"Maximum number of cameras that can be added before the bundle adjustment is performed. This prevents adding too much data "
167+
"at once without performing the bundle adjustment.")
166168
("bundleAdjustmentMaxOutliers", po::value<int>(&sfmParams.bundleAdjustmentMaxOutliers)->default_value(sfmParams.bundleAdjustmentMaxOutliers),
167-
"Threshold for the maximum number of outliers allowed at the end of a bundle adjustment iteration."
168-
"Using a negative value for this threshold will disable BA iterations.")
169+
"Threshold for the maximum number of outliers allowed at the end of a bundle adjustment iteration."
170+
"Using a negative value for this threshold will disable BA iterations.")
169171
("localizerEstimator", po::value<robustEstimation::ERobustEstimator>(&sfmParams.localizerEstimator)->default_value(sfmParams.localizerEstimator),
170-
"Estimator type used to localize cameras (acransac (default), ransac, lsmeds, loransac, maxconsensus)")
172+
"Estimator type used to localize cameras (acransac (default), ransac, lsmeds, loransac, maxconsensus)")
171173
("localizerEstimatorError", po::value<double>(&sfmParams.localizerEstimatorError)->default_value(0.0),
172-
"Reprojection error threshold (in pixels) for the localizer estimator (0 for default value according to the estimator).")
174+
"Reprojection error threshold (in pixels) for the localizer estimator (0 for default value according to the estimator).")
173175
("localizerEstimatorMaxIterations", po::value<std::size_t>(&sfmParams.localizerEstimatorMaxIterations)->default_value(sfmParams.localizerEstimatorMaxIterations),
174-
"Max number of RANSAC iterations.")
176+
"Max number of RANSAC iterations.")
175177
("useOnlyMatchesFromInputFolder", po::value<bool>(&useOnlyMatchesFromInputFolder)->default_value(useOnlyMatchesFromInputFolder),
176-
"Use only matches from the input matchesFolder parameter.\n"
177-
"Matches folders previously added to the SfMData file will be ignored.")
178+
"Use only matches from the input matchesFolder parameter.\n"
179+
"Matches folders previously added to the SfMData file will be ignored.")
180+
("mergeTracks", po::value<bool>(&sfmParams.mergeTracks)->default_value(sfmParams.mergeTracks),
181+
"Enable/Disable the track merging. The merging between two tracks is made when they have duplicate features coming from the same original "
182+
"feature (same describer type, same 2D position in the same view, same scale, but different rotations and different feature id).\n")
178183
("filterTrackForks", po::value<bool>(&sfmParams.filterTrackForks)->default_value(sfmParams.filterTrackForks),
179-
"Enable/Disable the track forks removal. A track contains a fork when incoherent matches leads to multiple features in the same image for a single track.\n")
184+
"Enable/Disable the track forks removal. A track contains a fork when incoherent matches leads to multiple features in the same image for a "
185+
"single track.\n")
180186
("useRigConstraint", po::value<bool>(&sfmParams.rig.useRigConstraint)->default_value(sfmParams.rig.useRigConstraint),
181-
"Enable/Disable rig constraint.\n")
187+
"Enable/Disable rig constraint.\n")
182188
("rigMinNbCamerasForCalibration", po::value<int>(&sfmParams.rig.minNbCamerasForCalibration)->default_value(sfmParams.rig.minNbCamerasForCalibration),
183-
"Minimal number of cameras to start the calibration of the rig.\n")
189+
"Minimal number of cameras to start the calibration of the rig.\n")
184190
("lockScenePreviouslyReconstructed", po::value<bool>(&lockScenePreviouslyReconstructed)->default_value(lockScenePreviouslyReconstructed),
185-
"Lock/Unlock scene previously reconstructed.\n")
191+
"Lock/Unlock scene previously reconstructed.\n")
186192
("observationConstraint", po::value<EFeatureConstraint>(&sfmParams.featureConstraint)->default_value(sfmParams.featureConstraint),
187-
"Use of an observation constraint : basic, scale the observation or use of the covariance.\n")
193+
"Use of an observation constraint : basic, scale the observation or use of the covariance.\n")
188194
("computeStructureColor", po::value<bool>(&computeStructureColor)->default_value(computeStructureColor),
189-
"Compute each 3D point color.\n")
195+
"Compute each 3D point color.\n")
190196
("useAutoTransform", po::value<bool>(&useAutoTransform)->default_value(useAutoTransform),
191-
"Transform the result with the alignment method 'AUTO'.\n")
197+
"Transform the result with the alignment method 'AUTO'.\n")
192198
("randomSeed", po::value<int>(&randomSeed)->default_value(randomSeed),
193-
"This seed value will generate a sequence using a linear random generator. Set -1 to use a random seed.")
199+
"This seed value will generate a sequence using a linear random generator. Set -1 to use a random seed.")
194200
("logIntermediateSteps", po::value<bool>(&sfmParams.logIntermediateSteps)->default_value(logIntermediateSteps),
195-
"If set to true, the current state of the scene will be dumped as an SfMData file every 3 resections.")
196-
;
201+
"If set to true, the current state of the scene will be dumped as an SfMData file every 3 resections.");
197202

198203
CmdLine cmdline("Sequential/Incremental reconstruction.\n"
199204
"This program performs incremental SfM (Initial Pair Essential + Resection).\n"

0 commit comments

Comments
 (0)