core/vgl/algo/vgl_p_matrix.h
Go to the documentation of this file.
00001 // This is core/vgl/algo/vgl_p_matrix.h
00002 #ifndef vgl_p_matrix_h_
00003 #define vgl_p_matrix_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief General 3x4 perspective projection matrix
00010 //
00011 // A class to hold a perspective projection matrix and use it to
00012 // perform common operations e.g. projecting point in 3d space to
00013 // its image on the image plane
00014 //
00015 // \verbatim
00016 //  Modifications
00017 //   01 Jul 1996 AWF Implemented get_focal_point()
00018 //   01 Oct 1996 AWF Added caching vnl_svd<double>
00019 //   26 Feb 1997 AWF Converted to use vnl_double_3x4
00020 //   11 Mar 1997 PVr - Added operator==
00021 //   22 Oct 2002 Peter Vanroose - added vgl_homg_point_2d interface
00022 //   23 Oct 2002 Peter Vanroose - using fixed 3x4 matrices throughout
00023 //   25 May 2003 J.L.M. converted to pure vgl infrastructure and made templated
00024 //   25 May 2003 J.L.M. made the interface more consistent with plane projective transformations
00025 //   27 Jun 2003 Peter Vanroose - moved doc from .txx to .h
00026 //   27 Jun 2003 Peter Vanroose - implemented 3 NYI methods (get, set, set_rows)
00027 //   24 Oct 2010 Peter Vanroose - mutators and setters now return *this
00028 // \endverbatim
00029 
00030 #include <vcl_iosfwd.h>
00031 
00032 #include <vnl/algo/vnl_algo_fwd.h> // for vnl_svd
00033 #include <vnl/vnl_matrix.h>
00034 #include <vnl/vnl_vector.h>
00035 #include <vnl/vnl_matrix_fixed.h>
00036 #include <vnl/vnl_vector_fixed.h>
00037 #include <vgl/vgl_homg_point_2d.h>
00038 #include <vgl/vgl_homg_point_3d.h>
00039 #include <vgl/vgl_homg_line_2d.h>
00040 #include <vgl/vgl_homg_line_3d_2_points.h>
00041 #include <vgl/vgl_line_segment_2d.h>
00042 #include <vgl/vgl_line_segment_3d.h>
00043 #include <vgl/algo/vgl_homg_operators_3d.h> //for p_matrix_ * vgl_homg_point_3d
00044 #include <vgl/algo/vgl_h_matrix_3d.h>
00045 
00046 template <class T>
00047 class vgl_p_matrix
00048 {
00049  public:
00050 
00051   // Constructors/Initializers/Destructors-------------------------------------
00052 
00053   //: Constructor. Set up a canonical P matrix.
00054   vgl_p_matrix();
00055   //: Construct by loading from vcl_istream.
00056   // \code
00057   //   vgl_p_matrix P(cin);
00058   // \endcode
00059   vgl_p_matrix(vcl_istream&);
00060   //: Construct from row-stored C-array of 12 elements
00061   vgl_p_matrix(const T *c_matrix);
00062   //: Construct from 3x4 matrix
00063   explicit vgl_p_matrix(vnl_matrix_fixed<T, 3, 4> const& P);
00064   //: Construct from 3x3 matrix A and vector a. P = [A a].
00065   vgl_p_matrix(const vnl_matrix_fixed<T,3,3>& A, const vnl_vector_fixed<T,3>& a)
00066   : svd_(0) { set(A,a); }
00067   //: Deprecated; use the vnl_matrix_fixed variant instead
00068   vgl_p_matrix(const vnl_matrix<T>& A, const vnl_vector<T>& a)
00069   : svd_(0) { set(A,a); }
00070 
00071   vgl_p_matrix(const vgl_p_matrix& P);
00072  ~vgl_p_matrix();
00073 
00074   //: Load from file.
00075   // Static method, so you can say
00076   // \code
00077   // vgl_p_matrix P = vgl_p_matrix::read("file.P");
00078   // \endcode
00079   static vgl_p_matrix read(const char* filename);
00080   //: Load from vcl_istream
00081   static vgl_p_matrix read(vcl_istream&);
00082 
00083   // Operations----------------------------------------------------------------
00084 
00085   //: Return the image point which is the projection of the specified 3D point X
00086   vgl_homg_point_2d<T>   operator()(vgl_homg_point_3d<T> const& X) const { return p_matrix_ * X; }
00087   //: Return the image point which is the projection of the specified 3D point X
00088   vgl_homg_point_2d<T>   operator*(vgl_homg_point_3d<T> const& X) const { return (*this)(X); }
00089   //: Return the image line which is the projection of the specified 3D line L
00090   vgl_homg_line_2d<T>    operator()(vgl_homg_line_3d_2_points<T> const& L) const;
00091   //: Return the image line which is the projection of the specified 3D line L
00092   vgl_homg_line_2d<T>   operator*(vgl_homg_line_3d_2_points<T> const& L) const { return (*this)(L);}
00093   //: Return the image linesegment which is the projection of the specified 3D linesegment L
00094   vgl_line_segment_2d<T> operator()(vgl_line_segment_3d<T> const& L) const;
00095   //: Return the image linesegment which is the projection of the specified 3D linesegment L
00096   vgl_line_segment_2d<T> operator*(vgl_line_segment_3d<T> const& L) const{return (*this)(L);}
00097   //: Return the 3D point $\vec X$ which is $\vec X = P^+ \vec x$.
00098   // Equivalently, the 3D point of smallest norm such that $P \vec X = \vec x$.
00099   // Uses svd().
00100   vgl_homg_point_3d<T> backproject_pseudoinverse(vgl_homg_point_2d<T> const& x) const;
00101 
00102   //: Return the 3D line which is the backprojection of the specified image point, x.
00103   // Uses svd().
00104   vgl_homg_line_3d_2_points<T>  backproject(vgl_homg_point_2d<T> const& x) const;
00105   //: Return the 3D plane which is the backprojection of the specified line l in the image
00106   vgl_homg_plane_3d<T> backproject(vgl_homg_line_2d<T> const& l) const;
00107 
00108   //: post-multiply this projection matrix with a 3-d projective transform
00109   vgl_p_matrix<T> postmultiply(vnl_matrix_fixed<T,4,4> const& H) const;
00110 
00111   //: pre-multiply this projection matrix with a 2-d projective transform
00112   vgl_p_matrix<T> premultiply(vnl_matrix_fixed<T,3,3> const& H) const;
00113   //: pre-multiply this projection matrix with a 2-d projective transform
00114   vgl_p_matrix<T> operator*(vnl_matrix_fixed<T, 3,3> const& C)const{return vgl_p_matrix(C * p_matrix_);}
00115 
00116   //: Compute the svd of this P and cache it, so that future operations that require it need not recompute it.
00117   vnl_svd<T>* svd() const; // mutable const
00118   //: Discredit the cached svd.
00119   //  This is necessary only in order to recover the space used by it if the vgl_p_matrix is not being deleted.
00120   void clear_svd() const;
00121 
00122   //: Return the 3D point representing the focal point of the camera.
00123   // Uses svd().
00124   vgl_homg_point_3d<T> get_focal() const;
00125 
00126   //: Return the 3D H-matrix s.t. P * H = [I 0].
00127   // If P = [A a], then H = [inv(A) -inv(A)*a; 0 0 0 1];
00128   vgl_h_matrix_3d<T> get_canonical_H() const;
00129   //: Return true iff P is [I 0].
00130   // Equality is assumed if the max abs diff is less than tol.
00131   bool is_canonical(T tol = 0) const;
00132 
00133   //: Return true if the 3D point X is behind the camera represented by this P.
00134   // This depends on the overall sign of the P matrix having been set correctly,
00135   // a la Hartley cheirality paper.
00136   bool is_behind_camera(vgl_homg_point_3d<T> const&);
00137   //: Change the overall sign of the P matrix.
00138   vgl_p_matrix& flip_sign();
00139   //: Splendid hack that tries to detect if the P is an image-coords P or a normalized P.
00140   bool looks_conditioned();
00141   //: Scale P so determinant of first 3x3 is 1.
00142   vgl_p_matrix& fix_cheirality();
00143 
00144   // Data Access---------------------------------------------------------------
00145 
00146   vgl_p_matrix& operator=(const vgl_p_matrix&);
00147 
00148   bool operator==(vgl_p_matrix const& p) const { return p_matrix_ == p.get_matrix(); }
00149 
00150   //: Return the 3x3 matrix and 3x1 column vector of P = [A a].
00151   void get(vnl_matrix_fixed<T,3,3>* A, vnl_vector_fixed<T,3>* a) const;
00152   //: Deprecated; use the vnl_matrix_fixed variant instead
00153   void get(vnl_matrix<T>* A, vnl_vector<T>* a) const;
00154 
00155   //: Return the rows of P = [a b c]'.
00156   void get_rows(vnl_vector<T>* a, vnl_vector<T>* b, vnl_vector<T>* c) const;
00157   //: Return the rows of P = [a b c]'.
00158   void get_rows(vnl_vector_fixed<T,4>* a, vnl_vector_fixed<T,4>* b, vnl_vector_fixed<T,4>* c) const;
00159   //: Set P = [a b c]' from its rows a, b, c.
00160   vgl_p_matrix& set_rows(const vnl_vector_fixed<T,4>& a, const vnl_vector_fixed<T,4>& b, const vnl_vector_fixed<T,4>& c);
00161 
00162   //: Return the element of the matrix at the specified index pair
00163   T get(unsigned int row_index, unsigned int col_index) const;
00164   //: Return the 3x4 projection matrix in the C-array, c_matrix
00165   void get(T *c_matrix) const;
00166   //: Return the 3x4 projection matrix in p_matrix
00167   void get(vnl_matrix_fixed<T, 3, 4>& p_matrix) const { p_matrix = p_matrix_; }
00168   //: Deprecated; use the vnl_matrix_fixed variant instead
00169   void get(vnl_matrix<T>& p_matrix) const { p_matrix = p_matrix_.as_ref(); }
00170 
00171   //: Set the internal matrix using the 3x4 p_matrix.
00172   vgl_p_matrix& set(vnl_matrix_fixed<T,3,4> const& p_matrix) { p_matrix_ = p_matrix; clear_svd(); return *this; }
00173   //: Deprecated; use the vnl_matrix_fixed variant instead
00174   vgl_p_matrix& set(const vnl_matrix<T>& p_matrix) { p_matrix_ = p_matrix; clear_svd(); return *this; }
00175   //: Set from 3x3 matrix and 3x1 column vector of P = [A a].
00176   vgl_p_matrix& set(vnl_matrix_fixed<T,3,3> const& A, vnl_vector_fixed<T,3> const& a);
00177   //: Deprecated; use the vnl_matrix_fixed variant instead
00178   vgl_p_matrix& set(vnl_matrix<T> const& A, vnl_vector<T> const& a);
00179   //: Set the projective matrix with the matrix in the 3x4 C-array, p_matrix
00180   vgl_p_matrix& set(const T* p_matrix);
00181   //: Set the projective matrix with the matrix in the 3x4 C-array, p_matrix
00182   vgl_p_matrix& set(const T p_matrix [3][4]);
00183 
00184   const vnl_matrix_fixed<T, 3, 4>& get_matrix() const { return p_matrix_; }
00185 
00186   //: Set the camera to an identity projection. X->u, Y->v
00187   vgl_p_matrix& set_identity();
00188 
00189   // Utility Methods-----------------------------------------------------------
00190 
00191   //: Load from file.
00192   // \code
00193   // P.read_ascii("file.P");
00194   // \endcode
00195   bool read_ascii(vcl_istream& f);
00196 
00197   // Data Members--------------------------------------------------------------
00198  protected:
00199   vnl_matrix_fixed<T, 3,4> p_matrix_;
00200   mutable vnl_svd<T>* svd_;
00201 };
00202 
00203 //: Postmultiply P-matrix P by 3D H-matrix H
00204 template <class T>
00205 vgl_p_matrix<T> operator*(const vgl_p_matrix<T>& P, const vgl_h_matrix_3d<T>& H);
00206 
00207 //: Print p on an ostream
00208 template <class T> vcl_ostream& operator<<(vcl_ostream& s, const vgl_p_matrix<T>& p);
00209 //: Load p from an ascii istream
00210 template <class T> vcl_istream& operator>>(vcl_istream& i, vgl_p_matrix<T>& p);
00211 
00212 #define VGL_P_MATRIX_INSTANTIATE(T) extern "please include vgl/algo/vgl_p_matrix.txx first"
00213 
00214 #endif // vgl_p_matrix_h_