Skip to content

Commit e2a53e1

Browse files
committed
[WIP] mask depth maps
1 parent 374783c commit e2a53e1

File tree

2 files changed

+117
-12
lines changed

2 files changed

+117
-12
lines changed

src/software/pipeline/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ if(ALICEVISION_BUILD_SFM)
382382
Boost::filesystem
383383
Boost::boost
384384
Boost::timer
385+
nanoflann
385386
)
386387

387388
# Filter SfM data

src/software/pipeline/main_prepareDenseScene.cpp

Lines changed: 116 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <aliceVision/config.hpp>
1515
#include <aliceVision/sfmDataIO/viewIO.hpp>
1616

17+
#include "nanoflann.hpp"
18+
1719
#include <boost/program_options.hpp>
1820
#include <boost/filesystem.hpp>
1921

@@ -41,6 +43,90 @@ using namespace aliceVision::sfmDataIO;
4143
namespace po = boost::program_options;
4244
namespace fs = boost::filesystem;
4345

46+
static const std::size_t MAX_LEAF_ELEMENTS = 64;
47+
48+
struct ObservationsAdaptator
49+
{
50+
using Derived = ObservationsAdaptator; //!< In this case the dataset class is myself.
51+
using T = double;
52+
53+
/// CRTP helper method
54+
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
55+
/// CRTP helper method
56+
inline Derived& derived() { return *static_cast<Derived*>(this); }
57+
58+
const std::vector<const Observation*> _data;
59+
ObservationsAdaptator(const std::vector<const Observation*>& data)
60+
: _data(data)
61+
{
62+
}
63+
64+
// Must return the number of data points
65+
inline size_t kdtree_get_point_count() const { return _data.size(); }
66+
67+
// Returns the dim'th component of the idx'th point in the class:
68+
inline T kdtree_get_pt(const size_t idx, int dim) const { return _data[idx]->x(dim); }
69+
70+
// Optional bounding-box computation: return false to default to a standard bbox computation loop.
71+
// Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it
72+
// again. Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
73+
template <class BBOX>
74+
bool kdtree_get_bbox(BBOX& bb) const
75+
{
76+
return false;
77+
}
78+
};
79+
80+
using KdTree = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, ObservationsAdaptator>,
81+
ObservationsAdaptator, 2, /* dim */
82+
size_t>;
83+
84+
/**
85+
* A result-set class used when performing a radius based search.
86+
*/
87+
class RadiusKnnSearch
88+
{
89+
public:
90+
const double _radius_sq;
91+
const int _nb_neighbors;
92+
int nb_found = 0;
93+
94+
inline RadiusKnnSearch(double radius, int k)
95+
: _radius_sq(radius * radius)
96+
, _nb_neighbors(k)
97+
{
98+
}
99+
100+
inline bool full() const { return nb_found == _nb_neighbors; }
101+
102+
inline bool addPoint(double dist, IndexT index)
103+
{
104+
if(dist < _radius_sq)
105+
{
106+
nb_found++;
107+
return nb_found < _nb_neighbors;
108+
}
109+
return true;
110+
}
111+
112+
inline double worstDist() const { return _radius_sq; }
113+
};
114+
115+
const auto getObservationsPerViews(const SfMData& sfmData)
116+
{
117+
stl::flat_map<std::size_t, std::vector<const Observation*>> observationsPerView;
118+
for(const auto& landIt : sfmData.getLandmarks())
119+
{
120+
for(const auto& obsIt : landIt.second.observations)
121+
{
122+
IndexT viewId = obsIt.first;
123+
auto& landmarksSet = observationsPerView[viewId];
124+
landmarksSet.push_back(&obsIt.second);
125+
}
126+
}
127+
return observationsPerView;
128+
}
129+
44130
template <class ImageT, class MaskFuncT>
45131
void process(const std::string &dstColorImage, const IntrinsicBase* cam, const oiio::ParamValueList & metadata, const std::string & srcImage, bool evCorrection, float exposureCompensation, MaskFuncT && maskFunc)
46132
{
@@ -124,9 +210,9 @@ bool prepareDenseScene(const SfMData& sfmData,
124210
const double medianCameraExposure = sfmData.getMedianCameraExposureSetting().getExposure();
125211
ALICEVISION_LOG_INFO("Median Camera Exposure: " << medianCameraExposure << ", Median EV: " << std::log2(1.0/medianCameraExposure));
126212

127-
const LandmarksPerView& landmarksPerView = getLandmarksPerViews(sfmData);
213+
const auto& observationsPerView = getObservationsPerViews(sfmData);
128214

129-
#pragma omp parallel for num_threads(3)
215+
//#pragma omp parallel for num_threads(3)
130216
for(int i = 0; i < viewIds.size(); ++i)
131217
{
132218
auto itView = viewIds.begin();
@@ -253,19 +339,37 @@ bool prepareDenseScene(const SfMData& sfmData,
253339
bool doMaskLandmarks = landmarksMaskScale > 0.f;
254340
if(doMaskLandmarks)
255341
{
256-
image::Image<RGBAfColor> image;
257-
readImage(srcImage, image, image::EImageColorSpace::LINEAR);
258342
// for the T camera, image alpha should be at least 0.4f * 255 (masking)
259-
maskLandmarks = image::Image<unsigned char>(image.Width(), image.Height(), true, 127);
260-
int r = (int)(landmarksMaskScale * 0.5f * (image.Width() + image.Height()));
261-
const auto& landmarksSetIt = landmarksPerView.find(viewId);
262-
if(landmarksSetIt != landmarksPerView.end())
343+
maskLandmarks = image::Image<unsigned char>(view->getWidth(), view->getHeight(), true, 127);
344+
int r = (int)(landmarksMaskScale * 0.5f * (view->getWidth() + view->getHeight()));
345+
const auto& observationsIt = observationsPerView.find(viewId);
346+
if(observationsIt != observationsPerView.end())
263347
{
264-
const LandmarkIdSet& landmarksSet = landmarksSetIt->second;
265-
for(const auto& landmarkId : landmarksSet)
348+
const auto& observations = observationsIt->second;
349+
350+
ALICEVISION_LOG_INFO("Build nanoflann KdTree index.");
351+
ObservationsAdaptator data(observations);
352+
KdTree tree(2, data, nanoflann::KDTreeSingleIndexAdaptorParams(MAX_LEAF_ELEMENTS));
353+
tree.buildIndex();
354+
ALICEVISION_LOG_INFO("KdTree created for " << observations.size() << " points.");
355+
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+
{
362+
return false;
363+
}
364+
return true;*/
365+
366+
for(const auto& observation : observations)
266367
{
267-
const sfmData::Landmark& landmark = sfmData.getLandmarks().at(landmarkId);
268-
Observation obs = landmark.observations.at(viewId);
368+
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;
269373
for(int y = std::max(obs.x.y() - r, 0.);
270374
y <= std::min(obs.x.y() + r, (double)maskLandmarks.Height() - 1); y++)
271375
{

0 commit comments

Comments
 (0)