Skip to content

Commit 2254e09

Browse files
committed
[filterSfM] optimize code for performance
1 parent f8e4d42 commit 2254e09

File tree

1 file changed

+74
-62
lines changed

1 file changed

+74
-62
lines changed

src/software/pipeline/main_filterSfM.cpp

Lines changed: 74 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ struct LandmarksAdaptator
5555
/// CRTP helper method
5656
inline Derived& derived() { return *static_cast<Derived*>(this); }
5757

58-
const sfmData::Landmarks& _data;
59-
LandmarksAdaptator(const sfmData::Landmarks& data)
58+
const std::vector<Landmark> _data;
59+
LandmarksAdaptator(const std::vector<Landmark>& data)
6060
: _data(data)
6161
{
6262
}
@@ -67,9 +67,7 @@ struct LandmarksAdaptator
6767
// Returns the dim'th component of the idx'th point in the class:
6868
inline T kdtree_get_pt(const size_t idx, int dim) const
6969
{
70-
auto it = _data.begin();
71-
std::advance(it, idx);
72-
return it->second.X(dim);
70+
return _data[idx].X(dim);
7371
}
7472

7573
// Optional bounding-box computation: return false to default to a standard bbox computation loop.
@@ -100,7 +98,7 @@ class PixSizeSearch
10098
const double _pixSize_i;
10199
bool found = false;
102100

103-
inline PixSizeSearch(double radius, const std::vector<double>& pixSize, int i)
101+
inline PixSizeSearch(double radius, const std::vector<double>& pixSize, size_t i)
104102
: _radius_sq(radius * radius)
105103
, _pixSize(pixSize)
106104
, _pixSize_i(pixSize[i])
@@ -124,16 +122,23 @@ class PixSizeSearch
124122

