Skip to content

Commit 7ad85cb

Browse files
author
Fabien Servant
committed
Update bundle adjustment unit test for relative Landmarks
1 parent 066cd63 commit 7ad85cb

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

src/aliceVision/multiview/NViewDataSet.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ struct NViewDatasetConfigurator
6161
double _jitter_amount;
6262

6363
NViewDatasetConfigurator(int fx = 1000, int fy = 1000, int cx = 500, int cy = 500, double distance = 1.5, double jitter_amount = 0.01);
64+
65+
bool _useRelative = false;
6466
};
6567

6668
/**

src/aliceVision/sfm/bundle/bundleAdjustment_test.cpp

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,27 @@ BOOST_AUTO_TEST_CASE(BUNDLE_ADJUSTMENT_EffectiveMinimization_Pinhole)
5454
BOOST_CHECK_LT(dResidual_after, dResidual_before);
5555
}
5656

57+
BOOST_AUTO_TEST_CASE(BUNDLE_ADJUSTMENT_EffectiveMinimization_Relative_Pinhole)
58+
{
59+
const int nviews = 3;
60+
const int npoints = 6;
61+
NViewDatasetConfigurator config;
62+
config._useRelative = true;
63+
const NViewDataSet d = NRealisticCamerasRing(nviews, npoints, config);
64+
65+
// Translate the input dataset to a SfMData scene
66+
SfMData sfmData = getInputScene(d, config, EINTRINSIC::PINHOLE_CAMERA, EDISTORTION::DISTORTION_NONE);
67+
68+
const double dResidual_before = RMSE(sfmData);
69+
70+
// Call the BA interface and let it refine (Structure and Camera parameters [Intrinsics|Motion])
71+
std::shared_ptr<BundleAdjustment> ba_object = std::make_shared<BundleAdjustmentCeres>();
72+
BOOST_CHECK(ba_object->adjust(sfmData));
73+
74+
const double dResidual_after = RMSE(sfmData);
75+
BOOST_CHECK_LT(dResidual_after, dResidual_before);
76+
}
77+
5778
BOOST_AUTO_TEST_CASE(BUNDLE_ADJUSTMENT_EffectiveMinimization_PinholeRadialK1)
5879
{
5980
const int nviews = 3;
@@ -246,15 +267,26 @@ double RMSE(const SfMData& sfm_data)
246267
{
247268
// Compute residuals for each observation
248269
std::vector<double> vec;
249-
for (Landmarks::const_iterator iterTracks = sfm_data.getLandmarks().begin(); iterTracks != sfm_data.getLandmarks().end(); ++iterTracks)
270+
for (const auto & [lid, landmark]: sfm_data.getLandmarks())
250271
{
251-
const Observations& observations = iterTracks->second.getObservations();
252-
for (Observations::const_iterator itObs = observations.begin(); itObs != observations.end(); ++itObs)
272+
const Observations& observations = landmark.getObservations();
273+
274+
275+
Pose3 world_T_reference;
276+
if (landmark.referenceViewIndex != UndefinedIndexT)
253277
{
254-
const View* view = sfm_data.getViews().find(itObs->first)->second.get();
255-
const Pose3 pose = sfm_data.getPose(*view).getTransform();
256-
const std::shared_ptr<IntrinsicBase> intrinsic = sfm_data.getIntrinsics().find(view->getIntrinsicId())->second;
257-
const Vec2 residual = intrinsic->residual(pose, iterTracks->second.X.homogeneous(), itObs->second.getCoordinates());
278+
const View & refView = sfm_data.getView(landmark.referenceViewIndex);
279+
world_T_reference = sfm_data.getPose(refView).getTransform().inverse();
280+
}
281+
282+
for (const auto [idView, observation] : observations)
283+
{
284+
const View & view = sfm_data.getView(idView);
285+
const Pose3 camera_T_world = sfm_data.getPose(view).getTransform();
286+
const Pose3 camera_T_reference = camera_T_world * world_T_reference;
287+
const IntrinsicBase & intrinsic = sfm_data.getIntrinsic(view.getIntrinsicId());
288+
const Vec2 residual = intrinsic.residual(camera_T_reference, landmark.X.homogeneous(), observation.getCoordinates());
289+
258290
vec.push_back(residual(0));
259291
vec.push_back(residual(1));
260292
}
@@ -308,15 +340,24 @@ SfMData getInputScene(const NViewDataSet& d, const NViewDatasetConfigurator& con
308340
// Collect the image of point i in each frame.
309341
Landmark landmark;
310342
landmark.X = d._X.col(i);
343+
344+
if (config._useRelative)
345+
{
346+
landmark.referenceViewIndex = nviews / 2;
347+
geometry::Pose3 p = sfm_data.getAbsolutePose(landmark.referenceViewIndex).getTransform();
348+
landmark.X = p(landmark.X);
349+
}
350+
311351
for (int j = 0; j < nviews; ++j)
312352
{
313353
Vec2 pt = d._x[j].col(i);
314354
// => random noise between [-.5,.5] is added
315-
pt(0) += rand() / RAND_MAX - .5;
316-
pt(1) += rand() / RAND_MAX - .5;
355+
pt(0) += double(rand()) / double(RAND_MAX) - .5;
356+
pt(1) += double(rand()) / double(RAND_MAX) - .5;
317357

318358
landmark.getObservations()[j] = Observation(pt, i, unknownScale);
319359
}
360+
320361
sfm_data.getLandmarks()[i] = landmark;
321362
}
322363

0 commit comments

Comments
 (0)