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 vnl_double_3 homo_to(to[0]-to_centre_[0], to[1]-to_centre_[1], 1.0);
00160
00161
00162 vnl_matrix_fixed<double, 3, 3> Hinv = vnl_inverse(H_);
00163 vnl_double_3 homo_from = Hinv * homo_to;
00164
00165 from[0] = homo_from[0]/homo_from[2]+from_centre_[0];
00166 from[1] = homo_from[1]/homo_from[2]+from_centre_[1];
00167
00168 if ( initialize_next ) {
00169 homo_to[0] += to_delta[0];
00170 homo_to[1] += to_delta[1];
00171 homo_from = Hinv * homo_to;
00172 from_next_est[0] = homo_from[0]/homo_from[2]+from_centre_[0];
00173 from_next_est[1] = homo_from[1]/homo_from[2]+from_centre_[1];
00174 }
00175 }
00176
00177
00178 rgrl_transformation_sptr
00179 rgrl_trans_homography2d::
00180 inverse_transform() const
00181 {
00182 vnl_matrix_fixed<double,3,3> H_inv = vnl_inverse(H_);
00183 rgrl_transformation_sptr result =
00184 new rgrl_trans_homography2d( H_inv.as_ref(), vnl_matrix<double>(), to_centre_.as_ref(), from_centre_.as_ref() );
00185
00186 const unsigned m = scaling_factors_.size();
00187 if ( m > 0 ) {
00188 vnl_vector<double> scaling( m );
00189 for ( unsigned int i=0; i<m; ++i )
00190 scaling[i] = 1.0 / scaling_factors_[i];
00191 result->set_scaling_factors( scaling );
00192 }
00193
00194 return result;
00195 }
00196
00197
00198 vnl_matrix_fixed<double,2,3>
00199 rgrl_trans_homography2d::
00200 homo_jacobian( vnl_vector_fixed<double,2> const& from_loc ) const
00201 {
00202
00203
00204
00205
00206
00207
00208
00209
00210 vnl_vector_fixed<double,3> p(from_loc[0]-from_centre_[0], from_loc[1]-from_centre_[1], 1.0);
00211 vnl_vector_fixed<double,3> h_0 = H_.get_row(0);
00212 vnl_vector_fixed<double,3> h_1 = H_.get_row(1);
00213 vnl_vector_fixed<double,3> h_2 = H_.get_row(2);
00214 double inv_mapped_w = 1.0/dot_product(h_2, p);
00215 double mapped_x = dot_product(h_0, p)*inv_mapped_w;
00216 double mapped_y = dot_product(h_1, p)*inv_mapped_w;
00217
00218 vnl_matrix_fixed<double,2,3> jacobian;
00219 jacobian.set_row(0, h_0-mapped_x*h_2 );
00220 jacobian.set_row(1, h_1-mapped_y*h_2 );
00221
00222 return inv_mapped_w*jacobian;
00223 }
00224
00225
00226 void
00227 rgrl_trans_homography2d::
00228 jacobian_wrt_loc( vnl_matrix<double>& jacobian, vnl_vector<double> const& from_loc ) const
00229 {
00230
00231
00232
00233
00234 vnl_double_2 centered_from = from_loc;
00235 centered_from -= from_centre_;
00236
00237 double mapped_w = H_(2,0)*centered_from[0] + H_(2,1)*centered_from[1] + H_(2,2);
00238
00239 jacobian.set_size(2, 2);
00240
00241 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) );
00242 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) );
00243
00244 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) );
00245 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) );
00246
00247 jacobian *= (1/(mapped_w*mapped_w));
00248 }
00249
00250
00251 void
00252 rgrl_trans_homography2d::
00253 write(vcl_ostream& os ) const
00254 {
00255
00256
00257
00258 os << "HOMOGRAPHY2D\n"
00259
00260 << 2 << vcl_endl
00261 << H_ << from_centre_ << " " << to_centre_ << vcl_endl;
00262
00263
00264 rgrl_transformation::write( os );
00265 }
00266
00267
00268 bool
00269 rgrl_trans_homography2d::
00270 read(vcl_istream& is )
00271 {
00272 int dim;
00273
00274
00275 rgrl_util_skip_empty_lines( is );
00276
00277 vcl_string str;
00278 vcl_getline( is, str );
00279
00280
00281 if ( str.find( "HOMOGRAPHY2D" ) != 0 ) {
00282 WarningMacro( "The tag is not HOMOGRAPHY2D. reading is aborted.\n" );
00283 return false;
00284 }
00285
00286
00287 dim=-1;
00288 is >> dim;
00289 if ( dim > 0 ) {
00290 is >> H_ >> from_centre_ >> to_centre_;
00291 }
00292
00293
00294 return is.good() && rgrl_transformation::read( is );
00295 }
00296
00297 void
00298 rgrl_trans_homography2d::
00299 map_loc( vnl_vector<double> const& from,
00300 vnl_vector<double> & to ) const
00301 {
00302 to.set_size(2);
00303
00304 vnl_vector_fixed<double,3> h_from(from[0]-from_centre_[0], from[1]-from_centre_[1], 1);
00305 vnl_vector_fixed<double,3> h_to = H_*h_from;
00306 to[0] = h_to[0]/h_to[2] + to_centre_[0];
00307 to[1] = h_to[1]/h_to[2] + to_centre_[1];
00308 }
00309
00310 void
00311 rgrl_trans_homography2d::
00312 map_dir( vnl_vector<double> const& from_loc,
00313 vnl_vector<double> const& from_dir,
00314 vnl_vector<double> & to_dir ) const
00315 {
00316 assert ( from_loc.size() == 2 );
00317 assert ( from_dir.size() == 2 );
00318 vnl_vector<double> to_loc_begin, to_loc_end;
00319 this->map_loc(from_loc, to_loc_begin);
00320 this->map_loc(from_loc+from_dir, to_loc_end);
00321
00322 to_dir = to_loc_end - to_loc_begin;
00323 to_dir.normalize();
00324 }
00325
00326 rgrl_transformation_sptr
00327 rgrl_trans_homography2d::
00328 scale_by( double scale ) const
00329 {
00330 vnl_matrix_fixed<double,3,3> new_H( H_ );
00331
00332
00333 new_H(0,2) *= scale;
00334 new_H(1,2) *= scale;
00335
00336
00337
00338 new_H(2,0) /= scale;
00339 new_H(2,1) /= scale;
00340
00341
00342 new_H /= new_H.fro_norm();
00343
00344
00345 vnl_vector_fixed<double,2> from = from_centre_ * scale;
00346 vnl_vector_fixed<double,2> to = to_centre_ * scale;
00347
00348 rgrl_transformation_sptr xform
00349 = new rgrl_trans_homography2d( new_H.as_ref(),
00350 vnl_matrix<double>(),
00351 from.as_ref(), to.as_ref() );
00352 xform->set_scaling_factors( this->scaling_factors() );
00353 return xform;
00354 }
00355
00356
00357 rgrl_transformation_sptr
00358 rgrl_trans_homography2d::
00359 clone() const
00360 {
00361 return new rgrl_trans_homography2d( *this );
00362 }