contrib/gel/mrc/vpgl/vpgl_proj_camera.h
Go to the documentation of this file.
00001 // This is gel/mrc/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 // \endverbatim
00015 //
00016 // This is the most general camera class based around the 3x4 matrix camera model.
00017 // In reality the 3x4 matrix should be rank 3, but this is only checked when an action
00018 // needing an SVD decomposition is called, and only gives a warning.
00019 //
00020 // Once the camera is constructed, the camera matrix can only be accessed through
00021 // the "get_matrix" and "set_matrix" functions. These are also the only ways for
00022 // subclasses to access the matrix, as the automatic SVD handling is done in them.
00023 //
00024 // Some camera operations require an SVD decomposition of the camera matrix.  When
00025 // such a function is first called, an SVD is automatically computed and cached for
00026 // all future calls.  When the camera matrix is changed by "set_matrix", the cached SVD
00027 // is automatically nulled and will only be recomputed when another function that
00028 // needs it is called.  The SVD can be viewed at any time via the "svd" function.
00029 //
00030 // Only elementary methods on the camera are included in the class itself.  In addition,
00031 // there several external functions at the end of the file for important camera operations
00032 // deemed too specialized to be included in the vpgl_proj_camera class itself.  Some
00033 // functions lifted from vgl_p_matrix.h.
00034 //
00035 // NOTE FOR DEVELOPERS:  If you write any member functions that change the
00036 // underlying matrix P_ you should call set_matrix to change it, rather than
00037 // changing P_ itself.  The automatic SVD caching will be screwed up otherwise.
00038 
00039 #include <vnl/vnl_fwd.h>
00040 #include <vgl/vgl_fwd.h>
00041 #include <vnl/vnl_matrix_fixed.h>
00042 #include <vnl/algo/vnl_svd.h>
00043 #include <vgl/vgl_homg_point_3d.h>
00044 #include <vgl/vgl_homg_point_2d.h>
00045 #include <vgl/vgl_line_segment_2d.h>
00046 #include <vgl/vgl_line_segment_3d.h>
00047 #include <vgl/vgl_infinite_line_3d.h>
00048 #include <vgl/vgl_homg_line_2d.h>
00049 #include <vgl/vgl_line_2d.h>
00050 #include <vgl/vgl_homg_line_3d_2_points.h>
00051 #include <vgl/vgl_homg_plane_3d.h>
00052 #include <vgl/algo/vgl_h_matrix_2d.h>
00053 #include <vgl/algo/vgl_h_matrix_3d.h>
00054 #include <vcl_iosfwd.h>
00055 #include <vsl/vsl_binary_io.h>
00056 
00057 
00058 #include "vpgl_camera.h"
00059 
00060 template <class T>
00061 class vpgl_perspective_camera;
00062 
00063 
00064 template <class T>
00065 class vpgl_proj_camera : public vpgl_camera<T>
00066 {
00067  public:
00068   //: Constructors:----------------------
00069 
00070   //: Default constructor makes an identity camera.
00071   vpgl_proj_camera();
00072 
00073   //: Construct from a vnl_matrix.
00074   vpgl_proj_camera( const vnl_matrix_fixed<T,3,4>& camera_matrix );
00075 
00076   //: Construct from an array.  The array should be in the order row1, row2, row3.
00077   vpgl_proj_camera( const T* camera_matrix );
00078 
00079   //: Copy constructor.
00080   vpgl_proj_camera( const vpgl_proj_camera& cam );
00081 
00082   virtual vcl_string type_name() const { return "vpgl_proj_camera"; }
00083 
00084   //: Clone `this': creation of a new object and initialization
00085   //  See Prototype pattern
00086   virtual vpgl_proj_camera<T>* clone(void) const;
00087 
00088   //: Assignment.
00089   const vpgl_proj_camera<T>& operator=( const vpgl_proj_camera& cam );
00090 
00091   virtual ~vpgl_proj_camera();
00092 
00093   // Projections and Backprojections:------------------------
00094 
00095   //: Projection from base class
00096   virtual void project(const T x, const T y, const T z, T& u, T& v) const;
00097 
00098   //: Project a point in world coordinates onto the image plane.
00099   virtual vgl_homg_point_2d<T> project( const vgl_homg_point_3d<T>& world_point ) const;
00100 
00101   //: Non-homogeneous version of the above.
00102   vgl_homg_point_2d<T> project( const vgl_point_3d<T>& world_point ) const {
00103     return project( vgl_homg_point_3d<T>( world_point ) ); }
00104 
00105   //: A shortcut to the above function.
00106   vgl_homg_point_2d<T> operator()( const vgl_homg_point_3d<T>& world_point ) const {
00107     return this->project( world_point ); }
00108 
00109   //: Project a line in the world onto a line in the image plane.
00110   vgl_line_segment_2d<T> project( const vgl_line_segment_3d<T>& world_line ) const;
00111 
00112   //: Standard () forward projection operator
00113   vgl_line_segment_2d<T> operator()( const vgl_line_segment_3d<T>& world_line ) const
00114   { return project( world_line ); }
00115 
00116   //: Project an infinite line in the world onto an infinite line in the image plane.
00117   vgl_line_2d<T> project( const vgl_infinite_line_3d<T>& world_line ) const;
00118 
00119   //: Standard () forward projection operator
00120   vgl_line_2d<T> operator()( const vgl_infinite_line_3d<T>& world_line ) const
00121   { return project( world_line ); }
00122 
00123   //: Find the 3d ray that goes through the camera center and the provided image point.
00124   vgl_homg_line_3d_2_points<T> backproject( const vgl_homg_point_2d<T>& image_point ) const;
00125 
00126 
00127   //: Find the 3d plane that contains the camera center and the provided line in the image plane.
00128   vgl_homg_plane_3d<T> backproject( const vgl_homg_line_2d<T>& image_line ) const;
00129 
00130 
00131   // Misc Camera Functions:-------------------
00132 
00133   //: Find the 3d coordinates of the center of the camera.
00134   virtual vgl_homg_point_3d<T> camera_center() const;
00135 
00136   //: Find the world plane parallel to the image plane intersecting the camera center.
00137   vgl_homg_plane_3d<T> principal_plane() const{
00138     return vgl_homg_plane_3d<T>( P_[2] ); }
00139 
00140   //: Find the image coordinates of the vanishing points of the world coordinate axes.
00141   vgl_homg_point_2d<T> x_vanishing_point() const{
00142     return vgl_homg_point_2d<T>( P_(0,0), P_(1,0), P_(2,0) ); }
00143   vgl_homg_point_2d<T> y_vanishing_point() const{
00144     return vgl_homg_point_2d<T>( P_(0,1), P_(1,1), P_(2,1) ); }
00145   vgl_homg_point_2d<T> z_vanishing_point() const{
00146     return vgl_homg_point_2d<T>( P_(0,2), P_(1,2), P_(2,2) ); }
00147 
00148 
00149   // Getters and Setters:---------------------
00150 
00151   //: Return a copy of the camera matrix.
00152   const vnl_matrix_fixed<T,3,4>& get_matrix() const{ return P_; }
00153 
00154   //: Get a copy of the svd of the get_matrix.
00155   // The svd is cached when first computed and automatically recomputed when the matrix is changed.
00156   vnl_svd<T>* svd() const;
00157 
00158   //: Setters mirror the constructors and return true if the setting was successful.
00159   // In subclasses these should be redefined so that they won't allow setting of
00160   // matrices with improper form.
00161   virtual bool set_matrix( const vnl_matrix_fixed<T,3,4>& new_camera_matrix );
00162   virtual bool set_matrix( const T* new_camera_matrix );
00163 
00164 
00165   // I/O :---------------------
00166 
00167   //: Binary save self to stream.
00168   virtual void b_write(vsl_b_ostream &os) const;
00169 
00170   //: Binary load self from stream.
00171   virtual void b_read(vsl_b_istream &is);
00172 
00173   //: IO version number
00174   short version() const {return 1;}
00175 
00176   //: Print an ascii summary to the stream
00177   void print_summary(vcl_ostream &os) const { os << *this; }
00178 
00179   //: Return a platform independent string identifying the class
00180   virtual vcl_string is_a() const { return vcl_string("vpgl_proj_camera"); }
00181 
00182   //: Return true if the argument matches the string identifying the class or any parent class
00183   virtual bool is_class(vcl_string const& cls) const
00184   { return cls==is_a() || cls==vcl_string("vpgl_camera"); }
00185 
00186   //: Return `this' if `this' is a vpgl_proj_camera, 0 otherwise
00187   // This is used by e.g. polymorphic binary i/o
00188   virtual vpgl_proj_camera<T> *cast_to_proj_camera() {return this;}
00189   virtual const vpgl_proj_camera<T> *cast_to_proj_camera() const {return this;}
00190 
00191   //: Return `this' if `this' is a vpgl_perspective_camera, 0 otherwise
00192   // This is used by e.g. the storage class
00193   // \todo code for affine camera and other children
00194   virtual vpgl_perspective_camera<T> *cast_to_perspective_camera() {return 0;}
00195   virtual const vpgl_perspective_camera<T> *cast_to_perspective_camera() const {return 0;}
00196 
00197  private:
00198   //: The internal representation of the get_matrix.
00199   // It is private so subclasses will need to access it through "get_matrix" and "set_matrix".
00200   vnl_matrix_fixed<T,3,4> P_;
00201 
00202   mutable vnl_svd<T>* cached_svd_;
00203 };
00204 
00205 
00206 // External Functions:-------------------------------------------------------------
00207 
00208 //: Return the 3D H-matrix s.t. P * H = [I 0].
00209 template <class T>
00210 vgl_h_matrix_3d<T> get_canonical_h( vpgl_proj_camera<T>& camera );
00211 
00212 //: Scale the camera matrix so determinant of first 3x3 is 1.
00213 template <class T>
00214 void fix_cheirality( vpgl_proj_camera<T>& camera );
00215 
00216 //: Set the camera matrix to [ I | 0 ].
00217 template <class T>
00218 void make_cannonical( vpgl_proj_camera<T>& camera );
00219 
00220 //: Pre-multiply this projection matrix with a 2-d projective transform.
00221 template <class T>
00222 vpgl_proj_camera<T> premultiply( const vpgl_proj_camera<T>& in_camera,
00223                                  const vnl_matrix_fixed<T,3,3>& transform );
00224 
00225 //: Pre-multiply this projection matrix with a 2-d projective transform.
00226 template <class T>
00227 vpgl_proj_camera<T> premultiply( const vpgl_proj_camera<T>& in_camera,
00228                                  const vgl_h_matrix_2d<T>& transform )
00229 {
00230   return premultiply(in_camera, transform.get_matrix());
00231 }
00232 
00233 
00234 //: Post-multiply this projection matrix with a 3-d projective transform.
00235 template <class T>
00236 vpgl_proj_camera<T> postmultiply( const vpgl_proj_camera<T>& in_camera,
00237                                   const vnl_matrix_fixed<T,4,4>& transform );
00238 
00239 //: Post-multiply this projection matrix with a 3-d projective transform.
00240 template <class T>
00241 vpgl_proj_camera<T> postmultiply( const vpgl_proj_camera<T>& in_camera,
00242                                   const vgl_h_matrix_3d<T>& transform )
00243 {
00244   return postmultiply(in_camera, transform.get_matrix());
00245 }
00246 //: Linearly intersect two camera rays to form a 3-d point
00247 template <class T>
00248 vgl_point_3d<T> triangulate_3d_point(const vpgl_proj_camera<T>& c1,
00249                                      const vgl_point_2d<T>& x1,
00250                                      const vpgl_proj_camera<T>& c2,
00251                                      const vgl_point_2d<T>& x2);
00252 
00253 //: Compute the image projection Jacobians at each point
00254 //  The returned matrices map a differential change in 3D
00255 //  to a differential change in the 2D image at each specified 3D point
00256 template <class T>
00257 vcl_vector<vnl_matrix_fixed<T,2,3> >
00258 image_jacobians(const vpgl_proj_camera<T>& camera,
00259                 const vcl_vector<vgl_point_3d<T> >& pts);
00260 
00261 
00262 // I/O ---
00263 
00264 //: Write vpgl_perspective_camera to stream
00265 
00266 template <class Type>
00267 vcl_ostream&  operator<<(vcl_ostream& s, vpgl_proj_camera<Type> const& p);
00268 
00269 //: Read vpgl_perspective_camera  from stream
00270 template <class Type>
00271 vcl_istream&  operator>>(vcl_istream& s, vpgl_proj_camera<Type>& p);
00272 
00273 
00274 //: Allows derived class to be loaded by base-class pointer
00275 //  A loader object exists which is invoked by calls
00276 //  of the form "vsl_b_read(os,base_ptr)".  This loads derived class
00277 //  objects from the disk, places them on the heap and
00278 //  returns a base class pointer.
00279 //  In order to work the loader object requires
00280 //  an instance of each derived class that might be
00281 //  found.  This function gives the model class to
00282 //  the appropriate loader.
00283 template <class T>
00284 void vsl_add_to_binary_loader(vpgl_proj_camera<T> const& b);
00285 
00286 
00287 #endif // vpgl_proj_camera_h_