Skip to content

Commit 60d7e10

Browse files
committed
[filterSfM] add params + remove deprecated function
1 parent 20f9f5e commit 60d7e10

File tree

1 file changed

+22
-67
lines changed

1 file changed

+22
-67
lines changed

src/software/pipeline/main_filterSfM.cpp

Lines changed: 22 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -249,64 +249,8 @@ bool filterLandmarks(SfMData& sfmData, double radiusScale, bool useFeatureScale,
249249
return true;
250250
}
251251

252-
bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark)
253-
{
254-
std::vector<Landmark*> landmarksData(sfmData.getLandmarks().size());
255-
{
256-
size_t i = 0;
257-
for(auto& it : sfmData.getLandmarks())
258-
{
259-
landmarksData[i++] = &it.second;
260-
}
261-
}
262-
263-
#pragma omp parallel for
264-
for(auto i = 0; i < landmarksData.size(); i++)
265-
{
266-
sfmData::Landmark& landmark = *landmarksData[i];
267-
268-
// check number of observations
269-
if(landmark.observations.size() <= maxNbObservationsPerLandmark)
270-
continue;
271-
272-
// // check angle between observations
273-
// if(!checkLandmarkMinObservationAngle(sfmData, landmark, minObservationAngle))
274-
275-
// compute observation scores
276-
277-
std::vector<std::pair<double, IndexT>> observationScores;
278-
observationScores.reserve(landmark.observations.size());
279-
280-
for(const auto& observationPair : landmark.observations)
281-
{
282-
const IndexT viewId = observationPair.first;
283-
const sfmData::View& view = *(sfmData.getViews().at(viewId));
284-
const geometry::Pose3 pose = sfmData.getPose(view).getTransform();
285-
286-
observationScores.push_back(std::pair<double, IndexT>(
287-
(pose.center() - landmark.X).squaredNorm(),
288-
viewId
289-
));
290-
}
291-
292-
// sort observations by ascending score order
293-
std::stable_sort(observationScores.begin(), observationScores.end());
294-
// take only best observations
295-
observationScores.resize(maxNbObservationsPerLandmark);
296-
297-
// replace the observations
298-
Observations filteredObservations;
299-
for(const auto& observationScorePair : observationScores)
300-
{
301-
filteredObservations[observationScorePair.second] = landmark.observations[observationScorePair.second];
302-
}
303-
landmark.observations = std::move(filteredObservations);
304-
}
305-
return true;
306-
}
307-
308-
bool filterObservations2(SfMData& sfmData, int maxNbObservationsPerLandmark, int nbNeighbors = 10, int nbIterations = 5,
309-
double fraction = 0.5)
252+
bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int nbNeighbors, double neighborsInfluence,
253+
int nbIterations)
310254
{
311255
std::vector<Landmark*> landmarksData(sfmData.getLandmarks().size());
312256
{
@@ -371,16 +315,18 @@ bool filterObservations2(SfMData& sfmData, int maxNbObservationsPerLandmark, int
371315
KdTree tree(3, dataAdaptor, nanoflann::KDTreeSingleIndexAdaptorParams(MAX_LEAF_ELEMENTS));
372316
tree.buildIndex();
373317
ALICEVISION_LOG_INFO("KdTree created for " << landmarksData.size() << " points.");
318+
// note that the landmark is a neighbor to itself with zero distance, hence the +/- 1
319+
int nbNeighbors_ = std::min(nbNeighbors, static_cast<int>(landmarksData.size() - 1)) + 1;
374320
std::vector<std::pair<std::vector<size_t>, std::vector<double>>> neighborsData(landmarksData.size());
375321
#pragma omp parallel for
376322
for(auto i = 0; i < landmarksData.size(); i++)
377323
{
378324
const sfmData::Landmark& landmark = *landmarksData[i];
379325
auto& [indices_, weights_] = neighborsData[i];
380-
// a landmark is a neighbor to itself with zero distance
381-
indices_.resize(nbNeighbors + 1);
382-
weights_.resize(nbNeighbors + 1);
383-
tree.knnSearch(landmark.X.data(), nbNeighbors + 1, &indices_[0], &weights_[0]);
326+
indices_.resize(nbNeighbors_);
327+
weights_.resize(nbNeighbors_);
328+
tree.knnSearch(landmark.X.data(), nbNeighbors_, &indices_[0], &weights_[0]);
329+
// a landmark is a neighbor to itself with zero distance, remove it
384330
indices_.erase(indices_.begin());
385331
weights_.erase(weights_.begin());
386332
double total = 0.;
@@ -442,8 +388,8 @@ bool filterObservations2(SfMData& sfmData, int maxNbObservationsPerLandmark, int
442388
}
443389
for(auto j = 0; j < viewScores_acc.size(); j++)
444390
{
445-
viewScores_acc[j] *= fraction / viewScores_total;
446-
viewScores_acc[j] += (1 - fraction) * viewScores[j];
391+
viewScores_acc[j] *= neighborsInfluence / viewScores_total;
392+
viewScores_acc[j] += (1 - neighborsInfluence) * viewScores[j];
447393
}
448394
}
449395
#pragma omp parallel for
@@ -485,13 +431,15 @@ int aliceVision_main(int argc, char *argv[])
485431
{
486432
// command-line parameters
487433

488-
// std::string verboseLevel = system::EVerboseLevel_enumToString(system::Logger::getDefaultVerboseLevel());
489434
std::string inputSfmFilename;
490435
std::string outputSfmFilename;
491436
int maxNbObservationsPerLandmark = 2;
492437
int minNbObservationsPerLandmark = 5;
493438
double radiusScale = 2;
494439
bool useFeatureScale = true;
440+
int nbNeighbors = 10;
441+
double neighborsInfluence = 0.5;
442+
int nbIterations = 5;
495443

496444
// user optional parameters
497445
std::vector<std::string> featuresFolders;
@@ -515,14 +463,21 @@ int aliceVision_main(int argc, char *argv[])
515463
"Scale factor applied to pixel size based radius filter applied to landmarks.")
516464
("useFeatureScale", po::value<bool>(&useFeatureScale)->default_value(useFeatureScale),
517465
"If true, use feature scale for computing pixel size. Otherwise, use a scale of 1 pixel.")
466+
("nbNeighbors", po::value<int>(&nbNeighbors)->default_value(nbNeighbors),
467+
"Number of neighbor landmarks used in making the decision for best observations.")
468+
("neighborsInfluence", po::value<double>(&neighborsInfluence)->default_value(neighborsInfluence),
469+
"Specifies how much influential the neighbors are in selecting the best observations."
470+
"Between 0. and 1., the closer to 1., the more influencial the neighborhood is.")
471+
("nbIterations", po::value<int>(&nbIterations)->default_value(nbIterations),
472+
"Number of iterations to propagate neighbors information.")
518473
("featuresFolders,f", po::value<std::vector<std::string>>(&featuresFolders)->multitoken(),
519474
"Path to folder(s) containing the extracted features.")
520475
("matchesFolders,m", po::value<std::vector<std::string>>(&matchesFolders)->multitoken(),
521476
"Path to folder(s) in which computed matches are stored.")
522477
("describerTypes,d", po::value<std::string>(&describerTypesName)->default_value(describerTypesName),
523478
feature::EImageDescriberType_informations().c_str());
524479

525-
CmdLine cmdline("AliceVision SfM filtering.");
480+
CmdLine cmdline("AliceVision SfM filtering."); // TODO add description
526481
cmdline.add(requiredParams);
527482
cmdline.add(optionalParams);
528483
if (!cmdline.execute(argc, argv))
@@ -557,7 +512,7 @@ int aliceVision_main(int argc, char *argv[])
557512
if(maxNbObservationsPerLandmark > 0)
558513
{
559514
ALICEVISION_LOG_INFO("Filtering observations: started.");
560-
filterObservations2(sfmData, maxNbObservationsPerLandmark);
515+
filterObservations(sfmData, maxNbObservationsPerLandmark, nbNeighbors, neighborsInfluence, nbIterations);
561516
ALICEVISION_LOG_INFO("Filtering observations: done.");
562517
}
563518

0 commit comments

Comments
 (0)