vpgl_calibration_matrix_compute.cxx
Go to the documentation of this file.
1 // This is core/vpgl/algo/vpgl_calibration_matrix_compute.cxx
2 #include <iostream>
4 #ifdef _MSC_VER
5 # include <vcl_msvc_warnings.h>
6 #endif
7 #include <vnl/vnl_matrix_fixed.h>
8 #include <vnl/vnl_vector_fixed.h>
9 #include <vnl/vnl_det.h>
12 
13 bool
15  const vgl_point_2d<double>& principal_point,
17 {
18  // For zero skew and square aspect ratio, the IAC is of the following form:
19  //
20  // 1 [ 1 0 -u0 ]
21  // w = ----- [ 0 1 -v0 ]
22  // f^2 [ -u0 -v0 u0^2 + v0^2 + f^2 ]
23  //
24  // For a homography, we have two constraint equations:
25  // h1^T * w * h2 = 0
26  // h1^T * w * h1 = h2^T * w * h2
27  //
28  // Although 'f' is the single unknown we want to calculate, it's easier
29  // to solve for w[2][2], as that is a system of over determined linear
30  // equations. Once we have a value for w[2][2] we can compute 'f'.
31 
33  const double u0 = principal_point.x();
34  const double v0 = principal_point.y();
35 
36  if ( vnl_det( H ) < 0 )
37  {
38  std::cerr << "compute::natural input homography is an inversion" << std::endl;
39  return false;
40  }
41 
42  // Set-up the system of equations Ax = b, where 'x' is 'w[2][2]'.
43  double a = - H[2][0] * H[2][1]
44  + H[2][1] * H[2][1] - H[2][0] * H[2][0];
45 
46  double b = H[0][0] * ( H[0][1] - u0 * H[2][1] )
47  + H[1][0] * ( H[1][1] - v0 * H[2][1] )
48  + H[2][0] * ( -u0 * H[0][1] - v0 * H[1][1] )
49  + H[0][0] * ( H[0][0] - u0 * H[2][0] )
50  + H[1][0] * ( H[1][0] - v0 * H[2][0] )
51  + H[2][0] * ( - u0 * H[0][0] - v0 * H[1][0] )
52  - H[0][1] * ( H[0][1] - u0 * H[2][1] )
53  - H[1][1] * ( H[1][1] - v0 * H[2][1] )
54  - H[2][1] * ( - u0 * H[0][1] - v0 * H[1][1] );
55 
56  // solve
57  double x = b / a;
58 
59  // re-arrange w[2][2] to get f^2
60  double f2 = x - u0 * u0 - v0 * v0;
61  if ( f2 < 0 )
62  {
63  std::cout << "suspicious square focal length: " << f2 << std::endl;
64  return false;
65  }
66 
67  double f = std::sqrt( f2 );
68 
69  // Done
70  K = vpgl_calibration_matrix<double>( f, principal_point );
71 
72  return true;
73 }
74 
75 bool
77  const std::vector< vgl_point_2d<double> >& ground_pts,
78  const vgl_point_2d<double>& principal_point,
80 {
81  if ( image_pts.size() != ground_pts.size() )
82  {
83  std::cerr << "number of image and ground points must be the same" << std::endl;
84  return false;
85  }
86 
87  if ( image_pts.size() < 4 )
88  {
89  std::cerr << "at least four point correspondences are required" << std::endl;
90  return false;
91  }
92 
93 
94  // convert to homogeneous coords to estimate homography
95  std::vector< vgl_homg_point_2d<double> > homg_image_pts;
96  std::vector< vgl_homg_point_2d<double> > homg_ground_pts;
97  for ( unsigned int k = 0; k < image_pts.size(); ++k )
98  {
99  homg_image_pts.emplace_back( image_pts[k] );
100  homg_ground_pts.emplace_back( ground_pts[k] );
101  }
102 
103  // estimate and optimize the ground to image homography
105  if ( vgl_h_matrix_2d_compute_linear().compute( homg_ground_pts, homg_image_pts, H ) == false )
106  {
107  std::cerr << "failed to compute homography" << std::endl;
108  return false;
109  }
110 
111  // cheirality
112  if ( vnl_det(H.get_matrix()) < 0 )
113  {
115  }
116 
117  // optimize
118  vgl_h_matrix_2d_optimize_lmq(H).optimize(homg_ground_pts, homg_image_pts, H);
119 
120  return vpgl_calibration_matrix_compute::natural(H, principal_point, K);
121 }
vnl_matrix_fixed< double, 3, 3 > const & get_matrix() const
Computes a camera calibration matrix from points on a 3D world plane.
static bool natural(const vgl_h_matrix_2d< double > &homography, const vgl_point_2d< double > &principal_point, vpgl_calibration_matrix< double > &K)
Computes the calibration matrix for a natural camera (zero skew, square pixels).
VNL_EXPORT T vnl_det(T const *row0, T const *row1)
Type & y()
bool optimize(std::vector< vgl_homg_point_2d< double > > const &points1, std::vector< vgl_homg_point_2d< double > > const &points2, vgl_h_matrix_2d< double > &H)
Type & x()