00001 #include "rgrl_trans_homography2d.h"
00002
00003
00004 #include <vcl_cassert.h>
00005
00006 #include <vnl/algo/vnl_svd.h>
00007 #include <vnl/vnl_inverse.h>
00008 #include <vnl/vnl_vector_fixed.h>
00009 #include <vnl/vnl_math.h>
00010 #include <vnl/vnl_double_2.h>
00011 #include <vnl/vnl_double_3.h>
00012
00013 #include <rgrl/rgrl_util.h>
00014
00015 rgrl_trans_homography2d::
00016 rgrl_trans_homography2d()
00017 : H_( 0.0 ),
00018 from_centre_( 0.0, 0.0 ),
00019 to_centre_( 0.0, 0.0 )
00020 {}
00021
00022 rgrl_trans_homography2d::
00023 rgrl_trans_homography2d( vnl_matrix<double> const& H,
00024 vnl_matrix<double> const& covar )
00025 : rgrl_transformation( covar ),
00026 H_( H ),
00027 from_centre_( 0.0, 0.0 ),
00028 to_centre_( 0.0, 0.0 )
00029 {
00030 assert( H.rows() == 3 );
00031 assert( H.cols() == 3 );
00032 assert( covar_.rows() == covar_.cols() );
00033
00034 }
00035
00036 rgrl_trans_homography2d::
00037 rgrl_trans_homography2d( vnl_matrix<double> const& H )
00038 : H_( H ),
00039 from_centre_( 0.0, 0.0 ),
00040 to_centre_( 0.0, 0.0 )
00041 {}
00042
00043 rgrl_trans_homography2d::
00044 rgrl_trans_homography2d( vnl_matrix<double> const& H,
00045 vnl_matrix<double> const& covar,
00046 vnl_vector<double> const& from_centre,
00047 vnl_vector<double> const& to_centre )
00048 : rgrl_transformation( covar ),
00049 from_centre_( from_centre ),
00050 to_centre_( to_centre )
00051 {
00052 assert( to_centre.size() == 2 );
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 H_ = H;
00068 }
00069
00070 vnl_matrix_fixed<double, 3, 3>
00071 rgrl_trans_homography2d::
00072 H() const
00073 {
00074 return uncenter_H_matrix();
00075 }
00076
00077 vnl_matrix_fixed<double, 3, 3>
00078 rgrl_trans_homography2d::
00079 uncenter_H_matrix( ) const
00080 {
00081 vnl_matrix_fixed<double, 3, 3> H;
00082
00083
00084 vnl_matrix_fixed<double, 3, 3> to_inv;
00085 to_inv.set_identity();
00086 to_inv(0,2) = to_centre_[0];
00087 to_inv(1,2) = to_centre_[1];
00088
00089
00090 vnl_matrix_fixed<double, 3, 3> from_matrix;
00091 from_matrix.set_identity();
00092 from_matrix(0,2) = -from_centre_[0];
00093 from_matrix(1,2) = -from_centre_[1];
00094
00095 H = to_inv * H_ * from_matrix;
00096
00097 return H;
00098 }
00099
00100 vnl_matrix<double>
00101 rgrl_trans_homography2d::
00102 transfer_error_covar( vnl_vector<double> const& from_loc ) const
00103 {
00104 assert ( is_covar_set() );
00105 assert ( from_loc.size() ==2 );
00106
00107 vnl_matrix_fixed<double, 2, 9 > jac;
00108 vnl_matrix_fixed<double, 3, 9 > jf(0.0);
00109 vnl_matrix_fixed<double, 2, 3 > jg(0.0);
00110 vnl_double_3 from_homo( from_loc[0]-from_centre_[0],
00111 from_loc[1]-from_centre_[1],
00112 1.0 );
00113
00114 vnl_double_3 mapped_homo = H_ * from_homo;
00115
00116
00117 jf(0,0) = jf(1,3) = jf(2,6) = from_homo[0];
00118 jf(0,1) = jf(1,4) = jf(2,7) = from_homo[1];
00119 jf(0,2) = jf(1,5) = jf(2,8) = 1.0;
00120
00121
00122 jg(0,0) = 1.0/mapped_homo[2];
00123 jg(0,2) = -mapped_homo[0]/vnl_math_sqr(mapped_homo[2]);
00124 jg(1,1) = 1.0/mapped_homo[2];
00125 jg(1,2) = -mapped_homo[1]/vnl_math_sqr(mapped_homo[2]);
00126
00127
00128 jac = jg * jf;
00129
00130 return jac * covar_ * jac.transpose();
00131 }
00132
00133
00134 void
00135 rgrl_trans_homography2d::
00136 inv_map( const vnl_vector<double>& to,
00137 vnl_vector<double>& from ) const
00138 {
00139 vnl_double_3 homo_to(to[0], to[1], 1.0);
00140
00141
00142 vnl_double_3 homo_from = vnl_inverse(uncenter_H_matrix()) * homo_to;
00143
00144 from[0] = homo_from[0]/homo_from[2];
00145 from[1] = homo_from[1]/homo_from[2];
00146
00147 return;
00148 }
00149
00150
00151 void
00152 rgrl_trans_homography2d::
00153 inv_map( const vnl_vector<double>& to,
00154 bool initialize_next,
00155 const vnl_vector<double>& to_delta,
00156 vnl_vector<double>& from,
00157 vnl_vector<double>& from_next_est) const
00158 {
00159 const double epsilon = 0.01;
00160 const double eps_squared = epsilon*epsilon;
00161 int t=0;
00162 const int max_t = 50;
00163 assert (to.size() == from.size());
00164 vnl_vector<double> to_est = this->map_location(from);
00165 vnl_matrix<double> approx_A_inv;
00166 vnl_vector<double> homo_from_delta(3,1);
00167 vnl_vector<double> from_delta(2,1);
00168
00169 while ( vnl_vector_ssd(to, to_est) > eps_squared && t<max_t )
00170 {
00171 ++t;
00172
00173
00174 vnl_matrix_fixed<double,2,3> J = homo_jacobian(from);
00175 vnl_svd<double> svd(J);
00176 approx_A_inv = svd.inverse();
00177
00178
00179
00180
00181
00182
00183 homo_from_delta = approx_A_inv * (to - to_est);
00184 homo_from_delta /= homo_from_delta[2];
00185 from_delta[0] = homo_from_delta[0];
00186 from_delta[1] = homo_from_delta[1];
00187 from += from_delta.normalize()*(to - to_est).two_norm()*0.95;
00188 to_est = this->map_location(from);
00189 }
00190 if ( t > max_t )
00191 DebugMacro( 0, " rgrl_trans_homography2d::inv_map() -- no convergence\n");
00192
00193 if ( initialize_next ) {
00194 if ( t == 0 ) {
00195 vnl_matrix_fixed<double,2,3> J = homo_jacobian(from);
00196 vnl_svd<double> svd(J);
00197 approx_A_inv = svd.inverse();
00198 }
00199 vnl_vector<double> homo_from_delta(3,1);
00200 homo_from_delta = approx_A_inv * to_delta;
00201 if (homo_from_delta[2] < 0)
00202 homo_from_delta *= -1;
00203 from_next_est[0] = from[0] + homo_from_delta[0]*to_delta.two_norm();
00204 from_next_est[1] = from[1] + homo_from_delta[1]*to_delta.two_norm();
00205 }
00206 }
00207
00208
00209 rgrl_transformation_sptr
00210 rgrl_trans_homography2d::
00211 inverse_transform() const
00212 {
00213 vnl_matrix_fixed<double,3,3> H_inv = vnl_inverse(H_);
00214 rgrl_transformation_sptr result =
00215 new rgrl_trans_homography2d( H_inv, vnl_matrix<double>(), to_centre_, from_centre_ );
00216
00217 const unsigned m = scaling_factors_.size();
00218 if ( m > 0 ) {
00219 vnl_vector<double> scaling( m );
00220 for ( unsigned int i=0; i<m; ++i )
00221 scaling[i] = 1.0 / scaling_factors_[i];
00222 result->set_scaling_factors( scaling );
00223 }
00224
00225 return result;
00226 }
00227
00228
00229 vnl_matrix_fixed<double,2,3>
00230 rgrl_trans_homography2d::
00231 homo_jacobian( vnl_vector_fixed<double,2> const& from_loc ) const
00232 {
00233
00234
00235
00236
00237
00238
00239
00240
00241 vnl_vector_fixed<double,3> p(from_loc[0]-from_centre_[0], from_loc[1]-from_centre_[1], 1.0);
00242 vnl_vector_fixed<double,3> h_0 = H_.get_row(0);
00243 vnl_vector_fixed<double,3> h_1 = H_.get_row(1);
00244 vnl_vector_fixed<double,3> h_2 = H_.get_row(2);
00245 double inv_mapped_w = 1.0/dot_product(h_2, p);
00246 double mapped_x = dot_product(h_0, p)*inv_mapped_w;
00247 double mapped_y = dot_product(h_1, p)*inv_mapped_w;
00248
00249 vnl_matrix_fixed<double,2,3> jacobian;
00250 jacobian.set_row(0, h_0-mapped_x*h_2 );
00251 jacobian.set_row(1, h_1-mapped_y*h_2 );
00252
00253 return inv_mapped_w*jacobian;
00254 }
00255
00256
00257 void
00258 rgrl_trans_homography2d::
00259 jacobian_wrt_loc( vnl_matrix<double>& jacobian, vnl_vector<double> const& from_loc ) const
00260 {
00261
00262
00263
00264
00265 vnl_double_2 centered_from = from_loc;
00266 centered_from -= from_centre_;
00267
00268 double mapped_w = H_(2,0)*centered_from[0] + H_(2,1)*centered_from[1] + H_(2,2);
00269
00270 jacobian.set_size(2, 2);
00271
00272 jacobian(0,0) = H_(0,0)*( H_(2,1)*centered_from[1]+H_(2,2) ) - H_(2,0)*( H_(0,1)*centered_from[1] + H_(0,2) );
00273 jacobian(1,0) = H_(1,0)*( H_(2,1)*centered_from[1]+H_(2,2) ) - H_(2,0)*( H_(1,1)*centered_from[1] + H_(1,2) );
00274
00275 jacobian(0,1) = H_(0,1)*( H_(2,0)*centered_from[0]+H_(2,2) ) - H_(2,1)*( H_(0,0)*centered_from[0] + H_(0,2) );
00276 jacobian(1,1) = H_(1,1)*( H_(2,0)*centered_from[0]+H_(2,2) ) - H_(2,1)*( H_(1,0)*centered_from[0] + H_(1,2) );
00277
00278 jacobian *= (1/(mapped_w*mapped_w));
00279 }
00280
00281
00282 void
00283 rgrl_trans_homography2d::
00284 write(vcl_ostream& os ) const
00285 {
00286
00287
00288
00289 os << "HOMOGRAPHY2D\n"
00290
00291 << 2 << vcl_endl
00292 << H_ << from_centre_ << " " << to_centre_ << vcl_endl;
00293
00294
00295 rgrl_transformation::write( os );
00296 }
00297
00298
00299 bool
00300 rgrl_trans_homography2d::
00301 read(vcl_istream& is )
00302 {
00303 int dim;
00304
00305
00306 rgrl_util_skip_empty_lines( is );
00307
00308 vcl_string str;
00309 vcl_getline( is, str );
00310
00311
00312 if ( str.find( "HOMOGRAPHY2D" ) != 0 ) {
00313 WarningMacro( "The tag is not HOMOGRAPHY2D. reading is aborted.\n" );
00314 return false;
00315 }
00316
00317
00318 dim=-1;
00319 is >> dim;
00320 if ( dim > 0 ) {
00321 is >> H_ >> from_centre_ >> to_centre_;
00322 }
00323
00324
00325 return is.good() && rgrl_transformation::read( is );
00326 }
00327
00328 void
00329 rgrl_trans_homography2d::
00330 map_loc( vnl_vector<double> const& from,
00331 vnl_vector<double> & to ) const
00332 {
00333 to.set_size(2);
00334
00335 vnl_vector_fixed<double,3> h_from(from[0]-from_centre_[0], from[1]-from_centre_[1], 1);
00336 vnl_vector_fixed<double,3> h_to = H_*h_from;
00337 to[0] = h_to[0]/h_to[2] + to_centre_[0];
00338 to[1] = h_to[1]/h_to[2] + to_centre_[1];
00339 }
00340
00341 void
00342 rgrl_trans_homography2d::
00343 map_dir( vnl_vector<double> const& from_loc,
00344 vnl_vector<double> const& from_dir,
00345 vnl_vector<double> & to_dir ) const
00346 {
00347 assert ( from_loc.size() == 2 );
00348 assert ( from_dir.size() == 2 );
00349 vnl_vector<double> to_loc_begin, to_loc_end;
00350 this->map_loc(from_loc, to_loc_begin);
00351 this->map_loc(from_loc+from_dir, to_loc_end);
00352
00353 to_dir = to_loc_end - to_loc_begin;
00354 to_dir.normalize();
00355 }
00356
00357 rgrl_transformation_sptr
00358 rgrl_trans_homography2d::
00359 scale_by( double scale ) const
00360 {
00361 vnl_matrix_fixed<double,3,3> new_H( H_ );
00362
00363
00364 new_H(0,2) *= scale;
00365 new_H(1,2) *= scale;
00366
00367
00368
00369 new_H(2,0) /= scale;
00370 new_H(2,1) /= scale;
00371
00372
00373 new_H /= new_H.fro_norm();
00374
00375
00376 vnl_vector_fixed<double,2> from = from_centre_ * scale;
00377 vnl_vector_fixed<double,2> to = to_centre_ * scale;
00378
00379 rgrl_transformation_sptr xform
00380 = new rgrl_trans_homography2d( new_H.as_ref(),
00381 vnl_matrix<double>(),
00382 from.as_ref(), to.as_ref() );
00383 xform->set_scaling_factors( this->scaling_factors() );
00384 return xform;
00385 }
00386
00387
00388 rgrl_transformation_sptr
00389 rgrl_trans_homography2d::
00390 clone() const
00391 {
00392 return new rgrl_trans_homography2d( *this );
00393 }