ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
bundle_adjustment_test.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #define TEST_NAME "optim/bundle_adjustment"
33 #include "util/testing.h"
34 
35 #include "base/camera_models.h"
37 #include "base/projection.h"
39 #include "util/random.h"
40 
41 #define CheckVariableCamera(camera, orig_camera) \
42  { \
43  const size_t focal_length_idx = \
44  SimpleRadialCameraModel::focal_length_idxs[0]; \
45  const size_t extra_param_idx = \
46  SimpleRadialCameraModel::extra_params_idxs[0]; \
47  BOOST_CHECK_NE(camera.Params(focal_length_idx), \
48  orig_camera.Params(focal_length_idx)); \
49  BOOST_CHECK_NE(camera.Params(extra_param_idx), \
50  orig_camera.Params(extra_param_idx)); \
51  }
52 
53 #define CheckConstantCamera(camera, orig_camera) \
54  { \
55  const size_t focal_length_idx = \
56  SimpleRadialCameraModel::focal_length_idxs[0]; \
57  const size_t extra_param_idx = \
58  SimpleRadialCameraModel::extra_params_idxs[0]; \
59  BOOST_CHECK_EQUAL(camera.Params(focal_length_idx), \
60  orig_camera.Params(focal_length_idx)); \
61  BOOST_CHECK_EQUAL(camera.Params(extra_param_idx), \
62  orig_camera.Params(extra_param_idx)); \
63  }
64 
65 #define CheckVariableImage(image, orig_image) \
66  { \
67  BOOST_CHECK_NE(image.Qvec(), orig_image.Qvec()); \
68  BOOST_CHECK_NE(image.Tvec(), orig_image.Tvec()); \
69  }
70 
71 #define CheckConstantImage(image, orig_image) \
72  { \
73  BOOST_CHECK_EQUAL(image.Qvec(), orig_image.Qvec()); \
74  BOOST_CHECK_EQUAL(image.Tvec(), orig_image.Tvec()); \
75  }
76 
77 #define CheckConstantXImage(image, orig_image) \
78  { \
79  CheckVariableImage(image, orig_image); \
80  BOOST_CHECK_EQUAL(image.Tvec(0), orig_image.Tvec(0)); \
81  }
82 
83 #define CheckConstantCameraRig(camera_rig, orig_camera_rig, camera_id) \
84  { \
85  BOOST_CHECK_EQUAL(camera_rig.RelativeQvec(camera_id), \
86  orig_camera_rig.RelativeQvec(camera_id)); \
87  BOOST_CHECK_EQUAL(camera_rig.RelativeTvec(camera_id), \
88  orig_camera_rig.RelativeTvec(camera_id)); \
89  }
90 
91 #define CheckVariableCameraRig(camera_rig, orig_camera_rig, camera_id) \
92  { \
93  if (camera_rig.RefCameraId() == camera_id) { \
94  CheckConstantCameraRig(camera_rig, orig_camera_rig, camera_id); \
95  } else { \
96  BOOST_CHECK_NE(camera_rig.RelativeQvec(camera_id), \
97  orig_camera_rig.RelativeQvec(camera_id)); \
98  BOOST_CHECK_NE(camera_rig.RelativeTvec(camera_id), \
99  orig_camera_rig.RelativeTvec(camera_id)); \
100  } \
101  }
102 
103 #define CheckVariablePoint(point, orig_point) \
104  { BOOST_CHECK_NE(point.XYZ(), orig_point.XYZ()); }
105 
106 #define CheckConstantPoint(point, orig_point) \
107  { BOOST_CHECK_EQUAL(point.XYZ(), orig_point.XYZ()); }
108 
109 using namespace colmap;
110 
111 void GeneratePointCloud(const size_t num_points, const Eigen::Vector3d& min,
112  const Eigen::Vector3d& max,
113  Reconstruction* reconstruction) {
114  for (size_t i = 0; i < num_points; ++i) {
115  Eigen::Vector3d xyz;
116  xyz.x() = RandomReal(min.x(), max.x());
117  xyz.y() = RandomReal(min.y(), max.y());
118  xyz.z() = RandomReal(min.z(), max.z());
119  reconstruction->AddPoint3D(xyz, Track());
120  }
121 }
122 
123 void GenerateReconstruction(const size_t num_images, const size_t num_points,
124  Reconstruction* reconstruction,
125  CorrespondenceGraph* correspondence_graph) {
126  SetPRNGSeed(0);
127 
128  GeneratePointCloud(num_points, Eigen::Vector3d(-1, -1, -1),
129  Eigen::Vector3d(1, 1, 1), reconstruction);
130 
131  const double kFocalLengthFactor = 1.2;
132  const size_t kImageSize = 1000;
133 
134  for (size_t i = 0; i < num_images; ++i) {
135  const camera_t camera_id = static_cast<camera_t>(i);
136  const image_t image_id = static_cast<image_t>(i);
137 
138  Camera camera;
140  kFocalLengthFactor * kImageSize, kImageSize,
141  kImageSize);
142  camera.SetCameraId(camera_id);
143  reconstruction->AddCamera(camera);
144 
145  Image image;
146  image.SetImageId(image_id);
147  image.SetCameraId(camera_id);
148  image.SetName(std::to_string(i));
149  image.Qvec() = ComposeIdentityQuaternion();
150  image.Tvec() =
151  Eigen::Vector3d(RandomReal(-1.0, 1.0), RandomReal(-1.0, 1.0), 10);
152  image.SetRegistered(true);
153  reconstruction->AddImage(image);
154 
155  const Eigen::Matrix3x4d proj_matrix = image.ProjectionMatrix();
156 
157  std::vector<Eigen::Vector2d> points2D;
158  for (const auto& point3D : reconstruction->Points3D()) {
159  BOOST_CHECK(HasPointPositiveDepth(proj_matrix, point3D.second.XYZ()));
160  // Get exact projection of 3D point.
161  Eigen::Vector2d point2D =
162  ProjectPointToImage(point3D.second.XYZ(), proj_matrix, camera);
163  // Add some uniform noise.
164  point2D += Eigen::Vector2d(RandomReal(-2.0, 2.0), RandomReal(-2.0, 2.0));
165  points2D.push_back(point2D);
166  }
167 
168  correspondence_graph->AddImage(image_id, num_points);
169  reconstruction->Image(image_id).SetPoints2D(points2D);
170  }
171 
172  reconstruction->SetUp(correspondence_graph);
173 
174  for (size_t i = 0; i < num_images; ++i) {
175  const image_t image_id = static_cast<image_t>(i);
176  TrackElement track_el;
177  track_el.image_id = image_id;
178  track_el.point2D_idx = 0;
179  for (const auto& point3D : reconstruction->Points3D()) {
180  reconstruction->AddObservation(point3D.first, track_el);
181  track_el.point2D_idx += 1;
182  }
183  }
184 }
185 
186 BOOST_AUTO_TEST_CASE(TestConfigNumObservations) {
187  Reconstruction reconstruction;
188  CorrespondenceGraph correspondence_graph;
189  GenerateReconstruction(4, 100, &reconstruction, &correspondence_graph);
190 
191  BundleAdjustmentConfig config;
192 
193  config.AddImage(0);
194  config.AddImage(1);
195  BOOST_CHECK_EQUAL(config.NumResiduals(reconstruction), 400);
196 
197  config.AddVariablePoint(1);
198  BOOST_CHECK_EQUAL(config.NumResiduals(reconstruction), 404);
199 
200  config.AddConstantPoint(2);
201  BOOST_CHECK_EQUAL(config.NumResiduals(reconstruction), 408);
202 
203  config.AddImage(2);
204  BOOST_CHECK_EQUAL(config.NumResiduals(reconstruction), 604);
205 
206  config.AddImage(3);
207  BOOST_CHECK_EQUAL(config.NumResiduals(reconstruction), 800);
208 }
209 
210 BOOST_AUTO_TEST_CASE(TestTwoView) {
211  Reconstruction reconstruction;
212  CorrespondenceGraph correspondence_graph;
213  GenerateReconstruction(2, 100, &reconstruction, &correspondence_graph);
214  const auto orig_reconstruction = reconstruction;
215 
216  BundleAdjustmentConfig config;
217  config.AddImage(0);
218  config.AddImage(1);
219  config.SetConstantPose(0);
220  config.SetConstantTvec(1, {0});
221 
222  BundleAdjustmentOptions options;
223  BundleAdjuster bundle_adjuster(options, config);
224  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
225 
226  const auto summary = bundle_adjuster.Summary();
227 
228  // 100 points, 2 images, 2 residuals per point per image
229  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 400);
230  // 100 x 3 point parameters
231  // + 5 image parameters (pose of second image)
232  // + 2 x 2 camera parameters
233  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 309);
234 
235  CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
236  CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0));
237 
238  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
239  CheckConstantXImage(reconstruction.Image(1), orig_reconstruction.Image(1));
240 
241  for (const auto& point3D : reconstruction.Points3D()) {
242  CheckVariablePoint(point3D.second,
243  orig_reconstruction.Point3D(point3D.first));
244  }
245 }
246 
247 BOOST_AUTO_TEST_CASE(TestTwoViewConstantCamera) {
248  Reconstruction reconstruction;
249  CorrespondenceGraph correspondence_graph;
250  GenerateReconstruction(2, 100, &reconstruction, &correspondence_graph);
251  const auto orig_reconstruction = reconstruction;
252 
253  BundleAdjustmentConfig config;
254  config.AddImage(0);
255  config.AddImage(1);
256  config.SetConstantPose(0);
257  config.SetConstantPose(1);
258  config.SetConstantCamera(0);
259 
260  BundleAdjustmentOptions options;
261  BundleAdjuster bundle_adjuster(options, config);
262  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
263 
264  const auto summary = bundle_adjuster.Summary();
265 
266  // 100 points, 2 images, 2 residuals per point per image
267  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 400);
268  // 100 x 3 point parameters
269  // + 2 camera parameters
270  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 302);
271 
272  CheckConstantCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
273  CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0));
274 
275  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
276  CheckConstantImage(reconstruction.Image(1), orig_reconstruction.Image(1));
277 
278  for (const auto& point3D : reconstruction.Points3D()) {
279  CheckVariablePoint(point3D.second,
280  orig_reconstruction.Point3D(point3D.first));
281  }
282 }
283 
284 BOOST_AUTO_TEST_CASE(TestPartiallyContainedTracks) {
285  Reconstruction reconstruction;
286  CorrespondenceGraph correspondence_graph;
287  GenerateReconstruction(3, 100, &reconstruction, &correspondence_graph);
288  const auto variable_point3D_id =
289  reconstruction.Image(2).Point2D(0).Point3DId();
290  reconstruction.DeleteObservation(2, 0);
291 
292  const auto orig_reconstruction = reconstruction;
293 
294  BundleAdjustmentConfig config;
295  config.AddImage(0);
296  config.AddImage(1);
297  config.SetConstantPose(0);
298  config.SetConstantPose(1);
299 
300  BundleAdjustmentOptions options;
301  BundleAdjuster bundle_adjuster(options, config);
302  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
303 
304  const auto summary = bundle_adjuster.Summary();
305 
306  // 100 points, 2 images, 2 residuals per point per image
307  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 400);
308  // 1 x 3 point parameters
309  // 2 x 2 camera parameters
310  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 7);
311 
312  CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
313  CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0));
314 
315  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
316  CheckConstantImage(reconstruction.Image(1), orig_reconstruction.Image(1));
317 
318  CheckConstantCamera(reconstruction.Camera(2), orig_reconstruction.Camera(2));
319  CheckConstantImage(reconstruction.Image(2), orig_reconstruction.Image(2));
320 
321  for (const auto& point3D : reconstruction.Points3D()) {
322  if (point3D.first == variable_point3D_id) {
323  CheckVariablePoint(point3D.second,
324  orig_reconstruction.Point3D(point3D.first));
325  } else {
326  CheckConstantPoint(point3D.second,
327  orig_reconstruction.Point3D(point3D.first));
328  }
329  }
330 }
331 
332 BOOST_AUTO_TEST_CASE(TestPartiallyContainedTracksForceToOptimizePoint) {
333  Reconstruction reconstruction;
334  CorrespondenceGraph correspondence_graph;
335  GenerateReconstruction(3, 100, &reconstruction, &correspondence_graph);
336  const point3D_t variable_point3D_id =
337  reconstruction.Image(2).Point2D(0).Point3DId();
338  const point3D_t add_variable_point3D_id =
339  reconstruction.Image(2).Point2D(1).Point3DId();
340  const point3D_t add_constant_point3D_id =
341  reconstruction.Image(2).Point2D(2).Point3DId();
342  reconstruction.DeleteObservation(2, 0);
343 
344  const auto orig_reconstruction = reconstruction;
345 
346  BundleAdjustmentConfig config;
347  config.AddImage(0);
348  config.AddImage(1);
349  config.SetConstantPose(0);
350  config.SetConstantPose(1);
351  config.AddVariablePoint(add_variable_point3D_id);
352  config.AddConstantPoint(add_constant_point3D_id);
353 
354  BundleAdjustmentOptions options;
355  BundleAdjuster bundle_adjuster(options, config);
356  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
357 
358  const auto summary = bundle_adjuster.Summary();
359 
360  // 100 points, 2 images, 2 residuals per point per image
361  // + 2 residuals in 3rd image for added variable 3D point
362  // (added constant point does not add residuals since the image/camera
363  // is also constant).
364  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 402);
365  // 2 x 3 point parameters
366  // 2 x 2 camera parameters
367  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 10);
368 
369  CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
370  CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0));
371 
372  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
373  CheckConstantImage(reconstruction.Image(1), orig_reconstruction.Image(1));
374 
375  CheckConstantCamera(reconstruction.Camera(2), orig_reconstruction.Camera(2));
376  CheckConstantImage(reconstruction.Image(2), orig_reconstruction.Image(2));
377 
378  for (const auto& point3D : reconstruction.Points3D()) {
379  if (point3D.first == variable_point3D_id ||
380  point3D.first == add_variable_point3D_id) {
381  CheckVariablePoint(point3D.second,
382  orig_reconstruction.Point3D(point3D.first));
383  } else {
384  CheckConstantPoint(point3D.second,
385  orig_reconstruction.Point3D(point3D.first));
386  }
387  }
388 }
389 
390 BOOST_AUTO_TEST_CASE(TestConstantPoints) {
391  Reconstruction reconstruction;
392  CorrespondenceGraph correspondence_graph;
393  GenerateReconstruction(2, 100, &reconstruction, &correspondence_graph);
394  const auto orig_reconstruction = reconstruction;
395 
396  const point3D_t constant_point3D_id1 = 1;
397  const point3D_t constant_point3D_id2 = 2;
398 
399  BundleAdjustmentConfig config;
400  config.AddImage(0);
401  config.AddImage(1);
402  config.SetConstantPose(0);
403  config.SetConstantPose(1);
404  config.AddConstantPoint(constant_point3D_id1);
405  config.AddConstantPoint(constant_point3D_id2);
406 
407  BundleAdjustmentOptions options;
408  BundleAdjuster bundle_adjuster(options, config);
409  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
410 
411  const auto summary = bundle_adjuster.Summary();
412 
413  // 100 points, 2 images, 2 residuals per point per image
414  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 400);
415  // 98 x 3 point parameters
416  // + 2 x 2 camera parameters
417  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 298);
418 
419  CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
420  CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0));
421 
422  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
423  CheckConstantImage(reconstruction.Image(1), orig_reconstruction.Image(1));
424 
425  for (const auto& point3D : reconstruction.Points3D()) {
426  if (point3D.first == constant_point3D_id1 ||
427  point3D.first == constant_point3D_id2) {
428  CheckConstantPoint(point3D.second,
429  orig_reconstruction.Point3D(point3D.first));
430  } else {
431  CheckVariablePoint(point3D.second,
432  orig_reconstruction.Point3D(point3D.first));
433  }
434  }
435 }
436 
437 BOOST_AUTO_TEST_CASE(TestVariableImage) {
438  Reconstruction reconstruction;
439  CorrespondenceGraph correspondence_graph;
440  GenerateReconstruction(3, 100, &reconstruction, &correspondence_graph);
441  const auto orig_reconstruction = reconstruction;
442 
443  BundleAdjustmentConfig config;
444  config.AddImage(0);
445  config.AddImage(1);
446  config.AddImage(2);
447  config.SetConstantPose(0);
448  config.SetConstantTvec(1, {0});
449 
450  BundleAdjustmentOptions options;
451  BundleAdjuster bundle_adjuster(options, config);
452  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
453 
454  const auto summary = bundle_adjuster.Summary();
455 
456  // 100 points, 3 images, 2 residuals per point per image
457  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 600);
458  // 100 x 3 point parameters
459  // + 5 image parameters (pose of second image)
460  // + 6 image parameters (pose of third image)
461  // + 3 x 2 camera parameters
462  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 317);
463 
464  CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
465  CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0));
466 
467  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
468  CheckConstantXImage(reconstruction.Image(1), orig_reconstruction.Image(1));
469 
470  CheckVariableCamera(reconstruction.Camera(2), orig_reconstruction.Camera(2));
471  CheckVariableImage(reconstruction.Image(2), orig_reconstruction.Image(2));
472 
473  for (const auto& point3D : reconstruction.Points3D()) {
474  CheckVariablePoint(point3D.second,
475  orig_reconstruction.Point3D(point3D.first));
476  }
477 }
478 
479 BOOST_AUTO_TEST_CASE(TestConstantFocalLength) {
480  Reconstruction reconstruction;
481  CorrespondenceGraph correspondence_graph;
482  GenerateReconstruction(2, 100, &reconstruction, &correspondence_graph);
483  const auto orig_reconstruction = reconstruction;
484 
485  BundleAdjustmentConfig config;
486  config.AddImage(0);
487  config.AddImage(1);
488  config.SetConstantPose(0);
489  config.SetConstantTvec(1, {0});
490 
491  BundleAdjustmentOptions options;
492  options.refine_focal_length = false;
493  BundleAdjuster bundle_adjuster(options, config);
494  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
495 
496  const auto summary = bundle_adjuster.Summary();
497 
498  // 100 points, 3 images, 2 residuals per point per image
499  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 400);
500  // 100 x 3 point parameters
501  // + 5 image parameters (pose of second image)
502  // + 2 camera parameters
503  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 307);
504 
505  CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0));
506  CheckConstantXImage(reconstruction.Image(1), orig_reconstruction.Image(1));
507 
508  const size_t focal_length_idx = SimpleRadialCameraModel::focal_length_idxs[0];
509  const size_t extra_param_idx = SimpleRadialCameraModel::extra_params_idxs[0];
510 
511  const auto& camera0 = reconstruction.Camera(0);
512  const auto& orig_camera0 = orig_reconstruction.Camera(0);
513  BOOST_CHECK(camera0.Params(focal_length_idx) ==
514  orig_camera0.Params(focal_length_idx));
515  BOOST_CHECK(camera0.Params(extra_param_idx) !=
516  orig_camera0.Params(extra_param_idx));
517 
518  const auto& camera1 = reconstruction.Camera(1);
519  const auto& orig_camera1 = orig_reconstruction.Camera(1);
520  BOOST_CHECK(camera1.Params(focal_length_idx) ==
521  orig_camera1.Params(focal_length_idx));
522  BOOST_CHECK(camera1.Params(extra_param_idx) !=
523  orig_camera1.Params(extra_param_idx));
524 
525  for (const auto& point3D : reconstruction.Points3D()) {
526  CheckVariablePoint(point3D.second,
527  orig_reconstruction.Point3D(point3D.first));
528  }
529 }
530 
531 BOOST_AUTO_TEST_CASE(TestVariablePrincipalPoint) {
532  Reconstruction reconstruction;
533  CorrespondenceGraph correspondence_graph;
534  GenerateReconstruction(2, 100, &reconstruction, &correspondence_graph);
535  const auto orig_reconstruction = reconstruction;
536 
537  BundleAdjustmentConfig config;
538  config.AddImage(0);
539  config.AddImage(1);
540  config.SetConstantPose(0);
541  config.SetConstantTvec(1, {0});
542 
543  BundleAdjustmentOptions options;
544  options.refine_principal_point = true;
545  BundleAdjuster bundle_adjuster(options, config);
546  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
547 
548  const auto summary = bundle_adjuster.Summary();
549 
550  // 100 points, 3 images, 2 residuals per point per image
551  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 400);
552  // 100 x 3 point parameters
553  // + 5 image parameters (pose of second image)
554  // + 8 camera parameters
555  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 313);
556 
557  CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0));
558  CheckConstantXImage(reconstruction.Image(1), orig_reconstruction.Image(1));
559 
560  const size_t focal_length_idx = SimpleRadialCameraModel::focal_length_idxs[0];
561  const size_t principal_point_idx_x =
563  const size_t principal_point_idx_y =
565  const size_t extra_param_idx = SimpleRadialCameraModel::extra_params_idxs[0];
566 
567  const auto& camera0 = reconstruction.Camera(0);
568  const auto& orig_camera0 = orig_reconstruction.Camera(0);
569  BOOST_CHECK(camera0.Params(focal_length_idx) !=
570  orig_camera0.Params(focal_length_idx));
571  BOOST_CHECK(camera0.Params(principal_point_idx_x) !=
572  orig_camera0.Params(principal_point_idx_x));
573  BOOST_CHECK(camera0.Params(principal_point_idx_y) !=
574  orig_camera0.Params(principal_point_idx_y));
575  BOOST_CHECK(camera0.Params(extra_param_idx) !=
576  orig_camera0.Params(extra_param_idx));
577 
578  const auto& camera1 = reconstruction.Camera(1);
579  const auto& orig_camera1 = orig_reconstruction.Camera(1);
580  BOOST_CHECK(camera1.Params(focal_length_idx) !=
581  orig_camera1.Params(focal_length_idx));
582  BOOST_CHECK(camera1.Params(principal_point_idx_x) !=
583  orig_camera1.Params(principal_point_idx_x));
584  BOOST_CHECK(camera1.Params(principal_point_idx_y) !=
585  orig_camera1.Params(principal_point_idx_y));
586  BOOST_CHECK(camera1.Params(extra_param_idx) !=
587  orig_camera1.Params(extra_param_idx));
588 
589  for (const auto& point3D : reconstruction.Points3D()) {
590  CheckVariablePoint(point3D.second,
591  orig_reconstruction.Point3D(point3D.first));
592  }
593 }
594 
595 BOOST_AUTO_TEST_CASE(TestConstantExtraParam) {
596  Reconstruction reconstruction;
597  CorrespondenceGraph correspondence_graph;
598  GenerateReconstruction(2, 100, &reconstruction, &correspondence_graph);
599  const auto orig_reconstruction = reconstruction;
600 
601  BundleAdjustmentConfig config;
602  config.AddImage(0);
603  config.AddImage(1);
604  config.SetConstantPose(0);
605  config.SetConstantTvec(1, {0});
606 
607  BundleAdjustmentOptions options;
608  options.refine_extra_params = false;
609  BundleAdjuster bundle_adjuster(options, config);
610  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
611 
612  const auto summary = bundle_adjuster.Summary();
613 
614  // 100 points, 3 images, 2 residuals per point per image
615  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 400);
616  // 100 x 3 point parameters
617  // + 5 image parameters (pose of second image)
618  // + 2 camera parameters
619  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 307);
620 
621  CheckConstantImage(reconstruction.Image(0), orig_reconstruction.Image(0));
622  CheckConstantXImage(reconstruction.Image(1), orig_reconstruction.Image(1));
623 
624  const size_t focal_length_idx = SimpleRadialCameraModel::focal_length_idxs[0];
625  const size_t extra_param_idx = SimpleRadialCameraModel::extra_params_idxs[0];
626 
627  const auto& camera0 = reconstruction.Camera(0);
628  const auto& orig_camera0 = orig_reconstruction.Camera(0);
629  BOOST_CHECK(camera0.Params(focal_length_idx) !=
630  orig_camera0.Params(focal_length_idx));
631  BOOST_CHECK(camera0.Params(extra_param_idx) ==
632  orig_camera0.Params(extra_param_idx));
633 
634  const auto& camera1 = reconstruction.Camera(1);
635  const auto& orig_camera1 = orig_reconstruction.Camera(1);
636  BOOST_CHECK(camera1.Params(focal_length_idx) !=
637  orig_camera1.Params(focal_length_idx));
638  BOOST_CHECK(camera1.Params(extra_param_idx) ==
639  orig_camera1.Params(extra_param_idx));
640 
641  for (const auto& point3D : reconstruction.Points3D()) {
642  CheckVariablePoint(point3D.second,
643  orig_reconstruction.Point3D(point3D.first));
644  }
645 }
646 
647 #ifdef PBA_ENABLED
648 BOOST_AUTO_TEST_CASE(TestParallelReconstructionSupported) {
649  BundleAdjustmentOptions options;
650  options.refine_focal_length = true;
651  options.refine_principal_point = false;
652  options.refine_extra_params = true;
653  Reconstruction reconstruction;
654  CorrespondenceGraph correspondence_graph;
655  GenerateReconstruction(2, 100, &reconstruction, &correspondence_graph);
656  BOOST_CHECK(ParallelBundleAdjuster::IsSupported(options, reconstruction));
657 
658  reconstruction.Camera(0).SetModelIdFromName("SIMPLE_PINHOLE");
659  BOOST_CHECK(!ParallelBundleAdjuster::IsSupported(options, reconstruction));
660 
661  reconstruction.Camera(0).SetModelIdFromName("SIMPLE_RADIAL");
662  BOOST_CHECK(ParallelBundleAdjuster::IsSupported(options, reconstruction));
663 
664  options.refine_principal_point = true;
665  BOOST_CHECK(!ParallelBundleAdjuster::IsSupported(options, reconstruction));
666  options.refine_principal_point = false;
667 
668  options.refine_focal_length = false;
669  BOOST_CHECK(!ParallelBundleAdjuster::IsSupported(options, reconstruction));
670 
671  options.refine_extra_params = false;
672  BOOST_CHECK(ParallelBundleAdjuster::IsSupported(options, reconstruction));
673 
674  options.refine_focal_length = true;
675  BOOST_CHECK(!ParallelBundleAdjuster::IsSupported(options, reconstruction));
676 }
677 
678 BOOST_AUTO_TEST_CASE(TestParallelTwoViewVariableIntrinsics) {
679  Reconstruction reconstruction;
680  CorrespondenceGraph correspondence_graph;
681  GenerateReconstruction(2, 100, &reconstruction, &correspondence_graph);
682  const auto orig_reconstruction = reconstruction;
683 
684  BundleAdjustmentConfig config;
685  config.AddImage(0);
686  config.AddImage(1);
687 
688  ParallelBundleAdjuster::Options options;
689  BundleAdjustmentOptions ba_options;
690  ba_options.refine_focal_length = true;
691  ba_options.refine_principal_point = false;
692  ba_options.refine_extra_params = true;
693  ParallelBundleAdjuster bundle_adjuster(options, ba_options, config);
694  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
695 
696  const auto summary = bundle_adjuster.Summary();
697 
698  // 100 points, 2 images, 2 residuals per point per image
699  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 400);
700  // 100 x 3 point parameters
701  // + 12 image parameters
702  // + 2 x 2 camera parameters
703  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 316);
704 
705  CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
706  CheckVariableImage(reconstruction.Image(0), orig_reconstruction.Image(0));
707 
708  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
709  CheckVariableImage(reconstruction.Image(1), orig_reconstruction.Image(1));
710 
711  for (const auto& point3D : reconstruction.Points3D()) {
712  CheckVariablePoint(point3D.second,
713  orig_reconstruction.Point3D(point3D.first));
714  }
715 }
716 
717 BOOST_AUTO_TEST_CASE(TestParallelTwoViewConstantIntrinsics) {
718  Reconstruction reconstruction;
719  CorrespondenceGraph correspondence_graph;
720  GenerateReconstruction(2, 100, &reconstruction, &correspondence_graph);
721  const auto orig_reconstruction = reconstruction;
722 
723  BundleAdjustmentConfig config;
724  config.AddImage(0);
725  config.AddImage(1);
726 
727  ParallelBundleAdjuster::Options options;
728  BundleAdjustmentOptions ba_options;
729  ba_options.refine_focal_length = false;
730  ba_options.refine_principal_point = false;
731  ba_options.refine_extra_params = false;
732  ParallelBundleAdjuster bundle_adjuster(options, ba_options, config);
733  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction));
734 
735  const auto summary = bundle_adjuster.Summary();
736 
737  // 100 points, 2 images, 2 residuals per point per image
738  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 400);
739  // 100 x 3 point parameters
740  // + 12 image parameters
741  // + 2 x 2 camera parameters
742  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 316);
743 
744  CheckConstantCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
745  CheckVariableImage(reconstruction.Image(0), orig_reconstruction.Image(0));
746 
747  CheckConstantCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
748  CheckVariableImage(reconstruction.Image(1), orig_reconstruction.Image(1));
749 
750  for (const auto& point3D : reconstruction.Points3D()) {
751  CheckVariablePoint(point3D.second,
752  orig_reconstruction.Point3D(point3D.first));
753  }
754 }
755 #endif
756 
757 BOOST_AUTO_TEST_CASE(TestRigTwoView) {
758  Reconstruction reconstruction;
759  CorrespondenceGraph correspondence_graph;
760  GenerateReconstruction(2, 100, &reconstruction, &correspondence_graph);
761  const auto orig_reconstruction = reconstruction;
762 
763  BundleAdjustmentConfig config;
764  config.AddImage(0);
765  config.AddImage(1);
766 
767  std::vector<CameraRig> camera_rigs;
768  camera_rigs.emplace_back();
769  camera_rigs[0].AddCamera(0, ComposeIdentityQuaternion(),
770  Eigen::Vector3d(0, 0, 0));
771  camera_rigs[0].AddCamera(1, ComposeIdentityQuaternion(),
772  Eigen::Vector3d(0, 0, 0));
773  camera_rigs[0].AddSnapshot({0, 1});
774  camera_rigs[0].SetRefCameraId(0);
775  const auto orig_camera_rigs = camera_rigs;
776 
777  BundleAdjustmentOptions options;
778  RigBundleAdjuster::Options rig_options;
779  RigBundleAdjuster bundle_adjuster(options, rig_options, config);
780  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction, &camera_rigs));
781 
782  const auto summary = bundle_adjuster.Summary();
783 
784  // 100 points, 2 images, 2 residuals per point per image
785  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 400);
786  // 100 x 3 point parameters
787  // + 6 pose parameters for camera rig
788  // + 1 x 6 relative pose parameters for camera rig
789  // + 2 x 2 camera parameters
790  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 316);
791 
792  CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
793  CheckVariableImage(reconstruction.Image(0), orig_reconstruction.Image(0));
794 
795  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
796  CheckVariableImage(reconstruction.Image(1), orig_reconstruction.Image(1));
797 
798  CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 0);
799  CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 1);
800 
801  for (const auto& point3D : reconstruction.Points3D()) {
802  CheckVariablePoint(point3D.second,
803  orig_reconstruction.Point3D(point3D.first));
804  }
805 }
806 
807 BOOST_AUTO_TEST_CASE(TestRigFourView) {
808  Reconstruction reconstruction;
809  CorrespondenceGraph correspondence_graph;
810  GenerateReconstruction(4, 100, &reconstruction, &correspondence_graph);
811  reconstruction.Image(2).SetCameraId(0);
812  reconstruction.Image(3).SetCameraId(1);
813  const auto orig_reconstruction = reconstruction;
814 
815  BundleAdjustmentConfig config;
816  config.AddImage(0);
817  config.AddImage(1);
818  config.AddImage(2);
819  config.AddImage(3);
820 
821  std::vector<CameraRig> camera_rigs;
822  camera_rigs.emplace_back();
823  camera_rigs[0].AddCamera(0, ComposeIdentityQuaternion(),
824  Eigen::Vector3d(0, 0, 0));
825  camera_rigs[0].AddCamera(1, ComposeIdentityQuaternion(),
826  Eigen::Vector3d(0, 0, 0));
827  camera_rigs[0].AddSnapshot({0, 1});
828  camera_rigs[0].AddSnapshot({2, 3});
829  camera_rigs[0].SetRefCameraId(0);
830  const auto orig_camera_rigs = camera_rigs;
831 
832  BundleAdjustmentOptions options;
833  RigBundleAdjuster::Options rig_options;
834  RigBundleAdjuster bundle_adjuster(options, rig_options, config);
835  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction, &camera_rigs));
836 
837  const auto summary = bundle_adjuster.Summary();
838 
839  // 100 points, 2 images, 2 residuals per point per image
840  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 800);
841  // 100 x 3 point parameters
842  // + 2 x 6 pose parameters for camera rig
843  // + 1 x 6 relative pose parameters for camera rig
844  // + 2 x 2 camera parameters
845  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 322);
846 
847  CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
848  CheckVariableImage(reconstruction.Image(0), orig_reconstruction.Image(0));
849 
850  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
851  CheckVariableImage(reconstruction.Image(1), orig_reconstruction.Image(1));
852 
853  CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 0);
854  CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 1);
855 
856  for (const auto& point3D : reconstruction.Points3D()) {
857  CheckVariablePoint(point3D.second,
858  orig_reconstruction.Point3D(point3D.first));
859  }
860 }
861 
862 BOOST_AUTO_TEST_CASE(TestConstantRigFourView) {
863  Reconstruction reconstruction;
864  CorrespondenceGraph correspondence_graph;
865  GenerateReconstruction(4, 100, &reconstruction, &correspondence_graph);
866  reconstruction.Image(2).SetCameraId(0);
867  reconstruction.Image(3).SetCameraId(1);
868  const auto orig_reconstruction = reconstruction;
869 
870  BundleAdjustmentConfig config;
871  config.AddImage(0);
872  config.AddImage(1);
873  config.AddImage(2);
874  config.AddImage(3);
875 
876  std::vector<CameraRig> camera_rigs;
877  camera_rigs.emplace_back();
878  camera_rigs[0].AddCamera(0, ComposeIdentityQuaternion(),
879  Eigen::Vector3d(0, 0, 0));
880  camera_rigs[0].AddCamera(1, ComposeIdentityQuaternion(),
881  Eigen::Vector3d(0, 0, 0));
882  camera_rigs[0].AddSnapshot({0, 1});
883  camera_rigs[0].AddSnapshot({2, 3});
884  camera_rigs[0].SetRefCameraId(0);
885  const auto orig_camera_rigs = camera_rigs;
886 
887  BundleAdjustmentOptions options;
888  RigBundleAdjuster::Options rig_options;
889  rig_options.refine_relative_poses = false;
890  RigBundleAdjuster bundle_adjuster(options, rig_options, config);
891  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction, &camera_rigs));
892 
893  const auto summary = bundle_adjuster.Summary();
894 
895  // 100 points, 2 images, 2 residuals per point per image
896  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 800);
897  // 100 x 3 point parameters
898  // + 2 x 6 pose parameters for camera rig
899  // + 2 x 2 camera parameters
900  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 316);
901 
902  CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
903  CheckVariableImage(reconstruction.Image(0), orig_reconstruction.Image(0));
904 
905  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
906  CheckVariableImage(reconstruction.Image(1), orig_reconstruction.Image(1));
907 
908  CheckConstantCameraRig(camera_rigs[0], orig_camera_rigs[0], 0);
909  CheckConstantCameraRig(camera_rigs[0], orig_camera_rigs[0], 1);
910 
911  for (const auto& point3D : reconstruction.Points3D()) {
912  CheckVariablePoint(point3D.second,
913  orig_reconstruction.Point3D(point3D.first));
914  }
915 }
916 
917 BOOST_AUTO_TEST_CASE(TestRigFourViewPartial) {
918  Reconstruction reconstruction;
919  CorrespondenceGraph correspondence_graph;
920  GenerateReconstruction(4, 100, &reconstruction, &correspondence_graph);
921  reconstruction.Image(2).SetCameraId(0);
922  reconstruction.Image(3).SetCameraId(1);
923  const auto orig_reconstruction = reconstruction;
924 
925  BundleAdjustmentConfig config;
926  config.AddImage(0);
927  config.AddImage(1);
928  config.AddImage(2);
929  config.AddImage(3);
930 
931  std::vector<CameraRig> camera_rigs;
932  camera_rigs.emplace_back();
933  camera_rigs[0].AddCamera(0, ComposeIdentityQuaternion(),
934  Eigen::Vector3d(0, 0, 0));
935  camera_rigs[0].AddCamera(1, ComposeIdentityQuaternion(),
936  Eigen::Vector3d(0, 0, 0));
937  camera_rigs[0].AddSnapshot({0, 1});
938  camera_rigs[0].AddSnapshot({2});
939  camera_rigs[0].SetRefCameraId(0);
940  const auto orig_camera_rigs = camera_rigs;
941 
942  BundleAdjustmentOptions options;
943  RigBundleAdjuster::Options rig_options;
944  RigBundleAdjuster bundle_adjuster(options, rig_options, config);
945  BOOST_REQUIRE(bundle_adjuster.Solve(&reconstruction, &camera_rigs));
946 
947  const auto summary = bundle_adjuster.Summary();
948 
949  // 100 points, 2 images, 2 residuals per point per image
950  BOOST_CHECK_EQUAL(summary.num_residuals_reduced, 800);
951  // 100 x 3 point parameters
952  // + 2 x 6 pose parameters for camera rig
953  // + 1 x 6 relative pose parameters for camera rig
954  // + 1 x 6 pose parameters for individual image
955  // + 2 x 2 camera parameters
956  BOOST_CHECK_EQUAL(summary.num_effective_parameters_reduced, 328);
957 
958  CheckVariableCamera(reconstruction.Camera(0), orig_reconstruction.Camera(0));
959  CheckVariableImage(reconstruction.Image(0), orig_reconstruction.Image(0));
960 
961  CheckVariableCamera(reconstruction.Camera(1), orig_reconstruction.Camera(1));
962  CheckVariableImage(reconstruction.Image(1), orig_reconstruction.Image(1));
963 
964  CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 0);
965  CheckVariableCameraRig(camera_rigs[0], orig_camera_rigs[0], 1);
966 
967  for (const auto& point3D : reconstruction.Points3D()) {
968  CheckVariablePoint(point3D.second,
969  orig_reconstruction.Point3D(point3D.first));
970  }
971 }
std::shared_ptr< core::Tensor > image
#define CheckConstantImage(image, orig_image)
#define CheckVariableCamera(camera, orig_camera)
#define CheckVariableCameraRig(camera_rig, orig_camera_rig, camera_id)
#define CheckConstantXImage(image, orig_image)
#define CheckConstantPoint(point, orig_point)
#define CheckConstantCamera(camera, orig_camera)
#define CheckConstantCameraRig(camera_rig, orig_camera_rig, camera_id)
BOOST_AUTO_TEST_CASE(TestConfigNumObservations)
void GenerateReconstruction(const size_t num_images, const size_t num_points, Reconstruction *reconstruction, CorrespondenceGraph *correspondence_graph)
void GeneratePointCloud(const size_t num_points, const Eigen::Vector3d &min, const Eigen::Vector3d &max, Reconstruction *reconstruction)
#define CheckVariableImage(image, orig_image)
#define CheckVariablePoint(point, orig_point)
const ceres::Solver::Summary & Summary() const
bool Solve(Reconstruction *reconstruction)
void AddVariablePoint(const point3D_t point3D_id)
void SetConstantCamera(const camera_t camera_id)
void SetConstantPose(const image_t image_id)
void AddImage(const image_t image_id)
void SetConstantTvec(const image_t image_id, const std::vector< int > &idxs)
void AddConstantPoint(const point3D_t point3D_id)
size_t NumResiduals(const Reconstruction &reconstruction) const
void InitializeWithId(const int model_id, const double focal_length, const size_t width, const size_t height)
Definition: camera.cc:203
void SetModelIdFromName(const std::string &model_name)
Definition: camera.cc:57
void SetCameraId(const camera_t camera_id)
Definition: camera.h:156
void AddImage(const image_t image_id, const size_t num_points2D)
void SetPoints2D(const std::vector< Eigen::Vector2d > &points)
Definition: image.cc:71
void SetCameraId(const camera_t camera_id)
Definition: image.h:250
const class Point2D & Point2D(const point2D_t point2D_idx) const
Definition: image.h:349
point3D_t Point3DId() const
Definition: point2d.h:63
void AddImage(const class Image &image)
void AddCamera(const class Camera &camera)
void DeleteObservation(const image_t image_id, const point2D_t point2D_idx)
const class Image & Image(const image_t image_id) const
const class Camera & Camera(const camera_t camera_id) const
const std::unordered_map< point3D_t, class Point3D > & Points3D() const
void AddObservation(const point3D_t point3D_id, const TrackElement &track_el)
point3D_t AddPoint3D(const Eigen::Vector3d &xyz, const Track &track, const Eigen::Vector3ub &color=Eigen::Vector3ub::Zero())
void SetUp(const CorrespondenceGraph *correspondence_graph)
bool Solve(Reconstruction *reconstruction, std::vector< CameraRig > *camera_rigs)
Matrix< double, 3, 4 > Matrix3x4d
Definition: types.h:39
bool HasPointPositiveDepth(const Eigen::Matrix3x4d &proj_matrix, const Eigen::Vector3d &point3D)
Definition: projection.cc:191
void SetPRNGSeed(unsigned seed)
Definition: random.cc:40
uint64_t point3D_t
Definition: types.h:72
Eigen::Vector4d ComposeIdentityQuaternion()
Definition: pose.h:209
uint32_t image_t
Definition: types.h:61
uint32_t camera_t
Definition: types.h:58
T RandomReal(const T min, const T max)
Definition: random.h:75
Eigen::Vector2d ProjectPointToImage(const Eigen::Vector3d &point3D, const Eigen::Matrix3x4d &proj_matrix, const Camera &camera)
Definition: projection.cc:104
std::string to_string(const T &n)
Definition: Common.h:20
static const std::vector< size_t > principal_point_idxs
static const std::vector< size_t > focal_length_idxs
static const std::vector< size_t > extra_params_idxs
image_t image_id
Definition: track.h:22
point2D_t point2D_idx
Definition: track.h:24