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