Skip to content

Commit 8fbcd1e

Browse files
Fabien Servantservantftransperfect
authored andcommitted
cleanup mesh constraint
1 parent 8ba3100 commit 8fbcd1e

File tree

9 files changed

+273
-57
lines changed

9 files changed

+273
-57
lines changed

meshroom/aliceVision/SfmBootstrapping.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "4.1"
1+
__version__ = "4.2"
22

33
from meshroom.core import desc
44
from meshroom.core.utils import VERBOSE_LEVEL
@@ -21,8 +21,8 @@ class SfMBootStrapping(desc.AVCommandLineNode):
2121
desc.ChoiceParam(
2222
name="method",
2323
label="Method",
24-
description="Bootstrapping method: classic (epipolar geometry), mesh (3D mesh constraints), or depth (depth map information).",
25-
values=["classic", "mesh", "depth"],
24+
description="Bootstrapping method: classic (epipolar geometry), mesh (3D mesh constraints), mesh_single (mesh without visual parallax), or depth (depth map information).",
25+
values=["classic", "mesh", "mesh_single", "depth"],
2626
value="classic",
2727
),
2828
desc.File(
@@ -36,7 +36,7 @@ class SfMBootStrapping(desc.AVCommandLineNode):
3636
label="Mesh File",
3737
description="Mesh file (*.obj).",
3838
value="",
39-
enabled=lambda node: node.method.value == "mesh"
39+
enabled=lambda node: node.method.value.startswith("mesh")
4040
),
4141
desc.File(
4242
name="pairs",

src/aliceVision/sfm/pipeline/expanding/ExpansionChunk.cpp

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,6 @@ bool ExpansionChunk::process(sfmData::SfMData & sfmData, const track::TracksHand
159159
{
160160
return false;
161161
}
162-
163-
if (_pointFetcherHandler)
164-
{
165-
setConstraints(sfmData, tracksHandler, validViewIds);
166-
}
167162

168163
_historyHandler->saveState(sfmData);
169164

@@ -174,18 +169,17 @@ bool ExpansionChunk::process(sfmData::SfMData & sfmData, const track::TracksHand
174169

175170
bool ExpansionChunk::triangulate(sfmData::SfMData & sfmData, const track::TracksHandler & tracksHandler, const std::set<IndexT> & viewIds)
176171
{
177-
ALICEVISION_LOG_INFO("ExpansionChunk::triangulate start");
178-
SfmTriangulation triangulation(_triangulationMinPoints, _maxTriangulationError);
179-
180-
172+
ALICEVISION_LOG_INFO("ExpansionChunk::triangulate start");
181173
const bool enableMultiviewTriangulation = true;
182174

175+
const size_t minPoints = _triangulationHandler->getMinObservations();
176+
183177
if (enableMultiviewTriangulation)
184178
{
185179
std::set<IndexT> evaluatedTracks;
186180
std::map<IndexT, sfmData::Landmark> outputLandmarks;
187181
std::mt19937 randomNumberGenerator;
188-
if (!triangulation.process(sfmData, tracksHandler.getAllTracks(), tracksHandler.getTracksPerView(),
182+
if (!_triangulationHandler->process(sfmData, tracksHandler.getAllTracks(), tracksHandler.getTracksPerView(),
189183
randomNumberGenerator, viewIds,
190184
evaluatedTracks, outputLandmarks, false))
191185
{
@@ -204,7 +198,7 @@ bool ExpansionChunk::triangulate(sfmData::SfMData & sfmData, const track::Tracks
204198
landmarks.erase(pl.first);
205199
}
206200

207-
if (landmark.getObservations().size() < _triangulationMinPoints)
201+
if (landmark.getObservations().size() < minPoints)
208202
{
209203
continue;
210204
}
@@ -232,7 +226,51 @@ bool ExpansionChunk::triangulate(sfmData::SfMData & sfmData, const track::Tracks
232226
std::set<IndexT> evaluatedTracks;
233227
std::map<IndexT, sfmData::Landmark> outputLandmarks;
234228
std::mt19937 randomNumberGenerator;
235-
if (!triangulation.process(sfmData, tracksHandler.getAllTracks(), tracksHandler.getTracksPerView(),
229+
if (!_triangulationHandler->process(sfmData, tracksHandler.getAllTracks(), tracksHandler.getTracksPerView(),
230+
randomNumberGenerator, viewIds,
231+
evaluatedTracks, outputLandmarks, true))
232+
{
233+
return false;
234+
}
235+
236+
auto & landmarks = sfmData.getLandmarks();
237+
ALICEVISION_LOG_INFO("Existing landmarks : " << landmarks.size());
238+
239+
for (const auto & pl : outputLandmarks)
240+
{
241+
const auto & landmark = pl.second;
242+
243+
if (landmarks.find(pl.first) != landmarks.end())
244+
{
245+
if (!_ignoreMultiviewOnPrior)
246+
{
247+
continue;
248+
}
249+
}
250+
251+
if (landmark.getObservations().size() < minPoints)
252+
{
253+
continue;
254+
}
255+
256+
if (!SfmTriangulation::checkChierality(sfmData, landmark))
257+
{
258+
continue;
259+
}
260+
261+
landmarks.insert(pl);
262+
}
263+
264+
ALICEVISION_LOG_INFO("New landmarks count : " << landmarks.size());
265+
ALICEVISION_LOG_INFO("ExpansionChunk::triangulate end");
266+
}
267+
268+
if (_enableMeshPrior)
269+
{
270+
std::set<IndexT> evaluatedTracks;
271+
std::map<IndexT, sfmData::Landmark> outputLandmarks;
272+
std::mt19937 randomNumberGenerator;
273+
if (!_triangulationHandler->process(sfmData, tracksHandler.getAllTracks(), tracksHandler.getTracksPerView(),
236274
randomNumberGenerator, viewIds,
237275
evaluatedTracks, outputLandmarks, true))
238276
{
@@ -254,7 +292,7 @@ bool ExpansionChunk::triangulate(sfmData::SfMData & sfmData, const track::Tracks
254292
}
255293
}
256294

257-
if (landmark.getObservations().size() < _triangulationMinPoints)
295+
if (landmark.getObservations().size() < minPoints)
258296
{
259297
continue;
260298
}
@@ -285,7 +323,7 @@ void ExpansionChunk::addPose(sfmData::SfMData & sfmData, IndexT viewId, const Ei
285323

286324
void ExpansionChunk::setConstraints(sfmData::SfMData & sfmData, const track::TracksHandler & tracksHandler, const std::set<IndexT> & viewIds)
287325
{
288-
ALICEVISION_LOG_INFO("ExpansionChunk::setConstraints start");
326+
/*ALICEVISION_LOG_INFO("ExpansionChunk::setConstraints start");
289327
const track::TracksMap & tracks = tracksHandler.getAllTracks();
290328
const track::TracksPerView & tracksPerView = tracksHandler.getTracksPerView();
291329
@@ -399,7 +437,7 @@ void ExpansionChunk::setConstraints(sfmData::SfMData & sfmData, const track::Tra
399437
}
400438
401439
ALICEVISION_LOG_INFO("ExpansionChunk::setConstraints added " << constraints.size() << " constraints");
402-
ALICEVISION_LOG_INFO("ExpansionChunk::setConstraints end");
440+
ALICEVISION_LOG_INFO("ExpansionChunk::setConstraints end");*/
403441
}
404442

405443
} // namespace sfm

src/aliceVision/sfm/pipeline/expanding/ExpansionChunk.hpp

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
#include <aliceVision/sfmData/SfMData.hpp>
1212
#include <aliceVision/sfm/pipeline/expanding/ExpansionHistory.hpp>
1313
#include <aliceVision/sfm/pipeline/expanding/SfmBundle.hpp>
14-
#include <aliceVision/sfm/pipeline/expanding/PointFetcher.hpp>
1514
#include <aliceVision/sfm/pipeline/expanding/SfmResection.hpp>
15+
#include <aliceVision/sfm/pipeline/expanding/SfmTriangulation.hpp>
1616

1717
namespace aliceVision {
1818
namespace sfm {
@@ -54,16 +54,7 @@ class ExpansionChunk
5454
}
5555

5656
/**
57-
* brief setup the point fetcher handler
58-
* @param pointFetcher a unique ptr. the Ownership will be taken
59-
*/
60-
void setPointFetcherHandler(PointFetcher::uptr & pointFetcherHandler)
61-
{
62-
_pointFetcherHandler = std::move(pointFetcherHandler);
63-
}
64-
65-
/**
66-
* brief setup the point fetcher handler
57+
* brief setup the Resection handler
6758
* @param resectionHandler a unique ptr. the Ownership will be taken
6859
*/
6960
void setResectionHandler(SfmResection::uptr & resectionHandler)
@@ -72,21 +63,12 @@ class ExpansionChunk
7263
}
7364

7465
/**
75-
* @brief set the minimal number of points to enable triangulation of a track
76-
* @param count the number of points
77-
*/
78-
void setTriangulationMinPoints(size_t count)
79-
{
80-
_triangulationMinPoints = count;
81-
}
82-
83-
/**
84-
* @brief set the maximal reprojection error in the triangulation process.
85-
* @param count the number of points
66+
* brief setup the Triangulation handler
67+
* @param triangulationHandler a unique ptr. the Ownership will be taken
8668
*/
87-
void setTriangulationMaxError(double error)
69+
void setTriangulationHandler(SfmTriangulation::uptr & triangulationHandler)
8870
{
89-
_maxTriangulationError = error;
71+
_triangulationHandler = std::move(triangulationHandler);
9072
}
9173

9274
/**
@@ -159,16 +141,15 @@ class ExpansionChunk
159141
private:
160142
SfmBundle::uptr _bundleHandler;
161143
ExpansionHistory::sptr _historyHandler;
162-
PointFetcher::uptr _pointFetcherHandler;
163144
std::set<IndexT> _ignoredViews;
164145
SfmResection::uptr _resectionHandler;
146+
SfmTriangulation::uptr _triangulationHandler;
165147

166148
private:
167-
size_t _triangulationMinPoints = 2;
168149
double _minTriangulationAngleDegrees = 3.0;
169-
double _maxTriangulationError = 8.0;
170150
size_t _weakResectionSize = 100;
171151
bool _enableDepthPrior = true;
152+
bool _enableMeshPrior = true;
172153
bool _ignoreMultiviewOnPrior = false;
173154
};
174155

src/aliceVision/sfm/pipeline/expanding/PointFetcher.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class PointFetcher
1818
{
1919
public:
2020
using uptr = std::unique_ptr<PointFetcher>;
21+
using sptr = std::shared_ptr<PointFetcher>;
2122

2223
public:
2324
/**

src/aliceVision/sfm/pipeline/expanding/SfmBundle.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class SfmBundle
106106
double _maxReprojectionError = 4.0;
107107
double _minAngleForLandmark = 2.0;
108108
double _maxConstraintDistance = 1.0;
109-
size_t _minTrackLength = 2;
109+
size_t _minTrackLength = 1;
110110
size_t _minPointsPerPose = 30;
111111
size_t _bundleAdjustmentMaxOutlier = 50;
112112
size_t _minNbCamerasToRefinePrincipalPoint = 3;

src/aliceVision/sfm/pipeline/expanding/SfmTriangulation.cpp

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,19 @@ bool SfmTriangulation::process(
8686
sfmData::Landmark result;
8787
if (useDepthPrior)
8888
{
89-
if (!processTrackWithPrior(sfmData, track, randomNumberGenerator, trackViewsFiltered, result))
89+
if (_pointFetcherHandler)
9090
{
91-
continue;
91+
if (!processTrackWithPointFetcher(sfmData, track, randomNumberGenerator, trackViewsFiltered, result))
92+
{
93+
continue;
94+
}
95+
}
96+
else
97+
{
98+
if (!processTrackWithPrior(sfmData, track, randomNumberGenerator, trackViewsFiltered, result))
99+
{
100+
continue;
101+
}
92102
}
93103
}
94104
else
@@ -284,6 +294,108 @@ bool SfmTriangulation::processTrackWithPrior(
284294
return true;
285295
}
286296

297+
bool SfmTriangulation::processTrackWithPointFetcher(
298+
const sfmData::SfMData & sfmData,
299+
const track::Track & track,
300+
std::mt19937 &randomNumberGenerator,
301+
const std::set<IndexT> & viewIds,
302+
sfmData::Landmark & result
303+
)
304+
{
305+
size_t bestInliersCount = 0;
306+
std::vector<std::pair<Vec3, Vec3>> possibleParameters;
307+
308+
//For each observed view in the track
309+
for (auto referenceViewId : viewIds)
310+
{
311+
if (track.featPerView.find(referenceViewId) == track.featPerView.end())
312+
{
313+
continue;
314+
}
315+
316+
//Look if this observation has an associated depth
317+
const auto & refTrackItem = track.featPerView.at(referenceViewId);
318+
319+
const sfmData::View & v = sfmData.getView(referenceViewId);
320+
const sfmData::CameraPose & cp = sfmData.getAbsolutePose(v.getPoseId());
321+
const camera::IntrinsicBase & intrinsics = *sfmData.getIntrinsics().at(v.getIntrinsicId());
322+
323+
_pointFetcherHandler->setPose(cp.getTransform());
324+
325+
Vec3 point, normal;
326+
if (!_pointFetcherHandler->pickPointAndNormal(point, normal, intrinsics, refTrackItem.coords))
327+
{
328+
continue;
329+
}
330+
331+
possibleParameters.push_back(std::make_pair(point, normal));
332+
}
333+
334+
335+
336+
//Consider each point
337+
for (int idRef = 0; idRef < possibleParameters.size(); idRef++)
338+
{
339+
const Vec3 & refpt = possibleParameters[idRef].first;
340+
const Vec3 & refnormal = possibleParameters[idRef].second;
341+
342+
//Make sure this point is not dependent on parallax
343+
//As it does not need parallax to estimate its depth
344+
sfmData::Landmark landmark;
345+
landmark.setParallaxRobust(true);
346+
landmark.X = refpt;
347+
landmark.descType = track.descType;
348+
349+
//For each observed view in the track
350+
for (auto viewId: viewIds)
351+
{
352+
if (track.featPerView.find(viewId) == track.featPerView.end())
353+
{
354+
continue;
355+
}
356+
357+
const auto & trackItem = track.featPerView.at(viewId);
358+
359+
const sfmData::View & view = sfmData.getView(viewId);
360+
const camera::IntrinsicBase & intrinsic = sfmData.getIntrinsic(view.getIntrinsicId());
361+
const geometry::Pose3 pose = sfmData.getPose(view).getTransform();
362+
363+
const Vec2 est = intrinsic.transformProject(pose, refpt.homogeneous(), true);
364+
const Vec2 mes = trackItem.coords.cast<double>();
365+
double err = (est - mes).norm() / trackItem.scale;
366+
367+
//Use _maxError as threshold for inliers/outlier detection
368+
if (err > _maxError)
369+
{
370+
continue;
371+
}
372+
373+
//Create and associated an observation to the landmark
374+
sfmData::Observation & o = landmark.getObservations()[viewId];
375+
o.setFeatureId(trackItem.featureId);
376+
o.setScale(trackItem.scale);
377+
o.setCoordinates(trackItem.coords);
378+
o.setDepth(trackItem.depth);
379+
}
380+
381+
//Store the landmark if it's better than the previously estimated one
382+
int count = landmark.getObservations().size();
383+
if (count > bestInliersCount)
384+
{
385+
bestInliersCount = count;
386+
result = landmark;
387+
}
388+
}
389+
390+
//One inlier is the reference, so we need at least 2 inliers
391+
if (bestInliersCount < 2)
392+
{
393+
return false;
394+
}
395+
396+
return true;
397+
}
398+
287399
bool SfmTriangulation::checkChierality(const sfmData::SfMData & sfmData, const sfmData::Landmark & landmark)
288400
{
289401
for (const auto & pRefObs : landmark.getObservations())

0 commit comments

Comments
 (0)