contrib/mul/m23d/m23d_ortho_flexible_builder.h
Go to the documentation of this file.
00001 //:
00002 // \file
00003 // \author Tim Cootes
00004 // \brief Algorithm to estimate 3D shape basis from multiple 2D views
00005 
00006 #ifndef m2d3_ortho_flexible_builder_h_
00007 #define m2d3_ortho_flexible_builder_h_
00008 
00009 #include <vnl/vnl_matrix.h>
00010 #include <vnl/vnl_vector.h>
00011 
00012 #include <vcl_vector.h>
00013 
00014 #include <vgl/vgl_point_3d.h>
00015 #include <vgl/vgl_point_2d.h>
00016 
00017 //: Algorithm to estimate 3D shape basis from multiple 2D views.
00018 //  ses the method of Xiao, Chai and Kanade (CVPR 2004).
00019 //  Generates projection matrix, P, and 3D point matrix P3D, such that
00020 //  P2D = P.P3D.  Uncertainty in projection is constrained by setting
00021 //  the projection for the first shape to the identity (1 0 0; 0 1 0)
00022 //
00023 //  The ambiguity in the sign of the z ordinates is fixed by arranging that
00024 //  the first non-zero z ordinate should be negative.
00025 //
00026 //  Note that the 2D point sets will be normalised so that their CoG is
00027 //  at the origin.  The resulting 3D shape bases will also have their
00028 //  CoG at the origin.
00029 class m23d_ortho_flexible_builder
00030 {
00031  private:
00032     //: 3(1+m) x np matrix, each column containing one 3D point
00033     vnl_matrix<double> P3D_;
00034 
00035     //: The 2ns x 3(1+m) projection matrix
00036     //  Each 2x3 sub-matrix is a scaled orthographic projection matrix
00037     vnl_matrix<double> P_;
00038 
00039     //: The CoG of each shape supplied to reconstruct()
00040     //  This has been subtracted from each example to centre on the origin
00041     //  Centred data stored in P2Dc_
00042     vcl_vector<vgl_point_2d<double> > cog_;
00043 
00044     //: Centred version of the 2D views supplied to reconstruct()
00045     //  Each 2D shape has been translated so that its CoG is at the origin
00046     vnl_matrix<double> P2Dc_;
00047 
00048     //: The 2ns x 3 matrix. Each 2x3 block is the projection for a given view.
00049     //  Each 2x3 sub-matrix is a scaled orthographic projection matrix
00050     vnl_matrix<double> pure_P_;
00051 
00052     //: ns x (m+1) matrix, each row of which contains the weights for a shape
00053     vnl_matrix<double> coeffs_;
00054 
00055     //: Mean 3D shape as a 3 x np matrix
00056     vnl_matrix<double> mean_shape_;
00057 
00058     //: Mean coefficients
00059     vnl_vector<double> mean_coeffs_;
00060 
00061     //: Take copy of 2D points and remove CoG from each
00062     void set_view_data(const vnl_matrix<double>& P2D);
00063 
00064     //: Decompose centred view data to get initial estimate of shape/projection
00065     //  Uncertain up to an affine transformation
00066     void initial_decomposition(unsigned n_modes);
00067 
00068     //: Disambiguate the ambiguity in the sign of the z ordinates
00069     // First non-zero element should be negative.
00070     void disambiguate_z();
00071 
00072     //: Modify projection matrices so they are scaled orthographic projections
00073     //  P = s(I|0)*R
00074     void make_pure_projections();
00075 
00076     //: Compute the mean 3D shape
00077     void compute_mean(vnl_matrix<double>& mean_shape,
00078                       vnl_vector<double>& mean_coeffs);
00079 
00080     //: Return 3d pts given 3*np matrix
00081     void mat_to_3d_pts(vcl_vector< vgl_point_3d<double> >& pts,
00082                        const vnl_matrix<double>& M) const;
00083 
00084  public:
00085 
00086     //: Reconstruct structure from set of 2d pts
00087     // formulates measurement matrix P2D then calls reconstruct() function
00088     void reconstruct(const vcl_vector< vcl_vector< vgl_point_2d<double> > >& pt_vec_list,
00089                      const unsigned& n_modes );
00090 
00091 
00092     //: Reconstruct approximate structure of 3D points given multiple 2D views
00093     //  Data assumed to be scaled orthographic projections
00094     //  The result is stored in the shape_3d() matrix.
00095     //  The estimated projection matrices are stored in the projections() matrix
00096     //  However, the projection matrices are not necessarily consistent.
00097     //  Call refine() to ensure consistancy, (or use reconstruct(P2D,n_modes)
00098     //  This is exposed to aid testing and debugging.
00099     //  \param P2D 2ns x np matrix. Rows contain alternating x's and y's from 2D shapes
00100     void partial_reconstruct(const vnl_matrix<double>& P2D, unsigned n_modes);
00101 
00102     //: Reconstruct structure of 3D points given multiple 2D views
00103     //  Data assumed to be scaled orthographic projections
00104     //  The result is stored in the shape_3d() matrix.
00105     //  The estimated projection matrices are stored in the projections() matrix
00106     //  The first (n_modes+1) views are assumed to define a basis for the
00107     //  modes.  This might not be ideal.  Use reconstruct() to automatically
00108     //  select views which form a good basis.
00109     //  \param P2D 2ns x np matrix. Rows contain alternating x's and y's from 2D shapes
00110     void reconstruct_with_first_as_basis(const vnl_matrix<double>& P2D, unsigned n_modes);
00111 
00112     //: Reconstruct structure of 3D points given multiple 2D views
00113     //  Data assumed to be scaled orthographic projections
00114     //  The result is stored in the shape_3d() matrix.
00115     //  The estimated projection matrices are stored in the projections() matrix
00116     //  Automatically select views which form a good basis.
00117     //  \param P2D 2ns x np matrix. Rows contain alternating x's and y's from 2D shapes
00118     void reconstruct(const vnl_matrix<double>& P2D, unsigned n_modes);
00119 
00120     //: Return 3(m+1) x np matrix, each column containing modes for one 3D point
00121     //  Points are centred on the origin.
00122     //  Each 3 rows contains one of the (1+m) bases.
00123     const vnl_matrix<double>& shape_3d() const { return P3D_; }
00124 
00125     //: The 2ns x 3(m+1) projection matrix
00126     //  Each 2x3 sub-matrix is a scaled orthographic projection matrix
00127     const vnl_matrix<double>& projections() const { return P_; }
00128 
00129     //: Centred version of the 2D views supplied to reconstruct()
00130     //  Each 2D shape has been translated so that its CoG is at the origin
00131     const vnl_matrix<double>& centred_views() const { return P2Dc_; }
00132 
00133     //: The 2ns x 3 matrix. Each 2x3 block is the projection for a given view.
00134     //  Each 2x3 sub-matrix is a scaled orthographic projection matrix
00135     const vnl_matrix<double>& pure_projections() const { return pure_P_; }
00136 
00137     //: ns x (m+1) matrix, each row of which contains the weights for a shape
00138     const vnl_matrix<double>& coeffs() const { return coeffs_; }
00139 
00140     //: Refine estimates of projection and structure
00141     void refine();
00142 
00143     //: Apply rotation matrices to each 3 columns of P (and inverse to rows of B)
00144     // Matrix selected so that projection matrices in each 3 cols have same
00145     // effective rotation.
00146     void correct_coord_frame(vnl_matrix<double>& P,
00147                              vnl_matrix<double>& B);
00148 
00149     //: Compute correction matrix so that M1.G has suitable projection properties
00150     void compute_correction(const vnl_matrix<double>& M1,
00151                             vnl_matrix<double>& G);
00152 
00153     //: Return mean 3D shape as a 3 x np matrix
00154     const vnl_matrix<double>& mean_shape() const { return mean_shape_; }
00155 
00156     //: Return 3D shape i as a 3 x np matrix
00157     vnl_matrix<double> shape(unsigned i) const;
00158 
00159     //: Mean coefficients
00160     const vnl_vector<double>& mean_coeffs() const { return mean_coeffs_; }
00161 
00162 #if 0
00163     //: Get back 3d pts rotated and shifted for each frame
00164     void recon_shapes(vcl_vector< vcl_vector< vgl_point_3d<double> > >& pt_vec_list ) const;
00165 #endif // 0
00166 
00167     //: Return 3d pts given 3*np matrix
00168     void get_shape_3d_pts( vcl_vector< vgl_point_3d<double> >& pts ) const;
00169 };
00170 
00171 #endif // m2d3_ortho_flexible_builder_h_