core/vgl/algo/vgl_h_matrix_2d.txx

Go to the documentation of this file.
00001 // This is core/vgl/algo/vgl_h_matrix_2d.txx
00002 #ifndef vgl_h_matrix_2d_txx_
00003 #define vgl_h_matrix_2d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_h_matrix_2d.h"
00008 #include <vnl/vnl_inverse.h>
00009 #include <vnl/vnl_vector_fixed.h>
00010 #include <vnl/algo/vnl_svd.h>
00011 #include <vcl_fstream.h>
00012 
00013 //--------------------------------------------------------------
00014 //
00015 
00016 //: Default constructor
00017 template <class T>
00018 vgl_h_matrix_2d<T>::vgl_h_matrix_2d()
00019 {
00020 }
00021 
00022 //: Copy constructor
00023 template <class T>
00024 vgl_h_matrix_2d<T>::vgl_h_matrix_2d(const vgl_h_matrix_2d<T>& M)
00025 {
00026   t12_matrix_ = M.t12_matrix_;
00027 }
00028 
00029 
00030 //: Constructor from vcl_istream
00031 template <class T>
00032 vgl_h_matrix_2d<T>::vgl_h_matrix_2d(vcl_istream& s)
00033 {
00034   t12_matrix_.read_ascii(s);
00035 }
00036 
00037 //: Constructor from file
00038 template <class T>
00039 vgl_h_matrix_2d<T>::vgl_h_matrix_2d(char const* filename)
00040 {
00041   vcl_ifstream f(filename);
00042   if (!f.good())
00043     vcl_cerr << "vgl_h_matrix_2d::read: Error opening " << filename << vcl_endl;
00044   else
00045     t12_matrix_.read_ascii(f);
00046 }
00047 
00048 //--------------------------------------------------------------
00049 //: Constructor
00050 template <class T>
00051 vgl_h_matrix_2d<T>::vgl_h_matrix_2d(vnl_matrix_fixed<T,3,3> const& M):
00052   t12_matrix_(M)
00053 {
00054 }
00055 
00056 //--------------------------------------------------------------
00057 //: Constructor
00058 template <class T>
00059 vgl_h_matrix_2d<T>::vgl_h_matrix_2d(const T* H)
00060   : t12_matrix_(H)
00061 {
00062 }
00063 
00064 
00065 //: Destructor
00066 template <class T>
00067 vgl_h_matrix_2d<T>::~vgl_h_matrix_2d()
00068 {
00069 }
00070 
00071 // == OPERATIONS ==
00072 
00073 template <class T>
00074 vgl_homg_point_2d<T>
00075 vgl_h_matrix_2d<T>::operator()(vgl_homg_point_2d<T> const& p) const
00076 {
00077   vnl_vector_fixed<T, 3> v(p.x(), p.y(), p.w());
00078   vnl_vector_fixed<T,3> v2 = t12_matrix_ * v;
00079   return vgl_homg_point_2d<T>(v2[0], v2[1], v2[2]);
00080 }
00081 
00082 template <class T>
00083 vgl_homg_line_2d<T>
00084 vgl_h_matrix_2d<T>::preimage(vgl_homg_line_2d<T> const& l) const
00085 {
00086   vnl_vector_fixed<T,3> v(l.a(), l.b(), l.c());
00087   vnl_vector_fixed<T,3> v2 = t12_matrix_.transpose() * v;
00088   return vgl_homg_line_2d<T>(v2[0], v2[1], v2[2]);
00089 }
00090 
00091 template <class T>
00092 vgl_homg_line_2d<T>
00093 vgl_h_matrix_2d<T>::correlation(vgl_homg_point_2d<T> const& p) const
00094 {
00095   vnl_vector_fixed<T, 3> v(p.x(), p.y(), p.w());
00096   vnl_vector_fixed<T,3> v2 = t12_matrix_ * v;
00097   return vgl_homg_line_2d<T>(v2[0], v2[1], v2[2]);
00098 }
00099 
00100 template <class T>
00101 vgl_homg_point_2d<T>
00102 vgl_h_matrix_2d<T>::correlation(vgl_homg_line_2d<T> const& l) const
00103 {
00104   vnl_vector_fixed<T,3> v(l.a(), l.b(), l.c());
00105   vnl_vector_fixed<T,3> v2 = t12_matrix_ * v;
00106   return vgl_homg_point_2d<T>(v2[0], v2[1], v2[2]);
00107 }
00108 
00109 template <class T>
00110 vgl_conic<T> vgl_h_matrix_2d<T>::operator() (vgl_conic<T> const& C) const
00111 {
00112   T a=C.a(), b=C.b()/2, c = C.c(), d = C.d()/2, e = C.e()/2, f = C.f();
00113   vnl_matrix_fixed<T, 3, 3> M, Mp;
00114   M(0,0) = a;  M(0,1) = b;  M(0,2) = d;
00115   M(1,0) = b;  M(1,1) = c;  M(1,2) = e;
00116   M(2,0) = d;  M(2,1) = e;  M(2,2) = f;
00117   Mp = (t12_matrix_.transpose())*M*t12_matrix_;
00118   return   vgl_conic<T>(Mp(0,0),(Mp(0,1)+Mp(1,0)),Mp(1,1),(Mp(0,2)+Mp(2,0)),
00119                         (Mp(1,2)+Mp(2,1)), Mp(2,2));
00120 }
00121 
00122 template <class T>
00123 vgl_conic<T> vgl_h_matrix_2d<T>::preimage(vgl_conic<T> const& C) const
00124 {
00125   T a=C.a(), b=C.b()/2, c = C.c(), d = C.d()/2, e = C.e()/2, f = C.f();
00126   vnl_matrix_fixed<T, 3, 3> M, Mp;
00127   M(0,0) = a;  M(0,1) = b;  M(0,2) = d;
00128   M(1,0) = b;  M(1,1) = c;  M(1,2) = e;
00129   M(2,0) = d;  M(2,1) = e;  M(2,2) = f;
00130   Mp = vnl_inverse_transpose(t12_matrix_)*M*vnl_inverse(t12_matrix_);
00131   return   vgl_conic<T>(Mp(0,0),(Mp(0,1)+Mp(1,0)),Mp(1,1),(Mp(0,2)+Mp(2,0)),
00132                         (Mp(1,2)+Mp(2,1)), Mp(2,2));
00133 }
00134 
00135 
00136 template <class T>
00137 vgl_homg_point_2d<T>
00138 vgl_h_matrix_2d<T>::preimage(vgl_homg_point_2d<T> const& p) const
00139 {
00140   vnl_vector_fixed<T,3> v(p.x(), p.y(), p.w());
00141   v = vnl_inverse(t12_matrix_) * v;
00142   return vgl_homg_point_2d<T>(v[0], v[1], v[2]);
00143 }
00144 
00145 template <class T>
00146 vgl_homg_line_2d<T>
00147 vgl_h_matrix_2d<T>::operator()(vgl_homg_line_2d<T> const& l) const
00148 {
00149   vnl_vector_fixed<T,3> v(l.a(), l.b(), l.c());
00150   v = vnl_inverse_transpose(t12_matrix_) * v;
00151   return vgl_homg_line_2d<T>(v[0], v[1], v[2]);
00152 }
00153 
00154 //-----------------------------------------------------------------------------
00155 //: Print H on vcl_ostream
00156 template <class T>
00157 vcl_ostream& operator<<(vcl_ostream& s, const vgl_h_matrix_2d<T>& h)
00158 {
00159   return s << h.get_matrix();
00160 }
00161 
00162 //: Read H from vcl_istream
00163 template <class T>
00164 vcl_istream& operator >> (vcl_istream& s, vgl_h_matrix_2d<T>& H)
00165 {
00166   H.read(s);
00167   return s;
00168 }
00169 
00170 //: Read H from vcl_istream
00171 template <class T>
00172 bool vgl_h_matrix_2d<T>::read(vcl_istream& s)
00173 {
00174   return t12_matrix_.read_ascii(s);
00175 }
00176 
00177 //: Read H from file
00178 template <class T>
00179 bool vgl_h_matrix_2d<T>::read(char const* filename)
00180 {
00181   vcl_ifstream f(filename);
00182   if (!f.good())
00183     vcl_cerr << "vgl_h_matrix_2d::read: Error opening " << filename << vcl_endl;
00184   return read(f);
00185 }
00186 
00187 // == DATA ACCESS ==
00188 
00189 //-----------------------------------------------------------------------------
00190 //: Get matrix element at (row_index, col_index)
00191 template <class T>
00192 T vgl_h_matrix_2d<T>::get(unsigned int row_index, unsigned int col_index) const
00193 {
00194   return t12_matrix_. get(row_index, col_index);
00195 }
00196 
00197 //: Fill H with contents of this
00198 template <class T>
00199 void vgl_h_matrix_2d<T>::get(T* H) const
00200 {
00201   for (int row_index = 0; row_index < 3; row_index++)
00202     for (int col_index = 0; col_index < 3; col_index++)
00203       *H++ = t12_matrix_.get(row_index, col_index);
00204 }
00205 
00206 //: Fill H with contents of this
00207 template <class T>
00208 void vgl_h_matrix_2d<T>::get(vnl_matrix<T>* H) const
00209 {
00210   *H = t12_matrix_;
00211 }
00212 
00213 //: Set to identity
00214 template <class T>
00215 void vgl_h_matrix_2d<T>::set_identity()
00216 {
00217   t12_matrix_.set_identity();
00218 }
00219 
00220 //: Set to 3x3 row-stored matrix
00221 template <class T>
00222 void vgl_h_matrix_2d<T>::set(const T* H)
00223 {
00224   for (int row_index = 0; row_index < 3; row_index++)
00225     for (int col_index = 0; col_index < 3; col_index++)
00226       t12_matrix_.put(row_index, col_index, *H++);
00227 }
00228 
00229 //: Set to given vnl_matrix
00230 template <class T>
00231 void vgl_h_matrix_2d<T>::set(vnl_matrix_fixed<T,3,3> const& H)
00232 {
00233   t12_matrix_ = H;
00234 }
00235 
00236 //-------------------------------------------------------------------
00237 template <class T>
00238 bool vgl_h_matrix_2d<T>::
00239 projective_basis(vcl_vector<vgl_homg_point_2d<T> > const& points)
00240 {
00241   if (points.size()!=4)
00242     return false;
00243   vnl_vector_fixed<T, 3> p0(points[0].x(), points[0].y(), points[0].w());
00244   vnl_vector_fixed<T, 3> p1(points[1].x(), points[1].y(), points[1].w());
00245   vnl_vector_fixed<T, 3> p2(points[2].x(), points[2].y(), points[2].w());
00246   vnl_vector_fixed<T, 3> p3(points[3].x(), points[3].y(), points[3].w());
00247   vnl_matrix_fixed<T, 3, 4> point_matrix;
00248   point_matrix.set_column(0, p0);
00249   point_matrix.set_column(1, p1);
00250   point_matrix.set_column(2, p2);
00251   point_matrix.set_column(3, p3);
00252 
00253   if (! point_matrix.is_finite() || point_matrix.has_nans())
00254   {
00255     vcl_cerr << "vgl_h_matrix_2d<T>::projective_basis():\n"
00256              << " given points have infinite or NaN values\n";
00257     this->set_identity();
00258     return false;
00259   }
00260   vnl_svd<T> svd1(point_matrix, 1e-8);
00261   if (svd1.rank() < 3)
00262   {
00263     vcl_cerr << "vgl_h_matrix_2d<T>::projective_basis():\n"
00264              << " At least three out of the four points are nearly collinear\n";
00265     this->set_identity();
00266     return false;
00267   }
00268 
00269   vnl_matrix_fixed<T, 3, 3> back_matrix;
00270   back_matrix.set_column(0, p0);
00271   back_matrix.set_column(1, p1);
00272   back_matrix.set_column(2, p2);
00273 
00274   vnl_vector_fixed<T, 3> scales_vector = vnl_inverse(back_matrix) * p3;
00275 
00276   back_matrix.set_column(0, scales_vector[0] * p0);
00277   back_matrix.set_column(1, scales_vector[1] * p1);
00278   back_matrix.set_column(2, scales_vector[2] * p2);
00279 
00280   if (! back_matrix.is_finite() || back_matrix.has_nans())
00281   {
00282     vcl_cerr << "vgl_h_matrix_2d<T>::projective_basis():\n"
00283              << " back matrix has infinite or NaN values\n";
00284     this->set_identity();
00285     return false;
00286   }
00287   this->set(vnl_inverse(back_matrix));
00288   return true;
00289 }
00290 
00291 //-------------------------------------------------------------------
00292 template <class T>
00293 bool vgl_h_matrix_2d<T>::
00294 projective_basis(vcl_vector<vgl_homg_line_2d<T> > const& lines
00295 #ifdef VCL_VC_6
00296                 ,int dummy // parameter to help useless compiler disambiguate different functions
00297 #endif
00298                 )
00299 {
00300   if (lines.size()!=4)
00301     return false;
00302   vnl_vector_fixed<T,3> l0(lines[0].a(), lines[0].b(), lines[0].c());
00303   vnl_vector_fixed<T,3> l1(lines[1].a(), lines[1].b(), lines[1].c());
00304   vnl_vector_fixed<T,3> l2(lines[2].a(), lines[2].b(), lines[2].c());
00305   vnl_vector_fixed<T,3> l3(lines[3].a(), lines[3].b(), lines[3].c());
00306   vnl_matrix_fixed<T,3,4> line_matrix;
00307   line_matrix.set_column(0, l0);
00308   line_matrix.set_column(1, l1);
00309   line_matrix.set_column(2, l2);
00310   line_matrix.set_column(3, l3);
00311 
00312   if (! line_matrix.is_finite() || line_matrix.has_nans())
00313   {
00314     vcl_cerr << "vgl_h_matrix_2d<T>::projective_basis():\n"
00315              << " given lines have infinite or NaN values\n";
00316     this->set_identity();
00317     return false;
00318   }
00319   vnl_svd<T> svd1(line_matrix, 1e-8);
00320   if (svd1.rank() < 3)
00321   {
00322     vcl_cerr << "vgl_h_matrix_2d<T>::projective_basis():\n"
00323              << " At least three out of the four lines are nearly concurrent\n";
00324     this->set_identity();
00325     return false;
00326   }
00327 
00328   vnl_matrix_fixed<T,3,3> back_matrix;
00329   back_matrix.set_column(0, l0);
00330   back_matrix.set_column(1, l1);
00331   back_matrix.set_column(2, l2);
00332 
00333   vnl_svd<T> svd(back_matrix);
00334 
00335   vnl_vector_fixed<T, 3> scales_vector = svd.solve(l3);
00336 
00337   back_matrix.set_row(0, scales_vector[0] * l0);
00338   back_matrix.set_row(1, scales_vector[1] * l1);
00339   back_matrix.set_row(2, scales_vector[2] * l2);
00340 
00341   if (! back_matrix.is_finite() || back_matrix.has_nans())
00342   {
00343     vcl_cerr << "vgl_h_matrix_2d<T>::projective_basis():\n"
00344              << " back matrix has infinite or NaN values\n";
00345     this->set_identity();
00346     return false;
00347   }
00348   this->set(back_matrix);
00349   return true;
00350 }
00351 
00352 //: Return the inverse
00353 template <class T>
00354 const vgl_h_matrix_2d<T> vgl_h_matrix_2d<T>::get_inverse() const
00355 {
00356   vnl_matrix_fixed<T, 3, 3> temp = vnl_inverse(t12_matrix_);
00357   return vgl_h_matrix_2d<T>(temp);
00358 }
00359 
00360 
00361 //: Set the (0,2) and (1,2) elements of the transform matrix
00362 template <class T>
00363 void vgl_h_matrix_2d<T>::set_translation(const T tx, const T ty)
00364 {
00365   t12_matrix_[0][2] = tx;   t12_matrix_[1][2] = ty;
00366 }
00367 
00368 //: Set the upper 2x2 submatrix to a rotation matrix defined by theta
00369 template <class T>
00370 void vgl_h_matrix_2d<T>::set_rotation(const T theta)
00371 {
00372   double theta_d = (double)theta;
00373   double c = vcl_cos(theta_d), s = vcl_sin(theta_d);
00374   t12_matrix_[0][0] = (T)c;   t12_matrix_[0][1] = -(T)s;
00375   t12_matrix_[1][0] = (T)s;   t12_matrix_[1][1] = (T)c;
00376 }
00377 
00378 //: Compose the existing matrix with a uniform scale transformation
00379 //        _     _
00380 //       |s  0  0|
00381 //  Hs = |0  s  0| Hinitial
00382 //       |0  0  1|
00383 //        -     -
00384 //
00385 template <class T>
00386 void vgl_h_matrix_2d<T>::set_scale(const T scale)
00387 {
00388   for (unsigned r = 0; r<2; ++r)
00389     for (unsigned c = 0; c<3; ++c)
00390       t12_matrix_[r][c]*=scale;
00391 }
00392 
00393 //: Compose the existing matrix with an aspect ratio transform 
00394 //        _     _
00395 //       |1  0  0|
00396 //  Hs = |0  r  0| Hinitial
00397 //       |0  0  1|
00398 //        -     -
00399 //
00400 template <class T>
00401 void vgl_h_matrix_2d<T>::set_aspect_ratio(const T aspect_ratio)
00402 {
00403   for (unsigned c = 0; c<3; ++c)
00404     t12_matrix_[1][c]*=aspect_ratio;
00405 }
00406 
00407 //----------------------------------------------------------------------------
00408 #undef VGL_H_MATRIX_2D_INSTANTIATE
00409 #define VGL_H_MATRIX_2D_INSTANTIATE(T) \
00410 template class vgl_h_matrix_2d<T >; \
00411 template vcl_ostream& operator << (vcl_ostream& s, const vgl_h_matrix_2d<T >& h); \
00412 template vcl_istream& operator >> (vcl_istream& s, vgl_h_matrix_2d<T >& h)
00413 
00414 #endif // vgl_h_matrix_2d_txx_

Generated on Mon Mar 8 05:07:49 2010 for core/vgl by  doxygen 1.5.1