Skip to content

Commit 26751bb

Browse files
committed
[filterSfM] add comments
1 parent 60e00cb commit 26751bb

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

src/software/pipeline/main_filterSfM.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ bool filterLandmarks(SfMData& sfmData, double radiusScale, bool useFeatureScale,
252252
bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int nbNeighbors, double neighborsInfluence,
253253
int nbIterations)
254254
{
255+
// store in vector for faster access
255256
std::vector<Landmark*> landmarksData(sfmData.getLandmarks().size());
256257
{
257258
size_t i = 0;
@@ -261,6 +262,7 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
261262
}
262263
}
263264

265+
// contains the observing view ids for each landmark with their corresponding scores
264266
std::vector<std::pair<std::vector<IndexT>, std::vector<double>>> viewScoresData(landmarksData.size());
265267

266268
ALICEVISION_LOG_INFO("Computing initial observation scores based on distance to observing view: started");
@@ -270,11 +272,11 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
270272
const sfmData::Landmark& landmark = *landmarksData[i];
271273

272274
// compute observation scores
273-
274275
const auto& nbObservations = landmark.observations.size();
275276
auto& [viewIds, viewScores] = viewScoresData[i];
276277
viewIds.reserve(nbObservations);
277278
viewScores.reserve(nbObservations);
279+
// accumulator for normalizing the scores
278280
double total = 0.;
279281
for(const auto& observationPair : landmark.observations)
280282
{
@@ -283,6 +285,7 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
283285
const geometry::Pose3 pose = sfmData.getPose(view).getTransform();
284286

285287
viewIds.push_back(viewId);
288+
// score is the inverse of distance to observations
286289
const auto& v = 1. / (pose.center() - landmark.X).squaredNorm();
287290
total += v;
288291
viewScores.push_back(v);
@@ -296,9 +299,12 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
296299

297300
// sort by ascending view id order
298301
// for consequent faster access
302+
303+
// indices that sort the view ids
299304
std::vector<size_t> idx(nbObservations);
300305
std::iota(idx.begin(), idx.end(), 0);
301306
std::stable_sort(idx.begin(), idx.end(), [&v = viewIds](size_t i1, size_t i2) { return v[i1] < v[i2]; });
307+
// apply sorting to both view ids and view scores for correspondance
302308
auto ids_temp = viewIds;
303309
auto scores_temp = viewScores;
304310
for(auto j = 0; j < nbObservations; j++)
@@ -317,6 +323,7 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
317323
ALICEVISION_LOG_INFO("KdTree created for " << landmarksData.size() << " points.");
318324
// note that the landmark is a neighbor to itself with zero distance, hence the +/- 1
319325
int nbNeighbors_ = std::min(nbNeighbors, static_cast<int>(landmarksData.size() - 1)) + 1;
326+
// contains the neighbor landmarks ids with their corresponding weights
320327
std::vector<std::pair<std::vector<size_t>, std::vector<double>>> neighborsData(landmarksData.size());
321328
#pragma omp parallel for
322329
for(auto i = 0; i < landmarksData.size(); i++)
@@ -329,12 +336,15 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
329336
// a landmark is a neighbor to itself with zero distance, remove it
330337
indices_.erase(indices_.begin());
331338
weights_.erase(weights_.begin());
339+
// accumulator used for normalisation
332340
double total = 0.;
333341
for(auto& w : weights_)
334342
{
343+
// weight is the inverse of distance between a landmark and its neighbor
335344
w = 1. / std::sqrt(w);
336345
total += w;
337346
}
347+
// normalize weights
338348
for(auto& w : weights_)
339349
{
340350
w /= total;
@@ -343,6 +353,7 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
343353
ALICEVISION_LOG_INFO("Computing landmark neighbors and distance-based weights: done");
344354

345355
ALICEVISION_LOG_INFO("Propagating neighbors observation scores: started");
356+
// new view scores at iteration t
346357
std::vector<std::vector<double>> viewScoresData_t(landmarksData.size());
347358
for(auto i = 0; i < nbIterations; i++)
348359
{
@@ -352,14 +363,17 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
352363
{
353364
const auto& [viewIds, viewScores] = viewScoresData[id];
354365
auto& viewScores_acc = viewScoresData_t[id];
366+
// initialize to zero, will first contain the weighted average scores of neighbors
355367
viewScores_acc.assign(viewScores.size(), 0.);
368+
// accumulator for normalisation
356369
double viewScores_total = 0.;
357370
auto& [indices_, weights_] = neighborsData[id];
358371
for(auto j = 0; j < nbNeighbors; j++)
359372
{
360373
const auto& neighborId = indices_[j];
361374
const auto& neighborWeight = weights_[j];
362375
const auto& [viewIds_neighbor, viewScores_neighbor] = viewScoresData[neighborId];
376+
// loop over common views
363377
auto viewIds_it = viewIds.begin();
364378
auto viewIds_neighbor_it = viewIds_neighbor.begin();
365379
auto viewScores_neighbor_it = viewScores_neighbor.begin();
@@ -373,6 +387,7 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
373387
}
374388
else
375389
{
390+
// if same view, accumulate weighted scores
376391
if(!(*viewIds_neighbor_it < *viewIds_it))
377392
{
378393
const auto& v = *viewScores_neighbor_it * neighborWeight;
@@ -388,10 +403,13 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
388403
}
389404
for(auto j = 0; j < viewScores_acc.size(); j++)
390405
{
406+
// normalize score and apply influence factor
391407
viewScores_acc[j] *= neighborsInfluence / viewScores_total;
408+
// combine weghted neighbor scores and the landmark's own scores
392409
viewScores_acc[j] += (1 - neighborsInfluence) * viewScores[j];
393410
}
394411
}
412+
// update scores at end of iteration
395413
#pragma omp parallel for
396414
for(auto id = 0; id < landmarksData.size(); id++)
397415
{
@@ -417,7 +435,7 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark, int
417435
std::iota(idx.begin(), idx.end(), 0);
418436
std::stable_sort(idx.begin(), idx.end(), [&v = viewScores](size_t i1, size_t i2) { return v[i1] > v[i2]; });
419437

420-
// replace the observations
438+
// keep only observations with best scores
421439
Observations filteredObservations;
422440
for(auto j = 0; j < maxNbObservationsPerLandmark; j++)
423441
{

0 commit comments

Comments
 (0)