vpgl_ba_shared_k_lsqr.cxx
Go to the documentation of this file.
1 // This is vpgl/algo/vpgl_ba_shared_k_lsqr.cxx
3 //:
4 // \file
5 
6 #include <vnl/vnl_vector_ref.h>
8 #include <vnl/vnl_double_3.h>
9 
10 
11 //: Constructor
12 vpgl_ba_shared_k_lsqr::
13 vpgl_ba_shared_k_lsqr(const vpgl_calibration_matrix<double>& K,
14  const std::vector<vgl_point_2d<double> >& image_points,
15  const std::vector<std::vector<bool> >& mask)
16  : vpgl_bundle_adjust_lsqr(6,3,1,image_points,mask),
17  K_(K)
18 {
19  // K_ is over parameterized, so enforce x_scale == 1.0
20  if (K_.x_scale() != 1.0)
21  {
22  K_.set_focal_length(K_.focal_length() * K_.x_scale());
23  K_.set_y_scale(K_.y_scale() * K_.x_scale());
24  K_.set_x_scale(1.0);
25  }
26  Km_ = K_.get_matrix();
27 }
28 
29 
30 //: Constructor
31 // Each image point is assigned an inverse covariance (error projector) matrix
32 // \note image points are not homogeneous because they require finite points to measure projection error
33 vpgl_ba_shared_k_lsqr::
34 vpgl_ba_shared_k_lsqr(const vpgl_calibration_matrix<double>& K,
35  const std::vector<vgl_point_2d<double> >& image_points,
36  const std::vector<vnl_matrix<double> >& inv_covars,
37  const std::vector<std::vector<bool> >& mask)
38  : vpgl_bundle_adjust_lsqr(6,3,1,image_points,inv_covars,mask),
39  K_(K)
40 {
41  // K_ is over parameterized, so enforce x_scale == 1.0
42  if (K_.x_scale() != 1.0)
43  {
44  K_.set_focal_length(K_.focal_length() * K_.x_scale());
45  K_.set_y_scale(K_.y_scale() * K_.x_scale());
46  K_.set_x_scale(1.0);
47  }
48  Km_ = K_.get_matrix();
49 }
50 
51 
52 //: compute the Jacobian Aij
53 void vpgl_ba_shared_k_lsqr::jac_Aij(unsigned int /*i*/,
54  unsigned int /*j*/,
55  vnl_double_3x4 const& Pi,
56  vnl_vector<double> const& ai,
57  vnl_vector<double> const& bj,
58  vnl_vector<double> const& c,
59  vnl_matrix<double>& Aij)
60 {
61  // the translation part
62  // --------------------
63  vnl_double_3x3 M = Pi.extract(3,3);
64  // This is semi const incorrect - there is no vnl_vector_ref_const
65  const vnl_vector_ref<double> C(3,const_cast<double*>(ai.data_block())+3);
66  vnl_matrix<double> Aij_sub(2,3);
67  jac_camera_center(M,C,bj,Aij_sub);
68  Aij.update(Aij_sub,0,3);
69 
70 
71  // the rotation part
72  // -----------------
73  // This is semi const incorrect - there is no vnl_vector_ref_const
74  const vnl_vector_ref<double> r(3,const_cast<double*>(ai.data_block()));
75  Km_(0,0) = c[0];
76  Km_(1,1) = c[0] * K_.y_scale();
77  jac_camera_rotation(Km_,C,r,bj,Aij);
78 }
79 
80 //: compute the Jacobian Bij
81 void vpgl_ba_shared_k_lsqr::jac_Bij(unsigned int /*i*/,
82  unsigned int /*j*/,
83  vnl_double_3x4 const& Pi,
84  vnl_vector<double> const& /*ai*/,
85  vnl_vector<double> const& bj,
86  vnl_vector<double> const& /*c*/,
87  vnl_matrix<double>& Bij)
88 {
89  jac_inhomg_3d_point(Pi, bj, Bij);
90 }
91 
92 //: compute the Jacobian Cij
93 void vpgl_ba_shared_k_lsqr::jac_Cij(unsigned int /*i*/,
94  unsigned int /*j*/,
95  vnl_double_3x4 const& Pi,
96  vnl_vector<double> const& /*ai*/,
97  vnl_vector<double> const& bj,
98  vnl_vector<double> const& c,
99  vnl_matrix<double>& Cij)
100 {
101  vnl_double_3 p = Pi*vnl_vector_fixed<double,4>(bj[0], bj[1], bj[2], 1.0);
102 
103  double inv_f = 1.0/c[0];
104  double skew_term = K_.skew()*inv_f/K_.y_scale();
105  vgl_point_2d<double> pp = K_.principal_point();
106  Cij(1,0) = inv_f * (p[1]/p[2] - pp.y());
107  Cij(0,0) = inv_f * (p[0]/p[2] - pp.x()) - skew_term*Cij(1,0);
108 }
109 
110 //: construct the \param j-th perspective camera from a pointer to the j-th parameter of \param b and parameters \param c
112 vpgl_ba_shared_k_lsqr::param_to_point(int /*j*/,
113  const double* bj,
114  const vnl_vector<double>& /*c*/) const
115 {
116  return {bj[0], bj[1], bj[2]};
117 }
118 
119 //: construct the \param j-th perspective camera from a pointer to the j-th parameter of \param b and parameters \param c
121 vpgl_ba_shared_k_lsqr::param_to_pt_vector(int /*j*/,
122  const double* bj,
123  const vnl_vector<double>& /*c*/) const
124 {
125  return vnl_vector_fixed<double,4>(bj[0], bj[1], bj[2], 1.0);
126 }
127 
128 //: construct the \param i-th perspective camera from a pointer to the i-th parameter of \param a and parameters \param c
130 vpgl_ba_shared_k_lsqr::param_to_cam(int /*i*/,
131  const double* ai,
132  const vnl_vector<double>& c) const
133 {
134  K_.set_focal_length(c[0]);
135  vnl_vector<double> w(ai,3);
136  vgl_homg_point_3d<double> t(ai[3], ai[4], ai[5]);
138 }
139 
140 //: compute a 3x4 camera matrix of camera \param i from a pointer to the i-th parameters of \param a and parameters \param c
142 vpgl_ba_shared_k_lsqr::param_to_cam_matrix(int /*i*/,
143  const double* ai,
144  const vnl_vector<double>& c) const
145 {
146  Km_(0,0) = c[0];
147  Km_(1,1) = c[0] * K_.y_scale();
148  const vnl_vector_ref<double> r(3,const_cast<double*>(ai));
149  vnl_double_3x3 M = Km_*rod_to_matrix(r);
150  vnl_double_3x4 P;
151  P.update(M);
152  const vnl_vector_ref<double> center(3,const_cast<double*>(ai+3));
153  P.set_column(3,-(M*center));
154  return P;
155 }
156 
157 
158 //: Create the parameter vector \p a from a vector of cameras
159 void
160 vpgl_ba_shared_k_lsqr::
161 create_param_vector(const std::vector<vpgl_perspective_camera<double> >& cameras,
164 {
165  a.set_size(6*cameras.size());
166  c.set_size(1);
167  // compute the average intrinsic parameters
168  c[0] = 0.0;
169  for (unsigned int i=0; i<cameras.size(); ++i)
170  {
171  const vpgl_perspective_camera<double>& cam = cameras[i];
172  const vgl_point_3d<double>& C = cam.get_camera_center();
173  const vgl_rotation_3d<double>& R = cam.get_rotation();
175 
176  c[0] += K.focal_length() * K.x_scale();
177 
178  // compute the Rodrigues vector from the rotation
180 
181  double* ai = a.data_block() + i*6;
182  ai[0]=w[0]; ai[1]=w[1]; ai[2]=w[2];
183  ai[3]=C.x(); ai[4]=C.y(); ai[5]=C.z();
184  }
185  c[0] /= cameras.size();
186 }
187 
188 
189 //: Create the parameter vector \p b from a vector of 3D points
191 vpgl_ba_shared_k_lsqr::create_param_vector(const std::vector<vgl_point_3d<double> >& world_points)
192 {
193  vnl_vector<double> b(3*world_points.size(),0.0);
194  for (unsigned int j=0; j<world_points.size(); ++j){
195  const vgl_point_3d<double>& point = world_points[j];
196  double* bj = b.data_block() + j*3;
197  bj[0]=point.x(); bj[1]=point.y(); bj[2]=point.z();
198  }
199  return b;
200 }
bool set_size(size_t n)
size_t size() const
double const * data_block() const
vnl_matrix_fixed & update(vnl_matrix< T > const &, unsigned top=0, unsigned left=0)
vnl_vector_fixed< T, 3 > as_rodrigues() const
std::vector< vpgl_calibration_matrix< double > > K_
The fixed internal camera calibration.
Type & z()
const vpgl_calibration_matrix< T > & get_calibration() const
const vgl_rotation_3d< T > & get_rotation() const
std::vector< vnl_double_3x3 > Km_
The fixed internal camera calibration in matrix form.
base class bundle adjustment sparse least squares function.
vnl_matrix< T > extract(unsigned r, unsigned c, unsigned top=0, unsigned left=0) const
Type & y()
const vgl_point_3d< T > & get_camera_center() const
Type & x()
This class implements the perspective camera class as described in Hartley & Zisserman as a finite ca...
vnl_matrix_fixed & set_column(unsigned i, T const *v)
vnl_matrix< double > & update(vnl_matrix< double > const &, unsigned top=0, unsigned left=0)
Type & y()
Type & x()