contrib/gel/mrc/vpgl/algo/vpgl_bundle_adjust.h
Go to the documentation of this file.
00001 // This is gel/mrc/vpgl/algo/vpgl_bundle_adjust.h
00002 #ifndef vpgl_bundle_adjust_h_
00003 #define vpgl_bundle_adjust_h_
00004 //:
00005 // \file
00006 // \brief Bundle adjustment sparse least squares functions
00007 // \author Matt Leotta
00008 // \date April 18, 2005
00009 
00010 #include <vnl/vnl_vector.h>
00011 #include <vnl/vnl_sparse_lst_sqr_function.h>
00012 #include <vgl/vgl_point_2d.h>
00013 #include <vgl/vgl_point_3d.h>
00014 #include <vgl/vgl_homg_point_3d.h>
00015 #include <vgl/algo/vgl_rotation_3d.h>
00016 #include <vpgl/vpgl_perspective_camera.h>
00017 #include <vcl_vector.h>
00018 
00019 
00020 //: Computes the residuals for bundle adjustment given that the cameras share a fixed internal calibration
00021 class vpgl_bundle_adj_lsqr : public vnl_sparse_lst_sqr_function
00022 {
00023  public:
00024   //: Constructor
00025   // \note image points are not homogeneous because they require finite points to measure projection error
00026   vpgl_bundle_adj_lsqr(const vcl_vector<vpgl_calibration_matrix<double> >& K,
00027                        const vcl_vector<vgl_point_2d<double> >& image_points,
00028                        const vcl_vector<vcl_vector<bool> >& mask,
00029                        bool use_confidence_weights = true);
00030 
00031   //: Constructor
00032   //  Each image point is assigned an inverse covariance (error projector) matrix
00033   // \note image points are not homogeneous because they require finite points to measure projection error
00034   vpgl_bundle_adj_lsqr(const vcl_vector<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                        bool use_confidence_weights = true);
00039 
00040   // Destructor
00041   virtual ~vpgl_bundle_adj_lsqr() {}
00042 
00043   //: Compute all the reprojection errors
00044   //  Given the parameter vectors a and b, compute the vector of residuals e.
00045   //  e has been sized appropriately before the call.
00046   //  The parameters in a for each camera are {wx, wy, wz, tx, ty, tz}
00047   //  where w is the Rodrigues vector of the rotation and t is the translation.
00048   //  The parameters in b for each 3D point are {px, py, pz}
00049   //  the non-homogeneous position.
00050   virtual void f(vnl_vector<double> const& a, vnl_vector<double> const& b,
00051                  vnl_vector<double>& e);
00052 
00053   //: Compute the residuals from the ith component of a and the jth component of b.
00054   //  This is not normally used because f() has a self-contained efficient implementation
00055   //  It is used for finite-differencing if the gradient is marked as unavailable
00056   virtual void fij(int i, int j, vnl_vector<double> const& ai,
00057                    vnl_vector<double> const& bj, vnl_vector<double>& fij);
00058 
00059   //: Compute the sparse Jacobian in block form.
00060   virtual void jac_blocks(vnl_vector<double> const& a, vnl_vector<double> const& b,
00061                           vcl_vector<vnl_matrix<double> >& A,
00062                           vcl_vector<vnl_matrix<double> >& B);
00063 
00064   //: compute the Jacobian Aij
00065   void jac_Aij(vnl_double_3x4 const& Pi, vnl_double_3x3 const& K,
00066                vnl_vector<double> const& ai, vnl_vector<double> const& bj,
00067                vnl_matrix<double>& Aij);
00068 
00069   //: compute the Jacobian Bij
00070   void jac_Bij(vnl_double_3x4 const& Pi, vnl_vector<double> const& bj,
00071                vnl_matrix<double>& Bij);
00072 
00073 
00074   //: construct the jth 3D point from parameter vector b
00075   vgl_homg_point_3d<double> param_to_point(int j, const vnl_vector<double>& b) const
00076   {
00077     const double* d = b.data_block() + index_b(j);
00078     return vgl_homg_point_3d<double>(d[0], d[1], d[2]);
00079   }
00080 
00081   //: construct the ith perspective camera from parameter vector a
00082   vpgl_perspective_camera<double> param_to_cam(int i, const vnl_vector<double>& a) const
00083   {
00084     return param_to_cam(i, a.data_block()+index_a(i));
00085   }
00086   vpgl_perspective_camera<double> param_to_cam(int i, const double* d) const
00087   {
00088     vnl_vector<double> w(d,3);
00089     vgl_homg_point_3d<double> t(d[3], d[4], d[5]);
00090     return vpgl_perspective_camera<double>(K_[i],t,vgl_rotation_3d<double>(w));
00091   }
00092 
00093   //: construct the ith perspective camera matrix from parameter vector \param a
00094   //  Bypass vpgl for efficiency
00095   vnl_double_3x4 param_to_cam_matrix(int i, const vnl_vector<double>& a) const
00096   {
00097     return param_to_cam_matrix(i, a.data_block()+index_a(i));
00098   }
00099   vnl_double_3x4 param_to_cam_matrix(int i, const double* d) const
00100   {
00101     vnl_double_3x3 M = Km_[i]*rod_to_matrix(d);
00102     vnl_double_3x4 P;
00103     P.update(M);
00104     const vnl_vector_ref<double> c(3,const_cast<double*>(d+3));
00105     P.set_column(3,-(M*c));
00106     return P;
00107   }
00108 
00109   //: Fast conversion of rotation from Rodrigues vector to matrix
00110   vnl_matrix_fixed<double,3,3> rod_to_matrix(const double* r) const;
00111 
00112   //: Create the parameter vector \p a from a vector of cameras
00113   static vnl_vector<double>
00114     create_param_vector(const vcl_vector<vpgl_perspective_camera<double> >& cameras);
00115 
00116   //: Create the parameter vector \p b from a vector of 3D points
00117   static vnl_vector<double>
00118     create_param_vector(const vcl_vector<vgl_point_3d<double> >& world_points);
00119 
00120 
00121   void reset() { iteration_count_ = 0; for (unsigned int i=0; i<weights_.size(); ++i) weights_[i] = 1.0; }
00122 
00123   //: return the current weights
00124   vcl_vector<double> weights() const { return weights_; }
00125 
00126  protected:
00127   //: The fixed internal camera calibration
00128   vcl_vector<vpgl_calibration_matrix<double> > K_;
00129   //: The fixed internal camera calibration in matrix form
00130   vcl_vector<vnl_double_3x3> Km_;
00131   //: The corresponding points in the image
00132   vcl_vector<vgl_point_2d<double> > image_points_;
00133   //: The Cholesky factored inverse covariances for each image point
00134   vcl_vector<vnl_matrix<double> > factored_inv_covars_;
00135   //: Flag to enable covariance weighted errors
00136   bool use_covars_;
00137   //: Flag to enable confidence weighting
00138   bool use_weights_;
00139   //: The corresponding points in the image
00140   vcl_vector<double> weights_;
00141   int iteration_count_;
00142 };
00143 
00144 
00145 //: Static functions for bundle adjustment
00146 class vpgl_bundle_adjust
00147 {
00148  public:
00149   //: Constructor
00150   vpgl_bundle_adjust();
00151   //: Destructor
00152   ~vpgl_bundle_adjust();
00153 
00154   void set_use_weights(bool use_weights) { use_weights_ = use_weights; }
00155   void set_use_gradient(bool use_gradient) { use_gradient_ = use_gradient; }
00156 
00157   //: Return the ending error
00158   double end_error() const { return end_error_; }
00159   //: Return the starting error
00160   double start_error() const { return start_error_; }
00161   //: Return the number of iterations
00162   int num_iterations() const { return num_iterations_; }
00163 
00164   //: Return the raw camera parameters
00165   const vnl_vector<double>& cam_params() const { return a_; }
00166   //: Return the raw world point parameters
00167   const vnl_vector<double>& point_params() const { return b_; }
00168 
00169   //: Bundle Adjust
00170   bool optimize(vcl_vector<vpgl_perspective_camera<double> >& cameras,
00171                 vcl_vector<vgl_point_3d<double> >& world_points,
00172                 const vcl_vector<vgl_point_2d<double> >& image_points,
00173                 const vcl_vector<vcl_vector<bool> >& mask);
00174 
00175   //: Write cameras and points to a file in VRML 2.0 for debugging
00176   static void write_vrml(const vcl_string& filename,
00177                          vcl_vector<vpgl_perspective_camera<double> >& cameras,
00178                          vcl_vector<vgl_point_3d<double> >& world_points);
00179 
00180  private:
00181   //: The bundle adjustment error function
00182   vpgl_bundle_adj_lsqr* ba_func_;
00183   //: The last camera parameters
00184   vnl_vector<double> a_;
00185   //: The last point parameters
00186   vnl_vector<double> b_;
00187 
00188   bool use_weights_;
00189   bool use_gradient_;
00190 
00191   double start_error_;
00192   double end_error_;
00193   int num_iterations_;
00194 };
00195 
00196 #endif // vpgl_bundle_adjust_h_