125123
bool filterLandmarks(SfMData& sfmData, double radiusScale)
126124
{
125+
std::vector<Landmark> landmarksData(sfmData.getLandmarks().size());
126+
{
127+
size_t i = 0;
128+
for(const auto& it : sfmData.getLandmarks())
129+
{
130+
landmarksData[i++] = it.second;
131+
}
132+
}
133+
127134
mvsUtils::MultiViewParams mp(sfmData, "", "", "", false);
128-
std::vector<double> landmarksPixSize(sfmData.getLandmarks().size());
135+
std::vector<double> landmarksPixSize(landmarksData.size());
129136

130137
ALICEVISION_LOG_INFO("Computing pixel size: started.");
131138
#pragma omp parallel for
132-
for(auto i = 0; i < sfmData.getLandmarks().size(); i++)
139+
for(auto i = 0; i < landmarksData.size(); i++)
133140
{
134-
auto landmarkPair = sfmData.getLandmarks().begin();
135-
std::advance(landmarkPair, i);
136-
const sfmData::Landmark& landmark = landmarkPair->second;
141+
const Landmark& landmark = landmarksData[i];
137142

138143
// compute landmark pixSize
139144
double pixSize = 0.;
@@ -155,73 +160,66 @@ bool filterLandmarks(SfMData& sfmData, double radiusScale)
155160
//std::stable_sort(landmarksPixSize.begin(), landmarksPixSize.end(), std::greater<>{});
156161

157162
ALICEVISION_LOG_INFO("Build nanoflann KdTree index.");
158-
LandmarksAdaptator data(sfmData.getLandmarks());
163+
LandmarksAdaptator data(landmarksData);
159164
KdTree tree(3, data, nanoflann::KDTreeSingleIndexAdaptorParams(MAX_LEAF_ELEMENTS));
160165
tree.buildIndex();
161-
ALICEVISION_LOG_INFO("KdTree created for " << sfmData.getLandmarks().size() << " points.");
162-
std::vector<IndexT> newIdx(sfmData.getLandmarks().size());
163-
IndexT currentIdx = 0;
166+
ALICEVISION_LOG_INFO("KdTree created for " << landmarksData.size() << " points.");
167+
std::vector<bool> toRemove(landmarksData.size(), false);
164168

165169
ALICEVISION_LOG_INFO("Identifying landmarks to remove: started.");
166-
#pragma omp parallel for
167-
for (auto i = 0; i < sfmData.getLandmarks().size(); i++)
170+
171+
size_t nbToRemove = 0;
172+
#pragma omp parallel for reduction(+:nbToRemove)
173+
for(auto i = 0; i < landmarksData.size(); i++)
168174
{
169175
PixSizeSearch search(landmarksPixSize[i] * radiusScale, landmarksPixSize, i);
170-
bool found = tree.findNeighbors(search, sfmData.getLandmarks().at(i).X.data(), nanoflann::SearchParams());
176+
bool found = tree.findNeighbors(search, landmarksData[i].X.data(), nanoflann::SearchParams());
171177
if (found)
172178
{
173-
newIdx[i] = -1;
174-
}
175-
else
176-
{
177-
newIdx[i] = currentIdx++;
179+
toRemove[i] = true;
180+
nbToRemove++;
178181
}
179182
}
180183

181184
ALICEVISION_LOG_INFO(
182-
"Identified " << (sfmData.getLandmarks().size() - currentIdx) <<
183-
" landmarks to remove out of " << (sfmData.getLandmarks().size()) <<
184-
", i.e. " << ((sfmData.getLandmarks().size() - currentIdx) * 100.f / sfmData.getLandmarks().size()) <<
185+
"Identified " << (landmarksData.size() - nbToRemove) <<
186+
" landmarks to remove out of " << (landmarksData.size()) <<
187+
", i.e. " << ((landmarksData.size() - nbToRemove) * 100.f / landmarksData.size()) <<
185188
" % "
186189
);
187190
ALICEVISION_LOG_INFO("Identifying landmarks to remove: done.");
188191

189192
ALICEVISION_LOG_INFO("Removing landmarks: started.");
190-
std::vector<std::pair<IndexT, Landmark>> filteredLandmarks(currentIdx);
191-
#pragma omp parallel for
192-
for (auto i = 0; i < sfmData.getLandmarks().size(); i++)
193+
std::vector<std::pair<IndexT, Landmark>> filteredLandmarks(landmarksData.size() - nbToRemove);
194+
IndexT newIdx = 0;
195+
for (size_t i = 0; i < landmarksData.size(); i++)
193196
{
194-
if(newIdx[i] != -1)
197+
if(!toRemove[i])
195198
{
196-
filteredLandmarks[newIdx[i]] = std::make_pair(newIdx[i], sfmData.getLandmarks().at(i));
199+
filteredLandmarks[newIdx++] = std::make_pair(newIdx, landmarksData[i]);
197200
}
198201
}
199202
sfmData.getLandmarks() = Landmarks(filteredLandmarks.begin(), filteredLandmarks.end());
200203
ALICEVISION_LOG_INFO("Removing landmarks: done.");
201204

202-
//// take only best observations
203-
//observationScores.resize(maxNbObservationsPerLandmark);
204-
205-
206-
207-
//// replace the observations
208-
//Observations filteredObservations;
209-
//for(auto observationScorePair : observationScores)
210-
//{
211-
// filteredObservations[observationScorePair.second] = landmark.observations[observationScorePair.second];
212-
//}
213-
//landmark.observations = filteredObservations;
214205
return true;
215206
}
216207

217208
bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark)
218209
{
210+
std::vector<Landmark> landmarksData(sfmData.getLandmarks().size());
211+
{
212+
size_t i = 0;
213+
for(const auto& it : sfmData.getLandmarks())
214+
{
215+
landmarksData[i++] = it.second;
216+
}
217+
}
218+
219219
#pragma omp parallel for
220-
for(auto i = 0; i < sfmData.getLandmarks().size(); i++)
220+
for(auto i = 0; i < landmarksData.size(); i++)
221221
{
222-
auto landmarkPair = sfmData.getLandmarks().begin();
223-
std::advance(landmarkPair, i);
224-
sfmData::Landmark& landmark = landmarkPair->second;
222+
sfmData::Landmark landmark = landmarksData[i];
225223

226224
// check number of observations
227225
if(landmark.observations.size() <= maxNbObservationsPerLandmark)
@@ -232,8 +230,7 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark)
232230

233231
// compute observation scores
234232

235-
std::vector<std::pair<double, IndexT> > observationScores;
236-
observationScores.reserve(landmark.observations.size());
233+
std::vector<std::pair<double, IndexT>> observationScores(landmark.observations.size());
237234

238235
for(const auto& observationPair : landmark.observations)
239236
{
@@ -254,7 +251,7 @@ bool filterObservations(SfMData& sfmData, int maxNbObservationsPerLandmark)
254251

255252
// replace the observations
256253
Observations filteredObservations;
257-
for(auto observationScorePair : observationScores)
254+
for(const auto& observationScorePair : observationScores)
258255
{
259256
filteredObservations[observationScorePair.second] = landmark.observations[observationScorePair.second];
260257
}
@@ -273,6 +270,11 @@ int aliceVision_main(int argc, char *argv[])
273270
int maxNbObservationsPerLandmark = 5;
274271
double radiusScale = 2;
275272

273+
// user optional parameters
274+
std::vector<std::string> featuresFolders;
275+
std::vector<std::string> matchesFolders;
276+
std::string describerTypesName = feature::EImageDescriberType_enumToString(feature::EImageDescriberType::SIFT);
277+
276278
po::options_description requiredParams("Required parameters");
277279
requiredParams.add_options()
278280
("input,i", po::value<std::string>(&inputSfmFilename)->required(),
@@ -285,7 +287,13 @@ int aliceVision_main(int argc, char *argv[])
285287
("maxNbObservationsPerLandmark", po::value<int>(&maxNbObservationsPerLandmark)->default_value(maxNbObservationsPerLandmark),
286288
"Maximum number of allowed observations per landmark.")
287289
("radiusScale", po::value<double>(&radiusScale)->default_value(radiusScale),
288-
"Scale factor applied to pixel size based radius filter applied to landmarks.");
290+
"Scale factor applied to pixel size based radius filter applied to landmarks.")
291+
("featuresFolders,f", po::value<std::vector<std::string>>(&featuresFolders)->multitoken(),
292+
"Path to folder(s) containing the extracted features.")
293+
("matchesFolders,m", po::value<std::vector<std::string>>(&matchesFolders)->multitoken(),
294+
"Path to folder(s) in which computed matches are stored.")
295+
("describerTypes,d", po::value<std::string>(&describerTypesName)->default_value(describerTypesName),
296+
feature::EImageDescriberType_informations().c_str());
289297

290298
CmdLine cmdline("AliceVision SfM filtering.");
291299
cmdline.add(requiredParams);
@@ -311,18 +319,22 @@ int aliceVision_main(int argc, char *argv[])
311319
}
312320

313321
// filter SfM data
314-
ALICEVISION_LOG_INFO("Filtering landmarks: started.");
315-
bool success2 = filterLandmarks(sfmData, radiusScale);
316-
ALICEVISION_LOG_INFO("Filtering landmarks: done.");
317-
ALICEVISION_LOG_INFO("Filtering observations: started.");
318-
bool success1 = filterObservations(sfmData, maxNbObservationsPerLandmark);
319-
ALICEVISION_LOG_INFO("Filtering observations: done.");
320-
321-
if(success1)
322+
if(radiusScale > 0)
323+
{
324+
ALICEVISION_LOG_INFO("Filtering landmarks: started.");
325+
filterLandmarks(sfmData, radiusScale);
326+
ALICEVISION_LOG_INFO("Filtering landmarks: done.");
327+
}
328+
329+
if(maxNbObservationsPerLandmark > 0)
322330
{
323-
sfmDataIO::Save(sfmData, outputSfmFilename, sfmDataIO::ESfMData::ALL);
324-
return EXIT_SUCCESS;
331+
ALICEVISION_LOG_INFO("Filtering observations: started.");
332+
filterObservations(sfmData, maxNbObservationsPerLandmark);
333+
ALICEVISION_LOG_INFO("Filtering observations: done.");
325334
}
326335

327-
return EXIT_FAILURE;
336+
337+
sfmDataIO::Save(sfmData, outputSfmFilename, sfmDataIO::ESfMData::ALL);
338+
return EXIT_SUCCESS;
339+
328340
}

0 commit comments

Comments
 (0)