00001
00002 #include "rgrl_trans_rad_dis_homo2d.h"
00003
00004
00005
00006 #include <vcl_cassert.h>
00007 #include <vnl/vnl_vector_fixed.h>
00008 #include <vnl/vnl_math.h>
00009 #include <vnl/vnl_double_2.h>
00010 #include <vnl/vnl_double_3.h>
00011 #include <vnl/vnl_double_2x2.h>
00012 #include <vnl/vnl_transpose.h>
00013
00014 #include "rgrl_util.h"
00015
00016
00017
00018
00019
00020
00021 static
00022 inline
00023 void
00024 map_inhomo_point( vnl_double_2& mapped, vnl_matrix_fixed<double, 3, 3> const& H, vnl_vector<double> const& loc )
00025 {
00026 vnl_double_3 homo_from( loc[0], loc[1], 1 );
00027 vnl_double_3 homo_to = H * homo_from;
00028 mapped[0] = homo_to[0]/homo_to[2];
00029 mapped[1] = homo_to[1]/homo_to[2];
00030 }
00031
00032
00033 static
00034 void
00035 homo_wrt_loc( vnl_matrix_fixed<double, 2, 2>& jac_loc,
00036 vnl_matrix_fixed<double, 3, 3> const& H,
00037 vnl_vector_fixed<double, 2> const& from_loc )
00038 {
00039
00040
00041
00042
00043 const double mapped_w = H(2,0)*from_loc[0] + H(2,1)*from_loc[1] + H(2,2);
00044
00045
00046 jac_loc(0,0) = H(0,0)*( H(2,1)*from_loc[1]+H(2,2) ) - H(2,0)*( H(0,1)*from_loc[1] + H(0,2) );
00047 jac_loc(1,0) = H(1,0)*( H(2,1)*from_loc[1]+H(2,2) ) - H(2,0)*( H(1,1)*from_loc[1] + H(1,2) );
00048
00049 jac_loc(0,1) = H(0,1)*( H(2,0)*from_loc[0]+H(2,2) ) - H(2,1)*( H(0,0)*from_loc[0] + H(0,2) );
00050 jac_loc(1,1) = H(1,1)*( H(2,0)*from_loc[0]+H(2,2) ) - H(2,1)*( H(1,0)*from_loc[0] + H(1,2) );
00051
00052 jac_loc *= (1/(mapped_w*mapped_w));
00053 }
00054
00055
00056 static
00057 void
00058 homo_wrt_h( vnl_matrix_fixed<double, 2, 9>& jac_h,
00059 vnl_matrix_fixed<double, 3, 3> const& H,
00060 vnl_vector_fixed<double, 2> const& from_loc )
00061 {
00062 vnl_matrix_fixed<double, 3, 9 > jf(0.0);
00063 vnl_matrix_fixed<double, 2, 3 > jg(0.0);
00064
00065
00066 vnl_double_3 from_homo( from_loc[0], from_loc[1], 1 );
00067 vnl_double_3 mapped_homo = H * from_homo;
00068
00069
00070 jf(0,0) = jf(1,3) = jf(2,6) = from_homo[0];
00071 jf(0,1) = jf(1,4) = jf(2,7) = from_homo[1];
00072 jf(0,2) = jf(1,5) = jf(2,8) = 1.0;
00073
00074
00075 jg(0,0) = 1.0/mapped_homo[2];
00076 jg(0,2) = -mapped_homo[0]/vnl_math_sqr(mapped_homo[2]);
00077 jg(1,1) = 1.0/mapped_homo[2];
00078 jg(1,2) = -mapped_homo[1]/vnl_math_sqr(mapped_homo[2]);
00079
00080
00081 jac_h = jg * jf;
00082 }
00083
00084
00085 static
00086 inline
00087 void
00088 distort( vnl_double_2& dis_loc, vnl_double_2 const& true_loc, double k1 )
00089 {
00090 const double c = 1 + k1 * true_loc.squared_magnitude();
00091 dis_loc = c * true_loc;
00092 }
00093
00094 #if 0 // ***This is incorrect implementation***
00095
00096 static
00097 inline
00098 void
00099 undistort( vnl_double_2& true_loc, vnl_double_2 const& dis_loc, double k1 )
00100 {
00101 const double c = 1 + k1 * dis_loc.squared_magnitude();
00102 true_loc = dis_loc;
00103 }
00104 #endif // 0
00105
00106
00107 static
00108 inline
00109 void
00110 distort_wrt_k1( vnl_double_2& jac_k1, vnl_double_2 const& true_loc )
00111 {
00112 const double c = true_loc.squared_magnitude();
00113 jac_k1 = c * true_loc;
00114 }
00115
00116
00117
00118 static
00119 inline
00120 void
00121 distort_wrt_loc( vnl_double_2x2& jac_loc, vnl_double_2 const& true_loc, double k1 )
00122 {
00123 const double c = 1 + k1 * true_loc.squared_magnitude();
00124
00125 jac_loc(0,0) = c + 2*k1*vnl_math_sqr(true_loc[0]);
00126 jac_loc(1,1) = c + 2*k1*vnl_math_sqr(true_loc[1]);
00127 jac_loc(0,1) = jac_loc(1,0) = 2 * k1 * true_loc[0] * true_loc[1];
00128 }
00129
00130
00131 rgrl_trans_rad_dis_homo2d::
00132 rgrl_trans_rad_dis_homo2d()
00133 : H_( 0.0 ),
00134 from_centre_( 0.0, 0.0 ),
00135 to_centre_( 0.0, 0.0 ),
00136 k1_from_( 0.0 ),
00137 k1_to_( 0.0 )
00138 {}
00139
00140 rgrl_trans_rad_dis_homo2d::
00141 rgrl_trans_rad_dis_homo2d( vnl_matrix<double> const& H,
00142 double k1_from,
00143 double k1_to,
00144 vnl_vector<double> const& from_centre,
00145 vnl_vector<double> const& to_centre )
00146 : H_( H ),
00147 from_centre_( from_centre ),
00148 to_centre_( to_centre ),
00149 k1_from_( k1_from ),
00150 k1_to_( k1_to )
00151 {}
00152
00153 rgrl_trans_rad_dis_homo2d::
00154 rgrl_trans_rad_dis_homo2d( vnl_matrix<double> const& H,
00155 double k1_from,
00156 double k1_to,
00157 vnl_matrix<double> const& covar,
00158 vnl_vector<double> const& from_centre,
00159 vnl_vector<double> const& to_centre )
00160 : rgrl_transformation( covar ),
00161 H_( H ),
00162 from_centre_( from_centre ),
00163 to_centre_( to_centre ),
00164 k1_from_( k1_from ),
00165 k1_to_( k1_to )
00166 {
00167 assert( to_centre.size() == 2 );
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 }
00182
00183 vnl_matrix<double>
00184 rgrl_trans_rad_dis_homo2d::
00185 transfer_error_covar( vnl_vector<double> const& from ) const
00186 {
00187 assert ( is_covar_set() );
00188 assert ( from.size() ==2 );
00189
00190
00191 vnl_double_2 dis_from_loc( from[0]-from_centre_[0], from[1]-from_centre_[1] );
00192 vnl_double_2 true_from_loc;
00193
00194 distort( true_from_loc, dis_from_loc, k1_from_ );
00195 vnl_double_2x2 pu_pd;
00196 distort_wrt_loc( pu_pd, dis_from_loc, k1_from_ );
00197 vnl_double_2 pu_k1_from;
00198 distort_wrt_k1( pu_k1_from, dis_from_loc );
00199
00200
00201 vnl_double_2 true_to_loc;
00202 map_inhomo_point( true_to_loc, H_, true_from_loc.as_ref() );
00203 vnl_double_2x2 qu_pu;
00204 homo_wrt_loc( qu_pu, H_, true_from_loc );
00205 vnl_matrix_fixed<double, 2, 9> qu_h;
00206 homo_wrt_h( qu_h, H_, true_from_loc );
00207
00208
00209 vnl_double_2x2 qd_qu;
00210 distort_wrt_loc( qd_qu, true_to_loc, k1_to_ );
00211 vnl_double_2 qd_k1_to;
00212 distort_wrt_k1( qd_k1_to, true_to_loc );
00213
00214
00215 vnl_matrix_fixed<double, 2, 9> qd_h = qd_qu * qu_h;
00216 vnl_double_2 qd_k1_from = qd_qu * qu_pu * pu_k1_from;
00217
00218
00219 vnl_matrix<double> jac(2, 11, 0.0);
00220
00221 jac(0,9) = qd_k1_from[0];
00222 jac(1,9) = qd_k1_from[1];
00223
00224
00225 jac(0,10) = qd_k1_to[0];
00226 jac(1,10) = qd_k1_to[1];
00227
00228
00229 for ( unsigned i=0; i<2; ++i )
00230 for ( unsigned j=0; j<9; ++j )
00231 jac(i, j) = qd_h(i,j);
00232
00233 return jac * covar_ * vnl_transpose( jac );
00234 }
00235
00236
00237 void
00238 rgrl_trans_rad_dis_homo2d::
00239 inv_map( const vnl_vector<double>& ,
00240 vnl_vector<double>& ) const
00241 {
00242 assert( ! "rgrl_trans_rad_dis_homo2d::inv_map( to, from ) is not implemented!!!" );
00243 }
00244
00245
00246 void
00247 rgrl_trans_rad_dis_homo2d::
00248 jacobian_wrt_loc( vnl_matrix<double>& jac, vnl_vector<double> const& from ) const
00249 {
00250
00251
00252
00253
00254 jac.set_size(2, 2);
00255
00256
00257 vnl_double_2 dis_from_loc( from[0]-from_centre_[0], from[1]-from_centre_[1] );
00258 vnl_double_2 true_from_loc;
00259
00260 distort( true_from_loc, dis_from_loc, k1_from_ );
00261 vnl_double_2x2 pu_pd;
00262 distort_wrt_loc( pu_pd, dis_from_loc, k1_from_ );
00263
00264
00265
00266 vnl_double_2 true_to_loc;
00267 map_inhomo_point( true_to_loc, H_, true_from_loc.as_ref() );
00268 vnl_double_2x2 qu_pu;
00269 homo_wrt_loc( qu_pu, H_, true_from_loc );
00270
00271
00272 vnl_double_2x2 qd_qu;
00273 distort_wrt_loc( qd_qu, true_to_loc, k1_to_ );
00274
00275
00276 jac = (qd_qu * qu_pu * pu_pd).as_ref();
00277 }
00278
00279 void
00280 rgrl_trans_rad_dis_homo2d::
00281 map_loc( vnl_vector<double> const& from,
00282 vnl_vector<double> & to ) const
00283 {
00284 to.set_size(2);
00285
00286
00287 vnl_double_2 dis_from_loc( from[0]-from_centre_[0], from[1]-from_centre_[1] );
00288 vnl_double_2 true_from_loc;
00289
00290 distort( true_from_loc, dis_from_loc, k1_from_ );
00291
00292
00293 vnl_double_2 true_to_loc;
00294 map_inhomo_point( true_to_loc, H_, true_from_loc.as_ref() );
00295
00296
00297 vnl_double_2 dis_to_loc;
00298 distort( dis_to_loc, true_to_loc, k1_to_ );
00299
00300
00301 to = (dis_to_loc + to_centre_).as_ref();
00302 }
00303
00304 void
00305 rgrl_trans_rad_dis_homo2d::
00306 map_dir( vnl_vector<double> const& from_loc,
00307 vnl_vector<double> const& from_dir,
00308 vnl_vector<double> & to_dir ) const
00309 {
00310 assert ( from_loc.size() == 2 );
00311 assert ( from_dir.size() == 2 );
00312 vnl_vector<double> to_loc_begin, to_loc_end;
00313 this->map_loc(from_loc, to_loc_begin);
00314 this->map_loc(from_loc+from_dir, to_loc_end);
00315
00316 to_dir = to_loc_end - to_loc_begin;
00317 to_dir.normalize();
00318 }
00319
00320 rgrl_transformation_sptr
00321 rgrl_trans_rad_dis_homo2d::
00322 scale_by( double scale ) const
00323 {
00324 vnl_matrix_fixed<double,3,3> new_H( H_ );
00325
00326
00327 new_H(0,2) *= scale;
00328 new_H(1,2) *= scale;
00329
00330
00331
00332 new_H(2,0) /= scale;
00333 new_H(2,1) /= scale;
00334
00335
00336 new_H /= new_H.fro_norm();
00337
00338
00339 vnl_vector_fixed<double,2> from = from_centre_ * scale;
00340 vnl_vector_fixed<double,2> to = to_centre_ * scale;
00341
00342
00343 const double sq_scale = scale*scale;
00344 double k1_from = k1_from_ / sq_scale;
00345 double k1_to = k1_to_ / sq_scale;
00346
00347 rgrl_transformation_sptr xform
00348 = new rgrl_trans_rad_dis_homo2d( new_H.as_ref(),
00349 k1_from, k1_to,
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 vnl_matrix_fixed<double, 3, 3>
00357 rgrl_trans_rad_dis_homo2d::
00358 uncenter_H_matrix( ) const
00359 {
00360 vnl_matrix_fixed<double, 3, 3> H;
00361
00362
00363 vnl_matrix_fixed<double, 3, 3> to_inv;
00364 to_inv.set_identity();
00365 to_inv(0,2) = to_centre_[0];
00366 to_inv(1,2) = to_centre_[1];
00367
00368
00369 vnl_matrix_fixed<double, 3, 3> from_matrix;
00370 from_matrix.set_identity();
00371 from_matrix(0,2) = -from_centre_[0];
00372 from_matrix(1,2) = -from_centre_[1];
00373
00374 H = to_inv * H_ * from_matrix;
00375
00376 return H;
00377 }
00378
00379 rgrl_transformation_sptr
00380 rgrl_trans_rad_dis_homo2d::
00381 inverse_transform( ) const
00382 {
00383 assert ( ! "rgrl_trans_quadratic::inverse_transform() is not defined" );
00384 return 0;
00385 }
00386
00387
00388 void
00389 rgrl_trans_rad_dis_homo2d::
00390 write(vcl_ostream& os ) const
00391 {
00392
00393
00394
00395 os << "HOMOGRAPHY2D_WITH_RADIAL_DISTORTION\n"
00396
00397 << 2 << vcl_endl
00398 << H_
00399 << from_centre_ << " " << to_centre_ << '\n'
00400 << k1_from_ << " " << k1_to_
00401 << vcl_endl;
00402
00403
00404 rgrl_transformation::write( os );
00405 }
00406
00407
00408 bool
00409 rgrl_trans_rad_dis_homo2d::
00410 read(vcl_istream& is )
00411 {
00412 int dim;
00413
00414
00415 rgrl_util_skip_empty_lines( is );
00416
00417 vcl_string str;
00418 vcl_getline( is, str );
00419
00420
00421 if ( str.find( "HOMOGRAPHY2D_WITH_RADIAL_DISTORTION" ) != 0 ) {
00422 WarningMacro( "The tag is not HOMOGRAPHY2D. reading is aborted.\n" );
00423 return false;
00424 }
00425
00426
00427 dim=-1;
00428 is >> dim;
00429 if ( dim > 0 ) {
00430 is >> H_ >> from_centre_ >> to_centre_ >> k1_from_ >> k1_to_;
00431 }
00432
00433
00434 return is.good() && rgrl_transformation::read( is );
00435 }
00436
00437
00438 rgrl_transformation_sptr
00439 rgrl_trans_rad_dis_homo2d::
00440 clone() const
00441 {
00442 return new rgrl_trans_rad_dis_homo2d( *this );
00443 }