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 //     010796 AWF Implemented get_focal_point() - awf, july 96
00018 //     011096 AWF Added caching vnl_svd<double>
00019 //     260297 AWF Converted to use vnl_double_3x4
00020 //     110397 PVr Added operator==
00021 //     221002 Peter Vanroose - added vgl_homg_point_2d interface
00022 //     231002 Peter Vanroose - using fixed 3x4 matrices throughout
00023 //     250503 J.L.M. converted to pure vgl infrastructure and templated
00024 //            also made the interface a bit more consistent with
00025 //            plane projective transformations
00026 //     270603 Peter Vanroose - moved doc from .txx to .h
00027 //                           - implemented 3 NYI methods (get, set, set_rows)
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<T>& A, const vnl_vector<T>& a);
00066   vgl_p_matrix(const vgl_p_matrix& P);
00067  ~vgl_p_matrix();
00068 
00069   //: Load from file.
00070   // Static method, so you can say
00071   // \code
00072   // vgl_p_matrix P = vgl_p_matrix::read("file.P");
00073   // \endcode
00074   static vgl_p_matrix read(const char* filename);
00075   //: Load from vcl_istream
00076   static vgl_p_matrix read(vcl_istream&);
00077 
00078   // Operations----------------------------------------------------------------
00079 
00080   //: Return the image point which is the projection of the specified 3D point X
00081   vgl_homg_point_2d<T>   operator()(vgl_homg_point_3d<T> const& X) const { return p_matrix_ * X; }
00082   //: Return the image point which is the projection of the specified 3D point X
00083   vgl_homg_point_2d<T>   operator*(vgl_homg_point_3d<T> const& X) const { return (*this)(X); }
00084   //: Return the image line which is the projection of the specified 3D line L
00085   vgl_homg_line_2d<T>    operator()(vgl_homg_line_3d_2_points<T> const& L) const;
00086   //: Return the image line which is the projection of the specified 3D line L
00087   vgl_homg_line_2d<T>   operator*(vgl_homg_line_3d_2_points<T> const& L) const { return (*this)(L);}
00088   //: Return the image linesegment which is the projection of the specified 3D linesegment L
00089   vgl_line_segment_2d<T> operator()(vgl_line_segment_3d<T> const& L) const;
00090   //: Return the image linesegment which is the projection of the specified 3D linesegment L
00091   vgl_line_segment_2d<T> operator*(vgl_line_segment_3d<T> const& L) const{return (*this)(L);}
00092   //: Return the 3D point $\vec X$ which is $\vec X = P^+ \vec x$.
00093   // Equivalently, the 3D point of smallest norm such that $P \vec X = \vec x$.
00094   // Uses svd().
00095   vgl_homg_point_3d<T> backproject_pseudoinverse(vgl_homg_point_2d<T> const& x) const;
00096 
00097   //: Return the 3D line which is the backprojection of the specified image point, x.
00098   // Uses svd().
00099   vgl_homg_line_3d_2_points<T>  backproject(vgl_homg_point_2d<T> const& x) const;
00100   //: Return the 3D plane which is the backprojection of the specified line l in the image
00101   vgl_homg_plane_3d<T> backproject(vgl_homg_line_2d<T> const& l) const;
00102 
00103   //: post-multiply this projection matrix with a 3-d projective transform
00104   vgl_p_matrix<T> postmultiply(vnl_matrix_fixed<T,4,4> const& H) const;
00105 
00106   //: pre-multiply this projection matrix with a 2-d projective transform
00107   vgl_p_matrix<T> premultiply(vnl_matrix_fixed<T,3,3> const& H) const;
00108   //: pre-multiply this projection matrix with a 2-d projective transform
00109   vgl_p_matrix<T> operator*(vnl_matrix_fixed<T, 3,3> const& C)const{return vgl_p_matrix(C * p_matrix_);}
00110 
00111   //: Compute the svd of this P and cache it, so that future operations that require it need not recompute it.
00112   vnl_svd<T>* svd() const; // mutable const
00113   //: Discredit the cached svd.
00114   //  This is necessary only in order to recover the space used by it if the vgl_p_matrix is not being deleted.
00115   void clear_svd() const;
00116 
00117   //: Return the 3D point representing the focal point of the camera.
00118   // Uses svd().
00119   vgl_homg_point_3d<T> get_focal() const;
00120 
00121   //: Return the 3D H-matrix s.t. P * H = [I 0].
00122   // If P = [A a], then H = [inv(A) -inv(A)*a; 0 0 0 1];
00123   vgl_h_matrix_3d<T> get_canonical_H() const;
00124   //: Return true iff P is [I 0].
00125   // Equality is assumed if the max abs diff is less than tol.
00126   bool is_canonical(T tol = 0) const;
00127 
00128   //: Return true if the 3D point X is behind the camera represented by this P.
00129   // This depends on the overall sign of the P matrix having been set correctly,
00130   // a la Hartley cheirality paper.
00131   bool is_behind_camera(vgl_homg_point_3d<T> const&);
00132   //: Change the overall sign of the P matrix.
00133   void flip_sign();
00134   //: Splendid hack that tries to detect if the P is an image-coords P or a normalized P.
00135   bool looks_conditioned();
00136   //: Scale P so determinant of first 3x3 is 1.
00137   void fix_cheirality();
00138 
00139   // Data Access---------------------------------------------------------------
00140 
00141   vgl_p_matrix& operator=(const vgl_p_matrix&);
00142 
00143   bool operator==(vgl_p_matrix const& p) const { return p_matrix_ == p.get_matrix(); }
00144 
00145   //: Return the 3x3 matrix and 3x1 column vector of P = [A a].
00146   void get(vnl_matrix<T>* A, vnl_vector<T>* a) const;
00147   //: Return the 3x3 matrix and 3x1 column vector of P = [A a].
00148   void get(vnl_matrix_fixed<T,3,3>* A, vnl_vector_fixed<T,3>* a) const;
00149 
00150   //: Return the rows of P = [a b c]'.
00151   void get_rows(vnl_vector<T>* a, vnl_vector<T>* b, vnl_vector<T>* c) const;
00152   //: Return the rows of P = [a b c]'.
00153   void get_rows(vnl_vector_fixed<T,4>* a, vnl_vector_fixed<T,4>* b, vnl_vector_fixed<T,4>* c) const;
00154   //: Set P = [a b c]' from its rows a, b, c.
00155   void set_rows(const vnl_vector_fixed<T,4>& a, const vnl_vector_fixed<T,4>& b, const vnl_vector_fixed<T,4>& c);
00156 
00157   //: Return the element of the matrix at the specified index pair
00158   T get(unsigned int row_index, unsigned int col_index) const;
00159   //: Return the 3x4 projection matrix in the C-array, c_matrix
00160   void get(T *c_matrix) const;
00161   //: Return the 3x4 projection matrix in p_matrix
00162   void get(vnl_matrix<T>& p_matrix) const { p_matrix = p_matrix_; }
00163   //: Return the 3x4 projection matrix in p_matrix
00164   void get(vnl_matrix_fixed<T, 3, 4>& p_matrix) const { p_matrix = p_matrix_; }
00165 
00166   //: Set the 3x4 projective matrix with the matrix in the C-array, p_matrix
00167   void set(const T* p_matrix);
00168   //: Set the 3x4 projective matrix with the matrix in the C-array, p_matrix
00169   void set(const T p_matrix [3][4]);
00170   //: Set the internal matrix using the vnl_matrix<double> p_matrix.
00171   void set(const vnl_matrix<T>& p_matrix) { p_matrix_ = p_matrix; clear_svd(); }
00172   //: Set the internal matrix using the vnl_matrix<double> p_matrix.
00173   void set(vnl_matrix_fixed<T, 3, 4> const& p_matrix) { p_matrix_ = p_matrix; clear_svd(); }
00174   //: Set from 3x3 matrix and 3x1 column vector of P = [A a].
00175   void set(const vnl_matrix<T>& A, const vnl_vector<T>& a);
00176 
00177   const vnl_matrix_fixed<T, 3, 4>& get_matrix() const { return p_matrix_; }
00178 
00179   //: Set the camera to an identity projection. X->u, Y->v
00180   void set_identity();
00181 
00182   // Utility Methods-----------------------------------------------------------
00183 
00184   //: Load from file.
00185   // \code
00186   // P.read_ascii("file.P");
00187   // \endcode
00188   bool read_ascii(vcl_istream& f);
00189 
00190   // Data Members--------------------------------------------------------------
00191  protected:
00192   vnl_matrix_fixed<T, 3,4> p_matrix_;
00193   mutable vnl_svd<T>* svd_;
00194 };
00195 
00196 //: Postmultiply P-matrix P by 3D H-matrix H
00197 template <class T>
00198 vgl_p_matrix<T> operator*(const vgl_p_matrix<T>& P, const vgl_h_matrix_3d<T>& H);
00199 
00200 //: Print p on an ostream
00201 template <class T> vcl_ostream& operator<<(vcl_ostream& s, const vgl_p_matrix<T>& p);
00202 //: Load p from an ascii istream
00203 template <class T> vcl_istream& operator>>(vcl_istream& i, vgl_p_matrix<T>& p);
00204 
00205 #define VGL_P_MATRIX_INSTANTIATE(T) extern "please include vgl/algo/vgl_p_matrix.txx first"
00206 
00207 #endif // vgl_p_matrix_h_