core/vpgl/algo/vpgl_ba_shared_k_lsqr.cxx
Go to the documentation of this file.
00001 // This is vpgl/algo/vpgl_ba_shared_k_lsqr.cxx
00002 #include "vpgl_ba_shared_k_lsqr.h"
00003 //:
00004 // \file
00005 
00006 #include <vnl/vnl_vector_ref.h>
00007 #include <vgl/algo/vgl_rotation_3d.h>
00008 #include <vnl/vnl_double_3.h>
00009 
00010 
00011 //: Constructor
00012 vpgl_ba_shared_k_lsqr::
00013 vpgl_ba_shared_k_lsqr(const vpgl_calibration_matrix<double>& K,
00014                       const vcl_vector<vgl_point_2d<double> >& image_points,
00015                       const vcl_vector<vcl_vector<bool> >& mask)
00016  : vpgl_bundle_adjust_lsqr(6,3,1,image_points,mask),
00017    K_(K)
00018 {
00019   // K_ is over parameterized, so enforce x_scale == 1.0
00020   if (K_.x_scale() != 1.0)
00021   {
00022     K_.set_focal_length(K_.focal_length() * K_.x_scale());
00023     K_.set_y_scale(K_.y_scale() * K_.x_scale());
00024     K_.set_x_scale(1.0);
00025   }
00026   Km_ = K_.get_matrix();
00027 }
00028 
00029 
00030 //: Constructor
00031 //  Each image point is assigned an inverse covariance (error projector) matrix
00032 // \note image points are not homogeneous because they require finite points to measure projection error
00033 vpgl_ba_shared_k_lsqr::
00034 vpgl_ba_shared_k_lsqr(const vpgl_calibration_matrix<double>& K,
00035                       const vcl_vector<vgl_point_2d<double> >& image_points,
00036                       const vcl_vector<vnl_matrix<double> >& inv_covars,
00037                       const vcl_vector<vcl_vector<bool> >& mask)
00038  : vpgl_bundle_adjust_lsqr(6,3,1,image_points,inv_covars,mask),
00039    K_(K)
00040 {
00041   // K_ is over parameterized, so enforce x_scale == 1.0
00042   if (K_.x_scale() != 1.0)
00043   {
00044     K_.set_focal_length(K_.focal_length() * K_.x_scale());
00045     K_.set_y_scale(K_.y_scale() * K_.x_scale());
00046     K_.set_x_scale(1.0);
00047   }
00048   Km_ = K_.get_matrix();
00049 }
00050 
00051 
00052 //: compute the Jacobian Aij
00053 void vpgl_ba_shared_k_lsqr::jac_Aij(unsigned int i,
00054                                     unsigned int j,
00055                                     vnl_double_3x4 const& Pi,
00056                                     vnl_vector<double> const& ai,
00057                                     vnl_vector<double> const& bj,
00058                                     vnl_vector<double> const& c,
00059                                     vnl_matrix<double>& Aij)
00060 {
00061   // the translation part
00062   // --------------------
00063   vnl_double_3x3 M = Pi.extract(3,3);
00064   // This is semi const incorrect - there is no vnl_vector_ref_const
00065   const vnl_vector_ref<double> C(3,const_cast<double*>(ai.data_block())+3);
00066   vnl_matrix<double> Aij_sub(2,3);
00067   jac_camera_center(M,C,bj,Aij_sub);
00068   Aij.update(Aij_sub,0,3);
00069 
00070 
00071   // the rotation part
00072   // -----------------
00073   // This is semi const incorrect - there is no vnl_vector_ref_const
00074   const vnl_vector_ref<double> r(3,const_cast<double*>(ai.data_block()));
00075   Km_(0,0) = c[0];
00076   Km_(1,1) = c[0] * K_.y_scale();
00077   jac_camera_rotation(Km_,C,r,bj,Aij);
00078 }
00079 
00080 //: compute the Jacobian Bij
00081 void vpgl_ba_shared_k_lsqr::jac_Bij(unsigned int i,
00082                                     unsigned int j,
00083                                     vnl_double_3x4 const& Pi,
00084                                     vnl_vector<double> const& ai,
00085                                     vnl_vector<double> const& bj,
00086                                     vnl_vector<double> const& c,
00087                                     vnl_matrix<double>& Bij)
00088 {
00089   jac_inhomg_3d_point(Pi, bj, Bij);
00090 }
00091 
00092 //: compute the Jacobian Cij
00093 void vpgl_ba_shared_k_lsqr::jac_Cij(unsigned int i,
00094                                     unsigned int j,
00095                                     vnl_double_3x4 const& Pi,
00096                                     vnl_vector<double> const& ai,
00097                                     vnl_vector<double> const& bj,
00098                                     vnl_vector<double> const& c,
00099                                     vnl_matrix<double>& Cij)
00100 {
00101   vnl_double_3 p = Pi*vnl_vector_fixed<double,4>(bj[0], bj[1], bj[2], 1.0);
00102 
00103   double inv_f = 1.0/c[0];
00104   double skew_term = K_.skew()*inv_f/K_.y_scale();
00105   vgl_point_2d<double> pp = K_.principal_point();
00106   Cij(1,0) = inv_f * (p[1]/p[2] - pp.y());
00107   Cij(0,0) = inv_f * (p[0]/p[2] - pp.x()) - skew_term*Cij(1,0);
00108 }
00109 
00110 //: construct the \param j-th perspective camera from a pointer to the j-th parameter of \param b and parameters \param c
00111 vgl_homg_point_3d<double>
00112 vpgl_ba_shared_k_lsqr::param_to_point(int j,
00113                                       const double* bj,
00114                                       const vnl_vector<double>& c) const
00115 {
00116   return vgl_homg_point_3d<double>(bj[0], bj[1], bj[2]);
00117 }
00118 
00119 //: construct the \param j-th perspective camera from a pointer to the j-th parameter of \param b and parameters \param c
00120 vnl_vector_fixed<double,4>
00121 vpgl_ba_shared_k_lsqr::param_to_pt_vector(int j,
00122                                           const double* bj,
00123                                           const vnl_vector<double>& c) const
00124 {
00125   return vnl_vector_fixed<double,4>(bj[0], bj[1], bj[2], 1.0);
00126 }
00127 
00128 //: construct the \param i-th perspective camera from a pointer to the i-th parameter of \param a and parameters \param c
00129 vpgl_perspective_camera<double>
00130 vpgl_ba_shared_k_lsqr::param_to_cam(int i,
00131                                     const double* ai,
00132                                     const vnl_vector<double>& c) const
00133 {
00134   K_.set_focal_length(c[0]);
00135   vnl_vector<double> w(ai,3);
00136   vgl_homg_point_3d<double> t(ai[3], ai[4], ai[5]);
00137   return vpgl_perspective_camera<double>(K_,t,vgl_rotation_3d<double>(w));
00138 }
00139 
00140 //: compute a 3x4 camera matrix of camera \param i from a pointer to the i-th parameters of \param a and parameters \param c
00141 vnl_double_3x4
00142 vpgl_ba_shared_k_lsqr::param_to_cam_matrix(int i,
00143                                            const double* ai,
00144                                            const vnl_vector<double>& c) const
00145 {
00146   Km_(0,0) = c[0];
00147   Km_(1,1) = c[0] * K_.y_scale();
00148   const vnl_vector_ref<double> r(3,const_cast<double*>(ai));
00149   vnl_double_3x3 M = Km_*rod_to_matrix(r);
00150   vnl_double_3x4 P;
00151   P.update(M);
00152   const vnl_vector_ref<double> center(3,const_cast<double*>(ai+3));
00153   P.set_column(3,-(M*center));
00154   return P;
00155 }
00156 
00157 
00158 //: Create the parameter vector \p a from a vector of cameras
00159 void
00160 vpgl_ba_shared_k_lsqr::
00161 create_param_vector(const vcl_vector<vpgl_perspective_camera<double> >& cameras,
00162                     vnl_vector<double>& a,
00163                     vnl_vector<double>& c)
00164 {
00165   a.set_size(6*cameras.size());
00166   c.set_size(1);
00167   // compute the average intrinsic parameters
00168   c[0] = 0.0;
00169   for (unsigned int i=0; i<cameras.size(); ++i)
00170   {
00171     const vpgl_perspective_camera<double>& cam = cameras[i];
00172     const vgl_point_3d<double>& C = cam.get_camera_center();
00173     const vgl_rotation_3d<double>& R = cam.get_rotation();
00174     const vpgl_calibration_matrix<double>& K = cam.get_calibration();
00175 
00176     c[0] += K.focal_length() * K.x_scale();
00177 
00178     // compute the Rodrigues vector from the rotation
00179     vnl_vector<double> w = R.as_rodrigues();
00180 
00181     double* ai = a.data_block() + i*6;
00182     ai[0]=w[0];   ai[1]=w[1];   ai[2]=w[2];
00183     ai[3]=C.x();  ai[4]=C.y();  ai[5]=C.z();
00184   }
00185   c[0] /= cameras.size();
00186 }
00187 
00188 
00189 //: Create the parameter vector \p b from a vector of 3D points
00190 vnl_vector<double>
00191 vpgl_ba_shared_k_lsqr::create_param_vector(const vcl_vector<vgl_point_3d<double> >& world_points)
00192 {
00193   vnl_vector<double> b(3*world_points.size(),0.0);
00194   for (unsigned int j=0; j<world_points.size(); ++j){
00195     const vgl_point_3d<double>& point = world_points[j];
00196     double* bj = b.data_block() + j*3;
00197     bj[0]=point.x();  bj[1]=point.y();  bj[2]=point.z();
00198   }
00199   return b;
00200 }
00201