core/vpgl/vpgl_perspective_camera.h
Go to the documentation of this file.
00001 // This is core/vpgl/vpgl_perspective_camera.h
00002 #ifndef vpgl_perspective_camera_h_
00003 #define vpgl_perspective_camera_h_
00004 //:
00005 // \file
00006 // \brief A class for the perspective camera model.
00007 // \author Thomas Pollard
00008 // \date Jan 28, 2005
00009 // \author Joseph Mundy, Matt Leotta, Vishal Jain
00010 //
00011 // \verbatim
00012 //  Modifications
00013 //   May 08, 2005  Ricardo Fabbri   Added binary I/O support
00014 //   May 08, 2005  Ricardo Fabbri   Added == operator
00015 //   Feb  8, 2007  Thomas Pollard   Added finite backproject method.
00016 //   Mar 16, 2007  Matt Leotta      Replaced vgl_h_matrix_3d with vgl_rotation_3d for rotation
00017 //   May 31, 2011  Peter Vanroose   Added homg-coord. "backproject()" method
00018 // \endverbatim
00019 
00020 #include <vnl/vnl_fwd.h>
00021 #include <vgl/vgl_fwd.h>
00022 #include <vgl/vgl_point_3d.h>
00023 #include <vgl/vgl_homg_point_3d.h>
00024 #include <vgl/algo/vgl_rotation_3d.h>
00025 #include <vgl/vgl_ray_3d.h>
00026 #include <vcl_iosfwd.h>
00027 
00028 #include "vpgl_proj_camera.h"
00029 #include "vpgl_calibration_matrix.h"
00030 
00031 
00032 //: This class implements the perspective camera class as described in Hartley & Zisserman as a finite camera.
00033 //  This is the camera model based on three objects:
00034 //  the camera calibration matrix (see "vpgl_calibration_matrix.h"), the camera center,
00035 //  and the rotation of the camera from its canonical orientation staring down the
00036 //  positive z axis.
00037 //
00038 //  All rotation matrices entered will be checked that they are indeed rotations, i.e.
00039 //  that R.transpose()*R = Identity and in the form:
00040 //  \verbatim
00041 //   [ R 0 ]
00042 //   [ 0 1 ]
00043 //  \endverbatim
00044 //
00045 // \verbatim
00046 //  Modifications
00047 //   Feb 12, 2007  Thomas Pollard   Added finite backprojection method.
00048 // \endverbatim
00049 //
00050 //  For adding to this class:
00051 //
00052 //  Be sure to call recompute_matrix in your member functions any time you change any of the
00053 //  camera parameters.
00054 template <class T>
00055 class vpgl_perspective_camera : public vpgl_proj_camera<T>
00056 {
00057  public:
00058   //: Default constructor
00059   // Makes a camera at the origin with no rotation and default calibration matrix.
00060   vpgl_perspective_camera();
00061 
00062   //: Main constructor takes all of the camera parameters.
00063   vpgl_perspective_camera( const vpgl_calibration_matrix<T>& K,
00064                            const vgl_point_3d<T>& camera_center,
00065                            const vgl_rotation_3d<T>& R );
00066 
00067   //: Main constructor based on K[R|t]
00068   vpgl_perspective_camera( const vpgl_calibration_matrix<T>& K,
00069                            const vgl_rotation_3d<T>& R,
00070                            const vgl_vector_3d<T>& t);
00071 
00072 
00073   //: Copy constructor
00074   vpgl_perspective_camera( const vpgl_perspective_camera& cam );
00075 
00076   //: Destructor
00077   virtual ~vpgl_perspective_camera() {}
00078 
00079   virtual vcl_string type_name() const { return "vpgl_perspective_camera"; }
00080 
00081   //: Clone `this': creation of a new object and initialization
00082   //  See Prototype pattern
00083   virtual vpgl_proj_camera<T>* clone(void) const;
00084 
00085   //: Finite backprojection.
00086   // This is a virtual function from the parent class vpgl_proj_camera<T>
00087   vgl_homg_line_3d_2_points<T> backproject(const vgl_homg_point_2d<T>& image_point ) const;
00088   //: Finite backprojection.
00089   vgl_line_3d_2_points<T> backproject( const vgl_point_2d<T>& image_point ) const;
00090   //: Finite backprojection.
00091   vgl_line_3d_2_points<T> backproject(T u, T v) const
00092     {return backproject(vgl_point_2d<T>(u, v));}
00093 
00094   //: Finite ray backprojection.
00095   vgl_ray_3d<T> backproject_ray( const vgl_point_2d<T>& image_point ) const;
00096 
00097   //: Finite ray backprojection at u v.
00098   vgl_ray_3d<T> backproject_ray(T u, T v) const
00099     {return backproject_ray(vgl_point_2d<T>(u, v));}
00100 
00101   //: Compute the principal axis.
00102   // i.e. the vector perpendicular to the image plane pointing towards the front of the camera.
00103   vgl_vector_3d<T> principal_axis() const;
00104 
00105   //: Determine whether the given point lies in front of the principal plane.
00106   bool is_behind_camera( const vgl_homg_point_3d<T>& world_point ) const;
00107 
00108   //: Setters and getters.
00109   void set_calibration( const vpgl_calibration_matrix<T>& K );
00110   void set_camera_center( const vgl_point_3d<T>& camera_center );
00111   void set_translation(const vgl_vector_3d<T>& t);
00112   void set_rotation( const vgl_rotation_3d<T>& R );
00113   const vpgl_calibration_matrix<T>& get_calibration() const{ return K_; }
00114   const vgl_point_3d<T>& get_camera_center() const { return camera_center_; }
00115   vgl_vector_3d<T> get_translation() const;
00116   const vgl_rotation_3d<T>& get_rotation() const{ return R_; }
00117 
00118   //: Rotate the camera about its center such that it looks at the given point
00119   //  The camera should also be rotated about its principal axis such that
00120   //  the vertical image direction is closest to \p up in the world
00121   void look_at(const vgl_homg_point_3d<T>& point,
00122                const vgl_vector_3d<T>& up = vgl_vector_3d<T>(0,0,1));
00123 
00124   // Redefined virtual functions -------------------------------------------
00125 
00126   //: Return the known camera center instead of computing it in the base class
00127   virtual vgl_homg_point_3d<T> camera_center() const
00128   { return vgl_homg_point_3d<T>(camera_center_); }
00129 
00130   // static public functions -----------------------------------------------
00131 
00132   //: Post-multiply this perspective camera with a 3-d Euclidean transformation
00133   // \todo decide whether this needs to be either a static method or a stand-alone function.
00134   // (Now both are present.)
00135   static  vpgl_perspective_camera<T>
00136     postmultiply( const vpgl_perspective_camera<T>& in_cam,
00137                   const vgl_h_matrix_3d<T>& euclid_trans);
00138   //: Apply a 3-d Euclidean transformation (transform external cam parameters)
00139   static vpgl_perspective_camera<T>
00140     postmultiply(const vpgl_perspective_camera<T>& camera,
00141                  const vgl_rotation_3d<T>& rot, const vgl_vector_3d<T>& trans);
00142 
00143   //: Equality test
00144   inline bool operator==(vpgl_perspective_camera<T> const &that) const
00145   { return this == &that ||
00146     (K_ == that.K_ && this->get_matrix()== that.get_matrix() &&
00147      camera_center_ == that.camera_center_ && this->R_.as_matrix() == that.R_.as_matrix()); }
00148 
00149   // -------------------- I/O :---------------------
00150 
00151   //: Save in ascii format
00152   virtual void save(vcl_string cam_path);
00153 
00154 
00155   //: Return `this' if `this' is a vpgl_perspective_camera, 0 otherwise
00156   // This is used by e.g. the storage class
00157   // \todo code for affine camera and other children
00158   virtual vpgl_perspective_camera<T> *cast_to_perspective_camera() {return this;}
00159   virtual const vpgl_perspective_camera<T> *cast_to_perspective_camera() const {return this;}
00160 
00161  protected:
00162   //: Recalculate the 3x4 camera matrix from the parameters.
00163   void recompute_matrix();
00164 
00165   vpgl_calibration_matrix<T> K_;
00166   vgl_point_3d<T> camera_center_;
00167   vgl_rotation_3d<T> R_;
00168 };
00169 
00170 // External Functions:-------------------------------------------------------------
00171 
00172 //: Write vpgl_perspective_camera to stream
00173 template <class Type>
00174 vcl_ostream&  operator<<(vcl_ostream& s, vpgl_perspective_camera<Type> const& p);
00175 
00176 //: Read vpgl_perspective_camera  from stream
00177 template <class Type>
00178 vcl_istream&  operator>>(vcl_istream& s, vpgl_perspective_camera<Type>& p);
00179 
00180 //: Write vpgl_perspective_camera to a vrml file, does not write a vrml header, only the camera, the camera center sphere has radius rad
00181 template <class Type>
00182 void vrml_write(vcl_ostream& s, vpgl_perspective_camera<Type> const& p, double rad);
00183 
00184 //: Decompose camera into parameter blocks.
00185 // Attempts to decompose a 3x4 camera matrix into the parameter blocks that describe
00186 // a perspective camera, but will only work if the supplied matrix has a left 3x3
00187 // submatrix with rank 3.
00188 template <class T>
00189 bool vpgl_perspective_decomposition( const vnl_matrix_fixed<T,3,4>& camera_matrix,
00190                                      vpgl_perspective_camera<T>& p_camera );
00191 
00192 //: Changes the coordinate system of camera p1 such that the same change would transform p0 to K[I|0].
00193 template <class T>
00194 vpgl_perspective_camera<T> vpgl_align_down( const vpgl_perspective_camera<T>& p0,
00195                                             const vpgl_perspective_camera<T>& p1 );
00196 
00197 //: Changes the coordinate system of camera p1 such that the same change would transform K[I|0] to p0.
00198 template <class T>
00199 vpgl_perspective_camera<T> vpgl_align_up( const vpgl_perspective_camera<T>& p0,
00200                                           const vpgl_perspective_camera<T>& p1 );
00201 
00202 template <class T>
00203 double vpgl_persp_cam_distance( const vpgl_perspective_camera<T>& cam1, const vpgl_perspective_camera<T>& cam2);
00204 
00205 template <class T>
00206 vpgl_perspective_camera<T>
00207 postmultiply( const vpgl_perspective_camera<T>& in_cam,
00208               const vgl_h_matrix_3d<T>& euclid_trans)
00209 {
00210   return vpgl_perspective_camera<T>::postmultiply(in_cam, euclid_trans);
00211 }
00212 
00213 //: Return a list of camera's, loaded from the (name sorted) files from the given directory
00214 template <class T>
00215 vcl_vector<vpgl_perspective_camera<T> > cameras_from_directory(vcl_string dir, T);
00216 
00217 
00218 
00219 #endif // vpgl_perspective_camera_h_