core/vpgl/vpgl_proj_camera.h
Go to the documentation of this file.
00001 // This is core/vpgl/vpgl_proj_camera.h
00002 #ifndef vpgl_proj_camera_h_
00003 #define vpgl_proj_camera_h_
00004 //:
00005 // \file
00006 // \brief A camera model using the standard 3x4 matrix representation.
00007 // \author Thomas Pollard
00008 // \date January 28, 2005
00009 // \author Joseph Mundy, Matt Leotta, Vishal Jain
00010 //
00011 // \verbatim
00012 //  Modifications
00013 //  May 6, 2005  Ricardo Fabbri   Added binary I/O
00014 //  March 14, 2010 J.L. Mundy made some methods virtual to handle affine case
00015 // \endverbatim
00016 //
00017 // This is the most general camera class based around the 3x4 matrix camera model.
00018 // In reality the 3x4 matrix should be rank 3, but this is only checked when an action
00019 // needing an SVD decomposition is called, and only gives a warning.
00020 //
00021 // Once the camera is constructed, the camera matrix can only be accessed through
00022 // the "get_matrix" and "set_matrix" functions. These are also the only ways for
00023 // subclasses to access the matrix, as the automatic SVD handling is done in them.
00024 //
00025 // Some camera operations require an SVD decomposition of the camera matrix.  When
00026 // such a function is first called, an SVD is automatically computed and cached for
00027 // all future calls.  When the camera matrix is changed by "set_matrix", the cached SVD
00028 // is automatically nulled and will only be recomputed when another function that
00029 // needs it is called.  The SVD can be viewed at any time via the "svd" function.
00030 //
00031 // Only elementary methods on the camera are included in the class itself.  In addition,
00032 // there several external functions at the end of the file for important camera operations
00033 // deemed too specialized to be included in the vpgl_proj_camera class itself.  Some
00034 // functions lifted from vgl_p_matrix.h.
00035 //
00036 // NOTE FOR DEVELOPERS:  If you write any member functions that change the
00037 // underlying matrix P_ you should call set_matrix to change it, rather than
00038 // changing P_ itself.  The automatic SVD caching will be screwed up otherwise.
00039 
00040 #include <vnl/vnl_fwd.h>
00041 #include <vgl/vgl_fwd.h>
00042 #include <vnl/vnl_matrix_fixed.h>
00043 #include <vnl/algo/vnl_svd.h>
00044 #include <vgl/vgl_homg_point_3d.h>
00045 #include <vgl/vgl_homg_point_2d.h>
00046 #include <vgl/vgl_line_segment_2d.h>
00047 #include <vgl/vgl_line_segment_3d.h>
00048 #include <vgl/vgl_infinite_line_3d.h>
00049 #include <vgl/vgl_homg_line_2d.h>
00050 #include <vgl/vgl_line_2d.h>
00051 #include <vgl/vgl_homg_line_3d_2_points.h>
00052 #include <vgl/vgl_homg_plane_3d.h>
00053 #include <vgl/algo/vgl_h_matrix_2d.h>
00054 #include <vgl/algo/vgl_h_matrix_3d.h>
00055 #include <vcl_iosfwd.h>
00056 
00057 
00058 
00059 #include "vpgl_camera.h"
00060 
00061 template <class T>
00062 class vpgl_perspective_camera;
00063 
00064 
00065 template <class T>
00066 class vpgl_proj_camera : public vpgl_camera<T>
00067 {
00068  public:
00069   // ----------------- Constructors:----------------------
00070 
00071   //: Default constructor makes an identity camera.
00072   vpgl_proj_camera();
00073 
00074   //: Construct from a vnl_matrix.
00075   vpgl_proj_camera( const vnl_matrix_fixed<T,3,4>& camera_matrix );
00076 
00077   //: Construct from an array.  The array should be in the order row1, row2, row3.
00078   vpgl_proj_camera( const T* camera_matrix );
00079 
00080   //: Copy constructor.
00081   vpgl_proj_camera( const vpgl_proj_camera& cam );
00082 
00083   virtual vcl_string type_name() const { return "vpgl_proj_camera"; }
00084 
00085   //: Clone `this': creation of a new object and initialization
00086   //  See Prototype pattern
00087   virtual vpgl_proj_camera<T>* clone(void) const;
00088 
00089   //: Assignment.
00090   const vpgl_proj_camera<T>& operator=( const vpgl_proj_camera& cam );
00091 
00092   virtual ~vpgl_proj_camera();
00093 
00094   //: Equality test
00095   inline bool operator==(vpgl_proj_camera<T> const &that) const
00096   { return this == &that || this->get_matrix()==that.get_matrix(); }
00097 
00098   // ----------------- Projections and Backprojections:------------------------
00099 
00100   //: Projection from base class
00101   virtual void project(const T x, const T y, const T z, T& u, T& v) const;
00102 
00103   //: Project a point in world coordinates onto the image plane.
00104   virtual vgl_homg_point_2d<T> project( const vgl_homg_point_3d<T>& world_point ) const;
00105 
00106   //: Non-homogeneous version of the above.
00107   vgl_homg_point_2d<T> project( const vgl_point_3d<T>& world_point ) const {
00108     return project( vgl_homg_point_3d<T>( world_point ) ); }
00109 
00110   //: A shortcut to the above function.
00111   vgl_homg_point_2d<T> operator()( const vgl_homg_point_3d<T>& world_point ) const {
00112     return this->project( world_point ); }
00113 
00114   //: Project a line in the world onto a line in the image plane.
00115   vgl_line_segment_2d<T> project( const vgl_line_segment_3d<T>& world_line ) const;
00116 
00117   //: Standard () forward projection operator
00118   vgl_line_segment_2d<T> operator()( const vgl_line_segment_3d<T>& world_line ) const
00119   { return project( world_line ); }
00120 
00121   //: Project an infinite line in the world onto an infinite line in the image plane.
00122   vgl_line_2d<T> project( const vgl_infinite_line_3d<T>& world_line ) const;
00123 
00124   //: Standard () forward projection operator
00125   vgl_line_2d<T> operator()( const vgl_infinite_line_3d<T>& world_line ) const
00126   { return project( world_line ); }
00127 
00128   //: Find the 3d ray that goes through the camera center and the provided image point.
00129   virtual vgl_ray_3d<T> backproject_ray( const vgl_homg_point_2d<T>& image_point ) const;
00130 
00131   //: Find the 3d ray that goes through the camera center and the provided image point.
00132   virtual vgl_homg_line_3d_2_points<T> backproject( const vgl_homg_point_2d<T>& image_point ) const;
00133 
00134   //: Find the 3d plane that contains the camera center and the provided line in the image plane.
00135   vgl_homg_plane_3d<T> backproject( const vgl_homg_line_2d<T>& image_line ) const;
00136 
00137   // --------------------- Misc Camera Functions:-------------------
00138 
00139   //: Find the 3d coordinates of the center of the camera.
00140   virtual vgl_homg_point_3d<T> camera_center() const;
00141 
00142   //: Find the world plane parallel to the image plane intersecting the camera center.
00143   virtual  vgl_homg_plane_3d<T> principal_plane() const{ return vgl_homg_plane_3d<T>( P_[2] ); }
00144 
00145   //: Find the image coordinates of the vanishing points of the world coordinate axes.
00146   vgl_homg_point_2d<T> x_vanishing_point() const{ return vgl_homg_point_2d<T>( P_(0,0), P_(1,0), P_(2,0) ); }
00147   vgl_homg_point_2d<T> y_vanishing_point() const{ return vgl_homg_point_2d<T>( P_(0,1), P_(1,1), P_(2,1) ); }
00148   vgl_homg_point_2d<T> z_vanishing_point() const{ return vgl_homg_point_2d<T>( P_(0,2), P_(1,2), P_(2,2) ); }
00149 
00150   // --------------------- Getters and Setters:---------------------
00151 
00152   //: Return a copy of the camera matrix.
00153   const vnl_matrix_fixed<T,3,4>& get_matrix() const{ return P_; }
00154 
00155   //: Get a copy of the svd of the get_matrix.
00156   // The svd is cached when first computed and automatically recomputed when the matrix is changed.
00157   vnl_svd<T>* svd() const;
00158 
00159   //: Setters mirror the constructors and return true if the setting was successful.
00160   // In subclasses these should be redefined so that they won't allow setting of
00161   // matrices with improper form.
00162   virtual bool set_matrix( const vnl_matrix_fixed<T,3,4>& new_camera_matrix );
00163   virtual bool set_matrix( const T* new_camera_matrix );
00164 
00165   // --------------------- I/O :---------------------
00166 
00167   //: Save in ascii format
00168   virtual void save(vcl_string cam_path);
00169 
00170  private:
00171   //: The internal representation of the get_matrix.
00172   // It is private so subclasses will need to access it through "get_matrix" and "set_matrix".
00173   vnl_matrix_fixed<T,3,4> P_;
00174 
00175   mutable vnl_svd<T>* cached_svd_;
00176 };
00177 
00178 
00179 // External Functions:-------------------------------------------------------------
00180 
00181 //: Return the 3D H-matrix s.t. P * H = [I 0].
00182 template <class T>
00183 vgl_h_matrix_3d<T> get_canonical_h( vpgl_proj_camera<T>& camera );
00184 
00185 //: Scale the camera matrix so determinant of first 3x3 is 1.
00186 template <class T>
00187 void fix_cheirality( vpgl_proj_camera<T>& camera );
00188 
00189 //: Set the camera matrix to [ I | 0 ].
00190 template <class T>
00191 void make_canonical( vpgl_proj_camera<T>& camera );
00192 
00193 //: Pre-multiply this projection matrix with a 2-d projective transform.
00194 template <class T>
00195 vpgl_proj_camera<T> premultiply( const vpgl_proj_camera<T>& in_camera,
00196                                  const vnl_matrix_fixed<T,3,3>& transform );
00197 
00198 //: Pre-multiply this projection matrix with a 2-d projective transform.
00199 template <class T>
00200 vpgl_proj_camera<T> premultiply( const vpgl_proj_camera<T>& in_camera,
00201                                  const vgl_h_matrix_2d<T>& transform )
00202 {
00203   return premultiply(in_camera, transform.get_matrix());
00204 }
00205 
00206 
00207 //: Post-multiply this projection matrix with a 3-d projective transform.
00208 template <class T>
00209 vpgl_proj_camera<T> postmultiply( const vpgl_proj_camera<T>& in_camera,
00210                                   const vnl_matrix_fixed<T,4,4>& transform );
00211 
00212 //: Post-multiply this projection matrix with a 3-d projective transform.
00213 template <class T>
00214 vpgl_proj_camera<T> postmultiply( const vpgl_proj_camera<T>& in_camera,
00215                                   const vgl_h_matrix_3d<T>& transform )
00216 {
00217   return postmultiply(in_camera, transform.get_matrix());
00218 }
00219 //: Linearly intersect two camera rays to form a 3-d point
00220 template <class T>
00221 vgl_point_3d<T> triangulate_3d_point(const vpgl_proj_camera<T>& c1,
00222                                      const vgl_point_2d<T>& x1,
00223                                      const vpgl_proj_camera<T>& c2,
00224                                      const vgl_point_2d<T>& x2);
00225 
00226 //: Compute the image projection Jacobians at each point
00227 //  The returned matrices map a differential change in 3D
00228 //  to a differential change in the 2D image at each specified 3D point
00229 template <class T>
00230 vcl_vector<vnl_matrix_fixed<T,2,3> >
00231 image_jacobians(const vpgl_proj_camera<T>& camera,
00232                 const vcl_vector<vgl_point_3d<T> >& pts);
00233 
00234 
00235 // I/O ---
00236 
00237 //: Write vpgl_perspective_camera to stream
00238 template <class Type>
00239 vcl_ostream&  operator<<(vcl_ostream& s, vpgl_proj_camera<Type> const& p);
00240 
00241 //: Read vpgl_perspective_camera  from stream
00242 template <class Type>
00243 vcl_istream&  operator>>(vcl_istream& s, vpgl_proj_camera<Type>& p);
00244 
00245 #endif // vpgl_proj_camera_h_