@@ -215,7 +215,8 @@ ObservationsPerView getObservationsPerViews(SfMData& sfmData)
215215 return observationsPerView;
216216}
217217
218- bool filterLandmarks (SfMData& sfmData, double radiusScale, bool useFeatureScale, int minNbObservationsPerLandmark)
218+ bool filterLandmarks (SfMData& sfmData, double radiusScale, bool useFeatureScale, int minNbObservationsPerLandmark,
219+ int nbNeighbors3D, int maxNbObservationsPerLandmark)
219220{
220221 const auto initialNbLandmarks = sfmData.getLandmarks ().size ();
221222 std::vector<Landmark> landmarksData (initialNbLandmarks);
@@ -255,11 +256,8 @@ bool filterLandmarks(SfMData& sfmData, double radiusScale, bool useFeatureScale,
255256 tree.buildIndex ();
256257 ALICEVISION_LOG_INFO (" KdTree created for " << landmarksData.size () << " points." );
257258
258- // TODO as parameter
259- int nbNeighbors3D = 10 ;
260259 // note that the landmark is a neighbor to itself with zero distance, hence the +/- 1
261260 int nbNeighbors_ = std::min (nbNeighbors3D, static_cast <int >(landmarksData.size () - 1 )) + 1 ;
262-
263261 // contains the observing view ids and neighbors for each landmark
264262 std::vector<std::pair<std::vector<IndexT>, std::vector<size_t >>> viewData (landmarksData.size ());
265263
@@ -287,8 +285,6 @@ bool filterLandmarks(SfMData& sfmData, double radiusScale, bool useFeatureScale,
287285
288286 std::vector<bool > toRemove (landmarksData.size (), false );
289287 size_t nbToRemove = 0 ;
290- // TODO as parameter
291- int maxNbObservationsPerLandmark = 2 ;
292288 const auto initialNbLandmarks = sfmData.getLandmarks ().size ();
293289#pragma omp parallel for reduction(+ : nbToRemove)
294290 for (auto i = 0 ; i < landmarksData.size (); i++)
@@ -552,7 +548,6 @@ bool filterObservations3D(SfMData& sfmData, int maxNbObservationsPerLandmark, in
552548 std::vector<std::vector<double >> viewScoresData_t (landmarksData.size ());
553549 for (auto i = 0 ; i < nbIterations; i++)
554550 {
555- ALICEVISION_LOG_INFO (" Iteration " << i << " ..." );
556551#pragma omp parallel for
557552 for (auto id = 0 ; id < landmarksData.size (); id++)
558553 {
@@ -603,23 +598,44 @@ bool filterObservations3D(SfMData& sfmData, int maxNbObservationsPerLandmark, in
603598 {
604599 // normalize score and apply influence factor
605600 viewScores_acc[j] *= neighborsInfluence / viewScores_total;
606- // combine weghted neighbor scores and the landmark's own scores
601+ // combine weighted neighbor scores and the landmark's own scores
607602 viewScores_acc[j] += (1 - neighborsInfluence) * viewScores[j];
608603 }
604+ // dampen scores of non-chosen observations
605+ if (viewScores_acc.size () <= maxNbObservationsPerLandmark)
606+ continue ;
607+ // sort by descending view score order
608+ std::vector<size_t > idx (viewScores_acc.size ());
609+ std::iota (idx.begin (), idx.end (), 0 );
610+ std::stable_sort (idx.begin (), idx.end (),
611+ [&v = viewScores_acc](size_t i1, size_t i2) { return v[i1] > v[i2]; });
612+ viewScores_total = 1 .;
613+ for (auto j = maxNbObservationsPerLandmark; j < viewScores_acc.size (); j++)
614+ {
615+ const double & v = 0.5 * viewScores_acc[j];
616+ viewScores_acc[j] = v;
617+ viewScores_total -= v;
618+ }
619+ // re-normalize
620+ for (auto j = 0 ; j < viewScores_acc.size (); j++)
621+ viewScores_acc[j] /= viewScores_total;
609622 }
610623 // update scores at end of iteration
611624 double error = 0 .;
612625#pragma omp parallel for reduction(+:error)
613626 for (auto id = 0 ; id < landmarksData.size (); id++)
614627 {
615- double error_j = 0 .;
616- for (auto j = 0 ; j < viewScoresData_t[id].size (); j++)
628+ // compute MSE
617629 {
618- const auto & v = viewScoresData_t[id][j] - viewScoresData[id].second [j];
619- error_j += v * v;
630+ double error_j = 0 .;
631+ for (auto j = 0 ; j < viewScoresData_t[id].size (); j++)
632+ {
633+ const auto & v = viewScoresData_t[id][j] - viewScoresData[id].second [j];
634+ error_j += v * v;
635+ }
636+ error_j /= viewScoresData_t[id].size ();
637+ error += error_j;
620638 }
621- error_j /= viewScoresData_t[id].size ();
622- error += error_j;
623639 viewScoresData[id].second = std::move (viewScoresData_t[id]);
624640 }
625641 error /= landmarksData.size ();
@@ -850,7 +866,8 @@ int aliceVision_main(int argc, char *argv[])
850866 if (radiusScale > 0 || minNbObservationsPerLandmark > 0 )
851867 {
852868 ALICEVISION_LOG_INFO (" Filtering landmarks: started." );
853- filterLandmarks (sfmData, radiusScale, useFeatureScale, minNbObservationsPerLandmark);
869+ filterLandmarks (sfmData, radiusScale, useFeatureScale, minNbObservationsPerLandmark, nbNeighbors3D,
870+ maxNbObservationsPerLandmark);
854871 ALICEVISION_LOG_INFO (" Filtering landmarks: done." );
855872 }
856873
0 commit comments