vpgl_triangulate_points.cxx
Go to the documentation of this file.
1 // This is core/vpgl/algo/vpgl_triangulate_points.cxx
2 #include <cmath>
3 #include <cstdlib>
5 //:
6 // \file
7 
8 #ifdef _MSC_VER
9 # include <vcl_msvc_warnings.h>
10 #endif
11 #include <cassert>
12 
13 #include <vgl/vgl_vector_3d.h>
14 
15 #include <vnl/vnl_matrix_fixed.h>
16 #include <vnl/vnl_matrix.h>
17 #include <vnl/vnl_vector.h>
18 #include <vnl/vnl_double_3.h>
19 #include <vnl/vnl_double_3x3.h>
20 #include <vnl/algo/vnl_svd.h>
21 
22 
24  const std::vector<vgl_point_2d<double> > &points,
25  const std::vector<vpgl_perspective_camera<double> > &cameras,
26  vgl_point_3d<double> &point_3d)
27 {
28  constexpr int num_vars = 3;// One var for x, y, z of output 3d point
29  const int num_eqs = static_cast<const int>(2 * points.size());
30 
31  // Set up the least-squares solution.
32  vnl_matrix<double> A(num_eqs, num_vars, 0.0);
33  vnl_vector<double> b(num_eqs, 0.0);
34 
35  for (unsigned int i = 0; i < points.size(); ++i) {
36  const vgl_vector_3d<double> &trans =
37  cameras[i].get_translation();
38 
39  const vnl_double_3x3 &rot =
40  cameras[i].get_rotation().as_matrix();
41 
42  const vgl_point_2d<double> pt =
43  cameras[i].get_calibration().map_to_focal_plane(points[i]);
44 
45  // Set the row for x for this point
46  A.put(2 * i, 0, rot.get(0, 0) - pt.x() * rot.get(2, 0) );
47  A.put(2 * i, 1, rot.get(0, 1) - pt.x() * rot.get(2, 1) );
48  A.put(2 * i, 2, rot.get(0, 2) - pt.x() * rot.get(2, 2) );
49 
50  // Set the row for y for this point
51  A.put(2*i+1, 0, rot.get(1, 0) - pt.y() * rot.get(2, 0) );
52  A.put(2*i+1, 1, rot.get(1, 1) - pt.y() * rot.get(2, 1) );
53  A.put(2*i+1, 2, rot.get(1, 2) - pt.y() * rot.get(2, 2) );
54 
55  // Set the RHS row.
56  b[2*i + 0] = trans.z() * pt.x() - trans.x();
57  b[2*i + 1] = trans.z() * pt.y() - trans.y();
58  }
59 
60  // Find the least squares result
61  vnl_svd<double> svd(A);
62  vnl_double_3 x = svd.solve(b);
63 
64  point_3d.set(x.begin());
65 
66  // Find the error
67  double error = 0.0;
68  for (unsigned int i = 0; i < points.size(); ++i) {
69  // Compute projection error
70  vnl_double_3 pp = cameras[i].get_rotation().as_matrix() * x;
71 
72  pp[0] += cameras[i].get_translation().x();
73  pp[1] += cameras[i].get_translation().y();
74  pp[2] += cameras[i].get_translation().z();
75 
76  double dx = pp[0] / pp[2] - points[i].x();
77  double dy = pp[1] / pp[2] - points[i].y();
78  error += dx * dx + dy * dy;
79  }
80 
81  return std::sqrt(error / points.size());
82 }
Determines the 3D location of a point in world space given the 2D location of the point as seen by a ...
const vnl_matrix< T > as_matrix() const
T get(unsigned r, unsigned c) const
vnl_matrix< T > solve(vnl_matrix< T > const &B) const
T y() const
Type & y()
T x() const
T z() const
This class implements the perspective camera class as described in Hartley & Zisserman as a finite ca...
static double triangulate(const std::vector< vgl_point_2d< double > > &points, const std::vector< vpgl_perspective_camera< double > > &cameras, vgl_point_3d< double > &point_3d)
Calculates the best 3D point corresponding to a set of 2D camera points.
void set(Type px, Type py, Type pz)
Type & x()