1818
1919#include < boost/program_options.hpp>
2020#include < boost/filesystem.hpp>
21+ #include < boost/accumulators/accumulators.hpp>
22+ #include < boost/accumulators/statistics.hpp>
2123
2224#include < stdlib.h>
2325#include < stdio.h>
@@ -42,6 +44,7 @@ using namespace aliceVision::sfmDataIO;
4244
4345namespace po = boost::program_options;
4446namespace fs = boost::filesystem;
47+ using namespace boost ::accumulators;
4548
4649static const std::size_t MAX_LEAF_ELEMENTS = 64 ;
4750
@@ -173,7 +176,9 @@ bool prepareDenseScene(const SfMData& sfmData,
173176 bool saveMetadata,
174177 bool saveMatricesFiles,
175178 bool evCorrection,
176- float landmarksMaskScale)
179+ float landmarksMaskScale,
180+ int nbNeighborObservations,
181+ float percentile)
177182{
178183 // defined view Ids
179184 std::set<IndexT> viewIds;
@@ -212,7 +217,7 @@ bool prepareDenseScene(const SfMData& sfmData,
212217
213218 const auto & observationsPerView = getObservationsPerViews (sfmData);
214219
215- // #pragma omp parallel for num_threads(3)
220+ #pragma omp parallel for
216221 for (int i = 0 ; i < viewIds.size (); ++i)
217222 {
218223 auto itView = viewIds.begin ();
@@ -336,7 +341,7 @@ bool prepareDenseScene(const SfMData& sfmData,
336341 }
337342
338343 image::Image<unsigned char > maskLandmarks;
339- bool doMaskLandmarks = landmarksMaskScale > 0 .f ;
344+ bool doMaskLandmarks = nbNeighborObservations > 0 || percentile < 1 .f ;
340345 if (doMaskLandmarks)
341346 {
342347 // for the T camera, image alpha should be at least 0.4f * 255 (masking)
@@ -353,32 +358,45 @@ bool prepareDenseScene(const SfMData& sfmData,
353358 tree.buildIndex ();
354359 ALICEVISION_LOG_INFO (" KdTree created for " << observations.size () << " points." );
355360
356- /* index = std::numeric_limits<std::size_t>::max();
357- sq_dist = std::numeric_limits<double>::max();
358- nanoflann::KNNResultSet<double, std::size_t> resultSet(1);
359- resultSet.init(&index, &sq_dist);
360- if(!_tree->findNeighbors(resultSet, p.m, nanoflann::SearchParameters()))
361+ int n = std::min (nbNeighborObservations, static_cast <int >(observations.size ()));
362+ std::vector<double > means (observations.size ());
363+ const std::size_t cacheSize = 1000 ;
364+ accumulator_set<double , stats<tag::tail_quantile<right>, tag::mean>> acc (
365+ tag::tail<right>::cache_size = cacheSize);
366+ int j = 0 ;
367+ for (const auto & observation : observations)
361368 {
362- return false;
369+ const auto & obs = *observation;
370+ std::vector<size_t > indices_ (n);
371+ std::vector<double > distances_ (n);
372+ tree.knnSearch (obs.x .data (), n, &indices_[0 ], &distances_[0 ]);
373+
374+ std::transform (distances_.begin (), distances_.end (), distances_.begin (),
375+ static_cast <double (*)(double )>(std::sqrt));
376+ const auto & mean = std::accumulate (distances_.begin (), distances_.end (), 0.0 ) / n;
377+ means[j++] = mean;
378+ acc (mean);
363379 }
364- return true;*/
380+ double mean_max = std::numeric_limits<double >::max ();
381+ if (percentile != 1 .f )
382+ mean_max = quantile (acc, quantile_probability = percentile);
383+ r = mean (acc);
365384
385+ j = 0 ;
366386 for (const auto & observation : observations)
367387 {
368388 const auto & obs = *observation;
369- RadiusKnnSearch search (r, 5 );
370- bool found = tree.findNeighbors (search, obs.x .data (), nanoflann::SearchParameters ());
371- if (!found)
372- continue ;
373- for (int y = std::max (obs.x .y () - r, 0 .);
374- y <= std::min (obs.x .y () + r, (double )maskLandmarks.Height () - 1 ); y++)
375- {
376- for (int x = std::max (obs.x .x () - r, 0 .);
377- x <= std::min (obs.x .x () + r, (double )maskLandmarks.Width () - 1 ); x++)
389+ if (means[j] < mean_max)
390+ for (int y = std::max (obs.x .y () - r, 0 .);
391+ y <= std::min (obs.x .y () + r, (double )maskLandmarks.Height () - 1 ); y++)
378392 {
379- maskLandmarks (y, x) = std::numeric_limits<unsigned char >::max ();
393+ for (int x = std::max (obs.x .x () - r, 0 .);
394+ x <= std::min (obs.x .x () + r, (double )maskLandmarks.Width () - 1 ); x++)
395+ {
396+ maskLandmarks (y, x) = std::numeric_limits<unsigned char >::max ();
397+ }
380398 }
381- }
399+ j++;
382400 }
383401 }
384402 }
@@ -427,6 +445,8 @@ int aliceVision_main(int argc, char *argv[])
427445 bool saveMatricesTxtFiles = false ;
428446 bool evCorrection = false ;
429447 float landmarksMaskScale = 0 .f ;
448+ int nbNeighborObservations = 5 ;
449+ float percentile = 0.95 ;
430450
431451 po::options_description requiredParams (" Required parameters" );
432452 requiredParams.add_options ()
@@ -459,7 +479,11 @@ int aliceVision_main(int argc, char *argv[])
459479 " Correct exposure value." )
460480 (" landmarksMaskScale" , po::value<float >(&landmarksMaskScale)->default_value (landmarksMaskScale),
461481 " Scale (relative to image size) of the projection of landmarks to mask images for depth computation.\n "
462- " If 0, masking using landmarks will not be used." );
482+ " If 0, masking using landmarks will not be used." )
483+ (" nbNeighborObservations" , po::value<int >(&nbNeighborObservations)->default_value (nbNeighborObservations),
484+ " Number of neighbor observations to be considered for the landmarks-based masking." )(
485+ " percentile" , po::value<float >(&percentile)->default_value (percentile),
486+ " TODO." );
463487
464488 CmdLine cmdline (" AliceVision prepareDenseScene" );
465489 cmdline.add (requiredParams);
@@ -513,7 +537,8 @@ int aliceVision_main(int argc, char *argv[])
513537
514538 // export
515539 if (prepareDenseScene (sfmData, imagesFolders, masksFolders, maskExtension, rangeStart, rangeEnd, outFolder,
516- outputFileType, saveMetadata, saveMatricesTxtFiles, evCorrection, landmarksMaskScale))
540+ outputFileType, saveMetadata, saveMatricesTxtFiles, evCorrection, landmarksMaskScale,
541+ nbNeighborObservations, percentile))
517542 return EXIT_SUCCESS;
518543
519544 return EXIT_FAILURE;
0 commit comments