contrib/gel/mrc/vpgl/vpgl_fundamental_matrix.txx
Go to the documentation of this file.
00001 // This is gel/mrc/vpgl/vpgl_fundamental_matrix.txx
00002 #ifndef vpgl_fundamental_matrix_txx_
00003 #define vpgl_fundamental_matrix_txx_
00004 //:
00005 // \file
00006 
00007 #include "vpgl_fundamental_matrix.h"
00008 //
00009 #include <vnl/vnl_vector_fixed.h>
00010 #include <vnl/vnl_matrix_fixed.h>
00011 #include <vnl/vnl_cross_product_matrix.h>
00012 #include <vnl/io/vnl_io_matrix_fixed.h>
00013 #include <vnl/algo/vnl_svd.h>
00014 #include <vnl/vnl_vector.h>
00015 #include <vgl/vgl_point_2d.h>
00016 #include <vgl/vgl_point_3d.h>
00017 #include <vgl/vgl_homg_point_2d.h>
00018 #include <vgl/vgl_homg_line_2d.h>
00019 #include <vgl/algo/vgl_homg_operators_2d.h>
00020 #include <vcl_iosfwd.h>
00021 #include <vcl_cassert.h>
00022 
00023 //---------------------------------
00024 template <class T>
00025 vpgl_fundamental_matrix<T>::vpgl_fundamental_matrix()
00026   : cached_svd_(NULL)
00027 {
00028   vnl_matrix_fixed<T,3,3> default_matrix( (T)0 );
00029   default_matrix(0,0) = default_matrix(1,1) = (T)1;
00030   set_matrix( default_matrix );
00031 }
00032 
00033 //---------------------------------
00034 //: Copy Constructor
00035 template <class T>
00036 vpgl_fundamental_matrix<T>::vpgl_fundamental_matrix(
00037   const vpgl_fundamental_matrix<T>& other)
00038   : cached_svd_(NULL)
00039 {
00040   set_matrix( other.F_ );
00041 }
00042 
00043 
00044 //---------------------------------
00045 template <class T>
00046 const vpgl_fundamental_matrix<T>&
00047 vpgl_fundamental_matrix<T>::operator=( const vpgl_fundamental_matrix<T>& fm )
00048 {
00049   set_matrix( fm.F_ );
00050   return *this;
00051 }
00052 
00053 
00054 //---------------------------------
00055 //: Destructor
00056 template <class T>
00057 vpgl_fundamental_matrix<T>::~vpgl_fundamental_matrix()
00058 {
00059   delete cached_svd_;
00060 }
00061 
00062 
00063 //---------------------------------
00064 template <class T>
00065 void vpgl_fundamental_matrix<T>::get_epipoles( vgl_homg_point_2d<T>& er,
00066                                                vgl_homg_point_2d<T>& el ) const
00067 {
00068   vnl_vector_fixed<T,3> v = cached_svd_->nullvector();
00069   er.set( v[0], v[1], v[2] );
00070   v = cached_svd_->left_nullvector();
00071   el.set( v[0], v[1], v[2] );
00072 }
00073 
00074 
00075 //---------------------------------
00076 template <class T>
00077 vgl_homg_line_2d<T> vpgl_fundamental_matrix<T>::r_epipolar_line(
00078   const vgl_homg_point_2d<T>& pl ) const
00079 {
00080   vnl_vector_fixed<T,3> lr = F_.transpose() *
00081     vnl_vector_fixed<T,3>( pl.x(), pl.y(), pl.w() );
00082   return vgl_homg_line_2d<T>( lr(0), lr(1), lr(2) );
00083 }
00084 
00085 
00086 //---------------------------------
00087 template <class T>
00088 vgl_homg_line_2d<T> vpgl_fundamental_matrix<T>::l_epipolar_line(
00089   const vgl_homg_point_2d<T>& pr ) const
00090 {
00091   vnl_vector_fixed<T,3> ll =
00092     F_ * vnl_vector_fixed<T,3>( pr.x(), pr.y(), pr.w() );
00093   return vgl_homg_line_2d<T>( ll(0), ll(1), ll(2) );
00094 }
00095 
00096 
00097 //---------------------------------
00098 template <class T>
00099 vgl_homg_line_2d<T> vpgl_fundamental_matrix<T>::r_epipolar_line(
00100     const vgl_homg_line_2d<T> &epiline_l) const
00101 {
00102   vgl_homg_point_2d<T> er, el;
00103 
00104   get_epipoles(er, el);
00105 
00106   vgl_homg_line_2d<T> el_as_line(el.x(), el.y(), el.w());
00107 
00108   vnl_vector_fixed<T,3> epiline_r =
00109     get_matrix().transpose() *
00110     vgl_homg_operators_2d<T>::get_vector(
00111         vgl_homg_operators_2d<T>::intersection( el_as_line , epiline_l));
00112 
00113   return vgl_homg_line_2d<double>(epiline_r[0], epiline_r[1], epiline_r[2]);
00114 }
00115 
00116 
00117 //---------------------------------
00118 template <class T>
00119 vgl_homg_line_2d<T> vpgl_fundamental_matrix<T>::l_epipolar_line(
00120     const vgl_homg_line_2d<T> &epiline_r) const
00121 {
00122   vgl_homg_point_2d<T> er, el;
00123 
00124   get_epipoles(er, el);
00125 
00126   vgl_homg_line_2d<T> er_as_line(er.x(), er.y(), er.w());
00127 
00128   vnl_vector_fixed<T,3> epiline_l =
00129     get_matrix() *
00130     vgl_homg_operators_2d<T>::get_vector(
00131         vgl_homg_operators_2d<T>::intersection( er_as_line , epiline_r));
00132 
00133   return vgl_homg_line_2d<double>(epiline_l[0], epiline_l[1], epiline_l[2]);
00134 }
00135 
00136 
00137 //---------------------------------
00138 template <class T>
00139 vpgl_proj_camera<T> vpgl_fundamental_matrix<T>::extract_left_camera(
00140   const vnl_vector_fixed<T,3>& v, T lambda ) const
00141 {
00142   vgl_homg_point_2d<T> er, el;
00143   get_epipoles( er, el );
00144   vnl_matrix_fixed<T,3,3> elx((T)0);
00145   elx.put( 0, 1, -el.w() ); elx.put( 0, 2, el.y() );
00146   elx.put( 1, 0, el.w() ); elx.put( 1, 2, -el.x() );
00147   elx.put( 2, 0, -el.y() ); elx.put( 2, 1, el.x() );
00148 
00149   vnl_matrix_fixed<T,3,3> elvt;
00150   elvt(0,0) = el.x()*v[0]; elvt(1,0) = el.y()*v[0]; elvt(2,0) = el.w()*v[0];
00151   elvt(0,1) = el.x()*v[1]; elvt(1,1) = el.y()*v[1]; elvt(2,1) = el.w()*v[1];
00152   elvt(0,2) = el.x()*v[2]; elvt(1,2) = el.y()*v[2]; elvt(2,2) = el.w()*v[2];
00153 
00154   vnl_matrix_fixed<T,3,4> P;
00155   P.set_columns( 0, elx*F_+elvt );
00156   P.set_column( 3, vnl_vector_fixed<T,3>( lambda*el.x(), lambda*el.y(), lambda*el.w() ) );
00157   return P;
00158 }
00159 
00160 
00161 //--------------------------------
00162 template <class T>
00163 vpgl_proj_camera<T> vpgl_fundamental_matrix<T>::extract_left_camera(
00164     const vcl_vector< vgl_point_3d<T> >& world_points,
00165     const vcl_vector< vgl_point_2d<T> >& image_points ) const
00166 {
00167   assert( world_points.size() == image_points.size() );
00168   assert( world_points.size() >= 2 );
00169 
00170   vgl_homg_point_2d<T> er, el;
00171   get_epipoles( er, el );
00172   vnl_matrix_fixed<T,3,3> elxF((T)0);
00173   elxF.put( 0, 1, -el.w() ); elxF.put( 0, 2, el.y() );
00174   elxF.put( 1, 0, el.w() ); elxF.put( 1, 2, -el.x() );
00175   elxF.put( 2, 0, -el.y() ); elxF.put( 2, 1, el.x() );
00176   elxF*=F_;
00177 
00178   vnl_matrix<T> A( 3*image_points.size(), 4 );
00179   vnl_vector<T> y( 3*image_points.size() );
00180   for ( unsigned p = 0; p < image_points.size(); p++ ){
00181     vnl_vector_fixed<T,3> wp_vnl(
00182       world_points[p].x(), world_points[p].y(), world_points[p].z() );
00183     vnl_vector_fixed<T,3> ip_vnl(
00184       image_points[p].x(), image_points[p].y(), (T)1 );
00185     vnl_vector_fixed<T,3> yp = ip_vnl - elxF * wp_vnl;
00186     T ei;
00187     for ( unsigned i = 0; i < 3; i++ ){
00188       y(3*p+i) = yp(i);
00189       if ( i == 0 ) ei = el.x(); else if ( i == 1 ) ei = el.y(); else ei = el.w();
00190       A(3*p+i,0) = ei*wp_vnl[0]; A(3*p+i,1) = ei*wp_vnl[1]; A(3*p+i,2) = ei*wp_vnl[2];
00191       A(3*p+i,3) = ei;
00192     }
00193   }
00194 
00195   // Do least squares estimation of y=Ax
00196   vnl_vector<T> x = vnl_svd<T>(A).solve(y);
00197   vnl_vector_fixed<T,3> v( x(0), x(1), x(2) );
00198   T lambda = x(3);
00199   return extract_left_camera( v, lambda );
00200 }
00201 
00202 
00203 //---------------------------------
00204 template <class T>
00205 void vpgl_fundamental_matrix<T>::set_matrix( const vpgl_proj_camera<T>& cr,
00206                                              const vpgl_proj_camera<T>& cl )
00207 {
00208   vnl_cross_product_matrix e2x( cl.get_matrix() * cr.svd()->nullvector() );
00209   set_matrix( e2x * cl.get_matrix() * cr.svd()->inverse() );
00210 }
00211 
00212 
00213 //---------------------------------
00214 template <class T>
00215 void vpgl_fundamental_matrix<T>::set_matrix( const vnl_matrix_fixed<T,3,3>& F )
00216 {
00217   F_ = vnl_svd<T>( F ).recompose(2);
00218   if ( cached_svd_ != NULL ) delete cached_svd_;
00219   cached_svd_ = new vnl_svd<T>( F_ );
00220 }
00221 
00222 //:vpgl_fundamental_matrix stream I/O
00223 
00224 template <class T>
00225 vcl_ostream&  operator<<(vcl_ostream& s, vpgl_fundamental_matrix<T> const& p)
00226 {
00227   s << p.get_matrix();
00228   return s;
00229 }
00230 
00231 //: Read vpgl_perspective_camera  from stream
00232 template <class T>
00233 vcl_istream&  operator>>(vcl_istream& s, vpgl_fundamental_matrix<T>& p)
00234 {
00235   vnl_matrix_fixed<T, 3, 3> m;
00236   s >> m;
00237   p.set_matrix(m);
00238   return s;
00239 }
00240 // Code for easy instantiation.
00241 #undef vpgl_FUNDAMENTAL_MATRIX_INSTANTIATE
00242 #define vpgl_FUNDAMENTAL_MATRIX_INSTANTIATE(T) \
00243 template class vpgl_fundamental_matrix<T >; \
00244 template vcl_ostream& operator<<(vcl_ostream&, const vpgl_fundamental_matrix<T >&); \
00245 template vcl_istream& operator>>(vcl_istream&, vpgl_fundamental_matrix<T >&)
00246 
00247 #endif // vpgl_fundamental_matrix_txx_