Skip to content

Commit c77ad5c

Browse files
committed
[WIP] stash commit
1 parent 2fee024 commit c77ad5c

File tree

2 files changed

+140
-2
lines changed

2 files changed

+140
-2
lines changed

src/software/pipeline/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,10 @@ if(ALICEVISION_BUILD_SFM)
392392
aliceVision_cmdline
393393
aliceVision_sfmData
394394
aliceVision_sfmDataIO
395+
aliceVision_mvsUtils
395396
Boost::program_options
396397
Boost::filesystem
398+
nanoflann
397399
)
398400

399401
endif() # if(ALICEVISION_BUILD_SFM)

src/software/pipeline/main_filterSfM.cpp

Lines changed: 138 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include <aliceVision/system/main.hpp>
1212
#include <aliceVision/config.hpp>
1313
#include <aliceVision/sfmDataIO/viewIO.hpp>
14+
#include <aliceVision/mvsUtils/MultiViewParams.hpp>
15+
16+
#include "nanoflann.hpp"
1417

1518
#include <boost/program_options.hpp>
1619
#include <boost/filesystem.hpp>
@@ -40,7 +43,137 @@ using namespace aliceVision::sfmDataIO;
4043
namespace po = boost::program_options;
4144
namespace fs = boost::filesystem;
4245

43-
bool filterSfMData(SfMData& sfmData, int maxNbObservationsPerLandmark)
46+
static const std::size_t MAX_LEAF_ELEMENTS = 10;
47+
48+
template <typename DATA>
49+
struct PointVectorAdaptator
50+
{
51+
using Derived = PointVectorAdaptator; //!< In this case the dataset class is myself.
52+
using T = double;
53+
54+
const DATA& _data;
55+
PointVectorAdaptator(const DATA& data)
56+
: _data(data)
57+
{
58+
}
59+
60+
/// CRTP helper method
61+
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
62+
/// CRTP helper method
63+
inline Derived& derived() { return *static_cast<Derived*>(this); }
64+
65+
// Must return the number of data points
66+
inline size_t kdtree_get_point_count() const { return _data.size(); }
67+
68+
// Returns the dim'th component of the idx'th point in the class:
69+
// Since this is inlined and the "dim" argument is typically an immediate value, the
70+
// "if/else's" are actually solved at compile time.
71+
inline T kdtree_get_pt(const size_t idx, int dim) const { return _data.at(idx).m[dim]; }
72+
73+
// Optional bounding-box computation: return false to default to a standard bbox computation loop.
74+
// Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it
75+
// again. Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
76+
template <class BBOX>
77+
bool kdtree_get_bbox(BBOX& bb) const
78+
{
79+
return false;
80+
}
81+
};
82+
83+
template <typename DATA>
84+
using KdTree = nanoflann::KDTreeSingleIndexAdaptor<
85+
nanoflann::L2_Simple_Adaptor<double, PointVectorAdaptator>,
86+
PointVectorAdaptator, 3 /* dim */
87+
>;
88+
89+
template <typename DATA>
90+
class Tree
91+
{
92+
std::unique_ptr<KdTree> _tree;
93+
std::unique_ptr<PointVectorAdaptator> _pointCloudRef;
94+
95+
public:
96+
Tree(const DATA& data) { initKdTree(data); }
97+
98+
void initKdTree(const DATA& data)
99+
{
100+
ALICEVISION_LOG_INFO("Build nanoflann KdTree index.");
101+
_pointCloudRef = std::make_unique<PointVectorAdaptator>(data);
102+
_tree = std::make_unique<KdTree>(3 /*dim*/, *_pointCloudRef.get(),
103+
nanoflann::KDTreeSingleIndexAdaptorParams(MAX_LEAF_ELEMENTS));
104+
_tree->buildIndex();
105+
ALICEVISION_LOG_INFO("KdTree created for " << data.size() << " points.");
106+
}
107+
108+
bool locateNearestVertex(const Point3d& p, std::size_t& index, double& sq_dist) const
109+
{
110+
index = std::numeric_limits<std::size_t>::max();
111+
sq_dist = std::numeric_limits<double>::max();
112+
nanoflann::KNNResultSet<double, std::size_t> resultSet(1);
113+
resultSet.init(&index, &sq_dist);
114+
if(!_tree->findNeighbors(resultSet, p.m, nanoflann::SearchParams()))
115+
{
116+
return false;
117+
}
118+
return true;
119+
}
120+
};
121+
122+
bool filterLandmarks(SfMData& sfmData)
123+
{
124+
mvsUtils::MultiViewParams mp(sfmData, "", "", "", false);
125+
std::vector<std::pair<double, IndexT>> landmarksPixSize(sfmData.getLandmarks().size());
126+
127+
#pragma omp parallel for
128+
for(auto i = 0; i < sfmData.getLandmarks().size(); i++)
129+
{
130+
auto landmarkPair = sfmData.getLandmarks().begin();
131+
std::advance(landmarkPair, i);
132+
const sfmData::Landmark& landmark = landmarkPair->second;
133+
134+
// compute landmark pixSize
135+
double pixSize = 0.;
136+
int n = 0;
137+
for(const auto& observationPair : landmark.observations)
138+
{
139+
const IndexT viewId = observationPair.first;
140+
auto d = mp.getCamPixelSize(Point3d(landmark.X.x(), landmark.X.y(), landmark.X.z()),
141+
mp.getIndexFromViewId(viewId), observationPair.second.scale);
142+
if(d < 0.)
143+
d = 0.;
144+
pixSize += d;
145+
if(pixSize < 0.)
146+
pixSize = 0.;
147+
n++;
148+
}
149+
if(pixSize < 0.)
150+
pixSize = 0.;
151+
pixSize /= n;
152+
if(pixSize < 0.)
153+
pixSize = 0.;
154+
155+
landmarksPixSize[i] = std::pair<double, IndexT>(pixSize, landmarkPair->first);
156+
}
157+
158+
// sort landmarks by descending pixSize order
159+
std::stable_sort(landmarksPixSize.begin(), landmarksPixSize.end(), std::greater<>{});
160+
161+
//// take only best observations
162+
//observationScores.resize(maxNbObservationsPerLandmark);
163+
164+
165+
166+
//// replace the observations
167+
//Observations filteredObservations;
168+
//for(auto observationScorePair : observationScores)
169+
//{
170+
// filteredObservations[observationScorePair.second] = landmark.observations[observationScorePair.second];
171+
//}
172+
//landmark.observations = filteredObservations;
173+
return true;
174+
}
175+
176+
bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark)
44177
{
45178
#pragma omp parallel for
46179
for(auto i = 0; i < sfmData.getLandmarks().size(); i++)
@@ -134,7 +267,10 @@ int aliceVision_main(int argc, char *argv[])
134267
}
135268

136269
// filter SfM data
137-
if(filterSfMData(sfmData, maxNbObservationsPerLandmark))
270+
bool success2 = filterLandmarks(sfmData);
271+
bool success1 = filterObservations(sfmData, maxNbObservationsPerLandmark);
272+
273+
if(success1)
138274
{
139275
sfmDataIO::Save(sfmData, outputSfmFilename, sfmDataIO::ESfMData::ALL);
140276
return EXIT_SUCCESS;

0 commit comments

Comments
 (0)