core/vpgl/vpgl_essential_matrix.txx
Go to the documentation of this file.
00001 // This is core/vpgl/vpgl_essential_matrix.txx
00002 #ifndef vpgl_essential_matrix_txx_
00003 #define vpgl_essential_matrix_txx_
00004 //:
00005 // \file
00006 
00007 #include "vpgl_essential_matrix.h"
00008 #include <vnl/vnl_fwd.h>
00009 #include <vnl/vnl_vector_fixed.h>
00010 #include <vnl/vnl_matrix_fixed.h>
00011 #include <vnl/vnl_det.h>
00012 #include <vgl/vgl_point_2d.h>
00013 #include <vgl/vgl_point_3d.h>
00014 #include <vgl/vgl_homg_point_3d.h>
00015 #include <vgl/algo/vgl_rotation_3d.h>
00016 #include <vcl_iosfwd.h>
00017 #include "vpgl_proj_camera.h"
00018 
00019 
00020 //---------------------------------
00021 template <class T>
00022 vpgl_essential_matrix<T>::vpgl_essential_matrix()
00023 {
00024 }
00025 
00026 template <class T>
00027 vpgl_essential_matrix<T>::
00028 vpgl_essential_matrix( const vpgl_fundamental_matrix<T>& F,
00029                        const vpgl_calibration_matrix<T>& K_left,
00030                        const vpgl_calibration_matrix<T>& K_right)
00031 {
00032   vnl_matrix_fixed<T, 3, 3> klm = K_left.get_matrix();
00033   vnl_matrix_fixed<T, 3, 3> krm = K_right.get_matrix();
00034   vnl_matrix_fixed<T, 3, 3> fm = F.get_matrix();
00035   this->set_matrix(klm.transpose()*fm*krm);
00036 }
00037 
00038 //--------------------------------------------
00039 //: Compute from Euclidean properties of perspective cameras
00040 template <class T>
00041 vpgl_essential_matrix<T>::
00042 vpgl_essential_matrix( const vpgl_perspective_camera<T>& cr,
00043                        const vpgl_perspective_camera<T>& cl )
00044 {
00045   //copy the cameras
00046   vpgl_perspective_camera<T> crc = cr, clc = cl;
00047   //set the calibration matrices to identity
00048   vpgl_calibration_matrix<T> K;
00049   crc.set_calibration(K); clc.set_calibration(K);
00050   vpgl_proj_camera<T> ppr = static_cast<vpgl_proj_camera<T> >(crc);
00051   vpgl_proj_camera<T> ppl = static_cast<vpgl_proj_camera<T> >(clc);
00052   this->set_matrix(crc, clc);
00053 }
00054 
00055 //---------------------------------
00056 //: Copy Constructor
00057 template <class T>
00058 vpgl_essential_matrix<T>::
00059 vpgl_essential_matrix(const vpgl_essential_matrix<T>& other)
00060 : vpgl_fundamental_matrix<double>(other)
00061 {
00062 }
00063 
00064 //---------------------------------
00065 template <class T>
00066 const vpgl_essential_matrix<T>&
00067 vpgl_essential_matrix<T>::operator=( const vpgl_essential_matrix<T>& fm )
00068 {
00069   vpgl_fundamental_matrix<T>::set_matrix( fm.F_ );
00070   return *this;
00071 }
00072 
00073 //---------------------------------
00074 //: Destructor
00075 template <class T>
00076 vpgl_essential_matrix<T>::~vpgl_essential_matrix()
00077 {
00078 }
00079 
00080 //---------------------------------
00081 // Decompose the essential matrix to obtain rotation and translation of
00082 // the "left" camera. A correspondence is needed in order to remove the
00083 // ambiguity of the decomposition. There are four possible solutions.
00084 // The translation vector, t, in the decomposition,[R|t], is normalized to
00085 // have magnitude, translation_mag.
00086 template <class T>
00087 bool extract_left_camera(const vpgl_essential_matrix<T>& E,
00088                          const vgl_point_2d<T>& left_corr,
00089                          const vgl_point_2d<T>& right_corr,
00090                          vpgl_perspective_camera<T>& p_left,
00091                          const T translation_mag )
00092 {
00093   //The right camera is the identity camera [I|0]
00094   vpgl_perspective_camera<T> p_right;
00095 
00096   vnl_matrix_fixed<T,3,3> W;
00097   W[0][0]=0; W[0][1]=-1;W[0][2]=0;
00098   W[1][0]=1; W[1][1]=0; W[1][2]=0;
00099   W[2][0]=0; W[2][1]=0; W[2][2]=1;
00100 
00101   vnl_svd<T> SVD(E.get_matrix().as_ref());
00102   vnl_matrix_fixed<T,3,3> U=SVD.U();
00103   vnl_matrix_fixed<T,3,3> V=SVD.V();
00104   vnl_matrix_fixed<T,3,3> R;
00105   vnl_vector_fixed<T, 3> t;
00106   // checking for the correct combination of cameras
00107   for ( int c = 0; c < 4; c++ )
00108   {
00109     if ( c == 0 ) { //case 1
00110       R=U*W.transpose()*V.transpose();
00111       t=U.get_column(2);
00112     }
00113     if ( c == 1 ) { //case 2
00114       R=U*W*V.transpose();
00115       t=U.get_column(2);
00116     }
00117     if ( c == 2 ) { //case 3
00118       R=U*W.transpose()*V.transpose();
00119       t=-U.get_column(2);
00120     }
00121     if ( c == 3 ) { //case 4
00122       R=U*W*V.transpose();
00123       t=-U.get_column(2);
00124     }
00125     if ( vnl_det<T>( R ) < 0 ) R = -R ;
00126     t*=translation_mag;
00127     vnl_vector_fixed<T, 3> cc = -R.transpose()*t;
00128     p_left.set_rotation( vgl_rotation_3d<T>(R) );
00129     p_left.set_camera_center( vgl_point_3d<T>( cc(0), cc(1), cc(2) ) );
00130     vpgl_proj_camera<T> ppl =
00131       static_cast<vpgl_proj_camera<T> >(p_left);
00132     vpgl_proj_camera<T> ppr =
00133       static_cast<vpgl_proj_camera<T> >(p_right);
00134     //Test to see if the 3-d point formed by triangulation is in front
00135     //of the camera. There should exist one solution.
00136     vgl_point_3d<T> p3d = triangulate_3d_point<T>(ppl, left_corr, ppr, right_corr );
00137     vgl_homg_point_3d<T> ph3d(p3d);
00138     if (!p_right.is_behind_camera(ph3d) && !p_left.is_behind_camera(ph3d))
00139       break;
00140     if ( c == 3 ) {
00141       vcl_cerr << "ERROR: extract_left_camera in vpgl_essential_matrix failed.\n";
00142       return false;
00143     }
00144   }
00145 
00146   return true;
00147 }
00148 
00149 template <class T>
00150 vcl_ostream&  operator<<(vcl_ostream& s, vpgl_essential_matrix<T> const& p)
00151 {
00152   s << p.get_matrix();
00153   return s;
00154 }
00155 
00156 //: Read vpgl_perspective_camera  from stream
00157 template <class T>
00158 vcl_istream&  operator>>(vcl_istream& s, vpgl_essential_matrix<T>& p)
00159 {
00160   vnl_matrix_fixed<T, 3, 3> m;
00161   s >> m;
00162   p.set_matrix(m);
00163   return s;
00164 }
00165 
00166 // Code for easy instantiation.
00167 #undef vpgl_ESSENTIAL_MATRIX_INSTANTIATE
00168 #define vpgl_ESSENTIAL_MATRIX_INSTANTIATE(T) \
00169 template class vpgl_essential_matrix<T >; \
00170 template bool extract_left_camera(const vpgl_essential_matrix<T >& E, \
00171                                   const vgl_point_2d<T >& left_corr, \
00172                                   const vgl_point_2d<T >& right_corr, \
00173                                   vpgl_perspective_camera<T >& p_left, \
00174                                   const T translation_mag); \
00175 template vcl_ostream& operator<<(vcl_ostream&, const vpgl_essential_matrix<T >&); \
00176 template vcl_istream& operator>>(vcl_istream&, vpgl_essential_matrix<T >&)
00177 
00178 
00179 #endif // vpgl_essential_matrix_txx_