00001
00002 #ifndef vgl_h_matrix_2d_txx_
00003 #define vgl_h_matrix_2d_txx_
00004
00005
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
00017 template <class T>
00018 vgl_h_matrix_2d<T>::vgl_h_matrix_2d()
00019 {
00020 }
00021
00022
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
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
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
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
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
00066 template <class T>
00067 vgl_h_matrix_2d<T>::~vgl_h_matrix_2d()
00068 {
00069 }
00070
00071
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
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
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
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
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
00188
00189
00190
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
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
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
00214 template <class T>
00215 void vgl_h_matrix_2d<T>::set_identity()
00216 {
00217 t12_matrix_.set_identity();
00218 }
00219
00220
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
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
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
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
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
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
00379
00380
00381
00382
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
00394
00395
00396
00397
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_