00001
00002 #ifndef vgl_h_matrix_1d_txx_
00003 #define vgl_h_matrix_1d_txx_
00004
00005 #include "vgl_h_matrix_1d.h"
00006 #include <vgl/vgl_homg_point_1d.h>
00007 #include <vnl/vnl_inverse.h>
00008 #include <vnl/vnl_vector_fixed.h>
00009 #include <vnl/algo/vnl_svd.h>
00010 #include <vcl_cstdlib.h>
00011 #include <vcl_fstream.h>
00012 #include <vcl_cassert.h>
00013 # include <vcl_deprecated.h>
00014
00015
00016 template <class T>
00017 vgl_h_matrix_1d<T>::vgl_h_matrix_1d(vcl_istream &is)
00018 {
00019 t12_matrix_.read_ascii(is);
00020 }
00021
00022 template <class T>
00023 vgl_h_matrix_1d<T>::vgl_h_matrix_1d(vcl_vector<vgl_homg_point_1d<T> > const& points1,
00024 vcl_vector<vgl_homg_point_1d<T> > const& points2)
00025 {
00026 vnl_matrix<T> W;
00027 assert(points1.size() == points2.size());
00028 unsigned int numpoints = points1.size();
00029 if (numpoints < 3)
00030 {
00031 vcl_cerr << "\nvhl_h_matrix_1d - minimum of 3 points required\n";
00032 vcl_exit(0);
00033 }
00034
00035 W.set_size(numpoints, 4);
00036
00037 for (unsigned int i = 0; i < numpoints; i++)
00038 {
00039 T x1 = points1[i].x(), w1 = points1[i].w();
00040 T x2 = points2[i].x(), w2 = points2[i].w();
00041
00042 W[i][0]=x1*w2; W[i][1]=w1*w2;
00043 W[i][2]=-x1*x2; W[i][3]=-w1*x2;
00044 }
00045
00046 vnl_svd<T> SVD(W);
00047 t12_matrix_ = vnl_matrix_fixed<T,2,2>(SVD.nullvector().data_block());
00048 }
00049
00050
00051
00052 template <class T>
00053 vgl_homg_point_1d<T>
00054 vgl_h_matrix_1d<T>::operator()(vgl_homg_point_1d<T> const& p) const
00055 {
00056 vnl_vector_fixed<T,2> v = t12_matrix_ * vnl_vector_fixed<T,2>(p.x(),p.w());
00057 return vgl_homg_point_1d<T>(v[0], v[1]);
00058 }
00059
00060 template <class T>
00061 vgl_homg_point_1d<T>
00062 vgl_h_matrix_1d<T>::preimage(vgl_homg_point_1d<T> const& q) const
00063 {
00064 vnl_vector_fixed<T,2> v = vnl_inverse(t12_matrix_) * vnl_vector_fixed<T,2>(q.x(),q.w());
00065 return vgl_homg_point_1d<T>(v[0], v[1]);
00066 }
00067
00068 template <class T>
00069 vgl_h_matrix_1d<T>
00070 vgl_h_matrix_1d<T>::get_inverse() const
00071 {
00072 return vgl_h_matrix_1d<T>(vnl_inverse(t12_matrix_));
00073 }
00074
00075
00076 template <class T>
00077 vcl_ostream& operator<<(vcl_ostream& s, vgl_h_matrix_1d<T> const& H)
00078 {
00079 return s << H.get_matrix();
00080 }
00081
00082 template <class T>
00083 bool vgl_h_matrix_1d<T>::read(vcl_istream& s)
00084 {
00085 t12_matrix_.read_ascii(s);
00086 return s.good() || s.eof();
00087 }
00088
00089
00090 template <class T>
00091 vgl_h_matrix_1d<T>::vgl_h_matrix_1d(char const* filename)
00092 {
00093 vcl_ifstream f(filename);
00094 if (!f.good())
00095 vcl_cerr << "vgl_h_matrix_1d::read: Error opening " << filename << vcl_endl;
00096 else
00097 t12_matrix_.read_ascii(f);
00098 }
00099
00100 template <class T>
00101 bool vgl_h_matrix_1d<T>::read(char const* filename)
00102 {
00103 vcl_ifstream f(filename);
00104 if (!f.good())
00105 vcl_cerr << "vgl_h_matrix_1d::read: Error opening " << filename << vcl_endl;
00106 return read(f);
00107 }
00108
00109
00110
00111
00112 template <class T>
00113 T vgl_h_matrix_1d<T>::get(unsigned int row_index, unsigned int col_index) const
00114 {
00115 return t12_matrix_.get(row_index, col_index);
00116 }
00117
00118 template <class T>
00119 void vgl_h_matrix_1d<T>::get(T *H) const
00120 {
00121 for (T const* iter = t12_matrix_.begin(); iter < t12_matrix_.end(); ++iter)
00122 *H++ = *iter;
00123 }
00124
00125 template <class T>
00126 void vgl_h_matrix_1d<T>::get(vnl_matrix_fixed<T,2,2>* H) const
00127 {
00128 *H = t12_matrix_;
00129 }
00130
00131 template <class T>
00132 void vgl_h_matrix_1d<T>::get(vnl_matrix<T>* H) const
00133 {
00134 VXL_DEPRECATED("vgl_h_matrix_1d<T>::get(vnl_matrix<T>*) const");
00135 *H = t12_matrix_.as_ref();
00136 }
00137
00138 template <class T>
00139 vgl_h_matrix_1d<T>&
00140 vgl_h_matrix_1d<T>::set(const T* H)
00141 {
00142 for (T* iter = t12_matrix_.begin(); iter < t12_matrix_.end(); ++iter)
00143 *iter = *H++;
00144 return *this;
00145 }
00146
00147 template <class T>
00148 vgl_h_matrix_1d<T>&
00149 vgl_h_matrix_1d<T>::set(vnl_matrix_fixed<T,2,2> const& H)
00150 {
00151 t12_matrix_ = H;
00152 return *this;
00153 }
00154
00155 template <class T>
00156 vgl_h_matrix_1d<T>&
00157 vgl_h_matrix_1d<T>::set_identity()
00158 {
00159 t12_matrix_.set_identity();
00160 return *this;
00161 }
00162
00163 template <class T>
00164 vgl_h_matrix_1d<T>&
00165 vgl_h_matrix_1d<T>::set_scale(T scale)
00166 {
00167 t12_matrix_[0][0]*=scale;
00168 t12_matrix_[0][1]*=scale;
00169 return *this;
00170 }
00171
00172 template <class T>
00173 vgl_h_matrix_1d<T>&
00174 vgl_h_matrix_1d<T>::set_translation(T tx)
00175 {
00176 t12_matrix_[0][1] = tx;
00177 return *this;
00178 }
00179
00180 template <class T>
00181 vgl_h_matrix_1d<T>&
00182 vgl_h_matrix_1d<T>::set_affine(vnl_matrix_fixed<T,1,2> const& M12)
00183 {
00184 for (unsigned r = 0; r<1; ++r)
00185 for (unsigned c = 0; c<2; ++c)
00186 t12_matrix_[r][c] = M12[r][c];
00187 t12_matrix_[1][0] = T(0); t12_matrix_[1][1] = T(1);
00188 return *this;
00189 }
00190
00191
00192 template <class T>
00193 bool vgl_h_matrix_1d<T>::projective_basis(vcl_vector<vgl_homg_point_1d<T> > const& points)
00194 {
00195 if (points.size()!=3)
00196 return false;
00197 vnl_vector_fixed<T,2> p0(points[0].x(), points[0].w());
00198 vnl_vector_fixed<T,2> p1(points[1].x(), points[1].w());
00199 vnl_vector_fixed<T,2> p2(points[2].x(), points[2].w());
00200 vnl_matrix_fixed<T,2,3> point_matrix;
00201 point_matrix.set_column(0, p0);
00202 point_matrix.set_column(1, p1);
00203 point_matrix.set_column(2, p2);
00204
00205 if (! point_matrix.is_finite() || point_matrix.has_nans())
00206 {
00207 vcl_cerr << "vgl_h_matrix_1d<T>::projective_basis():\n"
00208 << " given points have infinite or NaN values\n";
00209 this->set_identity();
00210 return false;
00211 }
00212 vnl_svd<T> svd1(point_matrix.as_ref(), 1e-8);
00213 if (svd1.rank() < 2)
00214 {
00215 vcl_cerr << "vgl_h_matrix_1d<T>::projective_basis():\n"
00216 << " At least two out of the three points are nearly identical\n";
00217 this->set_identity();
00218 return false;
00219 }
00220
00221 vnl_matrix_fixed<T,2,2> back_matrix;
00222 back_matrix.set_column(0, p0);
00223 back_matrix.set_column(1, p1);
00224
00225 vnl_vector_fixed<T,2> scales_vector = vnl_inverse(back_matrix) * p2;
00226
00227 back_matrix.set_column(0, scales_vector[0] * p0);
00228 back_matrix.set_column(1, scales_vector[1] * p1);
00229
00230 if (! back_matrix.is_finite() || back_matrix.has_nans())
00231 {
00232 vcl_cerr << "vgl_h_matrix_1d<T>::projective_basis():\n"
00233 << " back matrix has infinite or NaN values\n";
00234 this->set_identity();
00235 return false;
00236 }
00237 this->set(vnl_inverse(back_matrix));
00238 return true;
00239 }
00240
00241 template <class T>
00242 bool vgl_h_matrix_1d<T>::is_identity() const
00243 {
00244 return t12_matrix_.is_identity();
00245 }
00246
00247 template <class T>
00248 bool vgl_h_matrix_1d<T>::is_rotation() const
00249 {
00250
00251 return t12_matrix_.is_identity();
00252 }
00253
00254
00255 template <class T>
00256 bool vgl_h_matrix_1d<T>::is_euclidean() const
00257 {
00258
00259 return t12_matrix_.get(0,0) == (T)1 &&
00260 t12_matrix_.get(1,0) == (T)0 &&
00261 t12_matrix_.get(1,1) == (T)1 ;
00262 }
00263
00264
00265
00266 #undef VGL_H_MATRIX_1D_INSTANTIATE
00267 #define VGL_H_MATRIX_1D_INSTANTIATE(T) \
00268 template class vgl_h_matrix_1d<T >; \
00269 template vcl_ostream& operator << (vcl_ostream& s, vgl_h_matrix_1d<T > const& h); \
00270 template vcl_istream& operator >> (vcl_istream& s, vgl_h_matrix_1d<T >& h)
00271
00272 #endif // vgl_h_matrix_1d_txx_