00001
00002
00003
00004
00005
00006 #include "rgrl_est_rigid.h"
00007
00008 #include <vcl_cassert.h>
00009 #include <vnl/algo/vnl_svd.h>
00010 #include <vnl/algo/vnl_determinant.h>
00011 #if 0
00012 #include <vnl/algo/vnl_matrix_inverse.h>
00013 #endif
00014 #include "rgrl_trans_rigid.h"
00015 #include "rgrl_match_set.h"
00016
00017 rgrl_est_rigid::
00018 rgrl_est_rigid( unsigned int dimension )
00019 {
00020
00021 assert(dimension == 2 || dimension == 3);
00022
00023 unsigned int param_dof = (dimension == 3)?6 : 3;
00024
00025
00026
00027 rgrl_estimator::set_param_dof( param_dof );
00028 }
00029
00030 rgrl_transformation_sptr
00031 rgrl_est_rigid::
00032 estimate( rgrl_set_of<rgrl_match_set_sptr> const& matches,
00033 rgrl_transformation const& cur_trans_in ) const
00034 {
00035
00036 const rgrl_trans_rigid* cur_trans =
00037 dynamic_cast<const rgrl_trans_rigid*>(&cur_trans_in);
00038 assert(cur_trans);
00039
00040
00041
00042 vcl_vector<vcl_vector<double> >* pp =
00043 const_cast<vcl_vector<vcl_vector<double> >* >(&stats);
00044
00045
00046 pp->clear();
00047 vcl_vector<double> cur_stat;
00048
00049
00050 rgrl_transformation_sptr current_trans =
00051 new rgrl_trans_rigid(cur_trans->R(), cur_trans->t());
00052
00053
00054
00055 typedef rgrl_match_set::const_from_iterator FIter;
00056 typedef FIter::to_iterator TIter;
00057
00058
00059
00060
00061 unsigned ms = 0;
00062 while ( ms < matches.size() &&
00063 matches[ms]->from_begin() == matches[ms]->from_end() )
00064 ++ms;
00065 if ( ms == matches.size() ) {
00066 DebugMacro( 0, "No data!\n" );
00067 return 0;
00068 }
00069 const unsigned int m = matches[ms]->from_begin().from_feature()->location().size();
00070 assert ( m==3 );
00071
00072 int numiterations = 1;
00073 do
00074 {
00075 cur_stat.clear();
00076
00077
00078
00079
00080
00081
00082
00083 vnl_matrix<double> XtWX( 6, 6 );
00084 vnl_vector<double> XtWy( 6 );
00085 XtWX.fill( 0.0 );
00086 XtWy.fill( 0.0 );
00087
00088 unsigned count=0;
00089
00090 vnl_vector<double> from_pt( m );
00091 vnl_vector<double> to_pt( m );
00092 for (unsigned int ms=0; ms < matches.size(); ++ms )
00093 {
00094 rgrl_match_set const& match_set = *matches[ms];
00095 for (FIter fi = match_set.from_begin(); fi != match_set.from_end(); ++fi )
00096 {
00097 for (TIter ti = fi.begin(); ti != fi.end(); ++ti )
00098 {
00099 from_pt = fi.from_feature()->location();
00100 to_pt = ti.to_feature()->location();
00101 vnl_matrix<double> const& B = ti.to_feature()->error_projector();
00102
00103 double const wgt = ti.cumulative_weight();
00104
00105 assert( from_pt.size() == m );
00106 assert( to_pt.size() == m );
00107 assert( B.cols() == m && B.rows() == m );
00108 ++count;
00109
00110
00111 vnl_matrix<double> XX(3,6,0.0);
00112 vnl_vector<double> RR(3,0.0);
00113
00114 vnl_vector<double> g(current_trans->map_location(from_pt));
00115 vnl_vector<double> f(to_pt);
00116
00117 XX(0,0)=0; XX(0,1)=g[2]; XX(0,2)=-g[1]; XX(0,3)=1;
00118 XX(1,0)=-g[2]; XX(1,1)=0; XX(1,2)=g[0]; XX(1,4)=1;
00119 XX(2,0)=g[1]; XX(2,1)=-g[0]; XX(2,2)=0; XX(2,5)=1;
00120
00121 RR=f-g;
00122
00123 XtWX+=XX.transpose()*B*XX*wgt;
00124 XtWy+=XX.transpose()*B*RR*wgt;
00125
00126
00127
00128 }
00129 }
00130 }
00131
00132
00133
00134
00135
00136 vnl_svd<double> svd( XtWX );
00137
00138
00139
00140 svd.zero_out_relative();
00141
00142
00143 if ( (unsigned)svd.rank() < m ) {
00144 DebugMacro(1, "rank ("<<svd.rank()<<") < "<<m<<"; no solution." );
00145 DebugMacro_abv(1, "(used " << count << " correspondences)\n" );
00146 return 0;
00147 }
00148
00149
00150
00151 vnl_matrix<double> covar = svd.inverse();
00152 XtWy.pre_multiply( covar );
00153
00154
00155
00156
00157
00158 vnl_vector<double> trans( m );
00159 trans[0]=XtWy[3];
00160 trans[1]=XtWy[4];
00161 trans[2]=XtWy[5];
00162
00163
00164
00165
00166 vnl_matrix<double> R( m, m );
00167 R(0,0)=1.0; R(0,1)=-XtWy[2]; R(0,2)=XtWy[1];
00168 R(1,0)=XtWy[2]; R(1,1)=1.0; R(1,2)=-XtWy[0];
00169 R(2,0)=-XtWy[1]; R(2,1)=XtWy[0]; R(2,2)=1.0;
00170
00171
00172
00173
00174 cur_stat.push_back(vnl_determinant(R));
00175 DebugMacro_abv(2, "about to orthonormalize with determinant "<<vnl_determinant(R)<<vcl_endl);
00176 vnl_svd<double> svdR( R );
00177
00178
00179 double scale = 1;
00180 svdR.W(0) = scale;
00181 svdR.W(1) = scale;
00182 svdR.W(2) = scale;
00183 R = svdR.recompose();
00184
00185
00186 rgrl_trans_rigid* old_sim = dynamic_cast<rgrl_trans_rigid* >( current_trans.as_pointer() );
00187 double fro_norm2 = trans.magnitude();
00188 trans += R * old_sim->t();
00189
00190 vnl_matrix<double> I(3,3,vnl_matrix_identity);
00191 I -= R;
00192
00193 double fro_norm1 = I.frobenius_norm();
00194
00195 #ifdef DEBUG
00196 vcl_cerr<<"fro_norm of deltaT,deltatrans is "<<fro_norm1<<','<<fro_norm2<<vcl_endl;
00197 #endif
00198
00199 cur_stat.push_back(fro_norm1);
00200 cur_stat.push_back(fro_norm2);
00201
00202
00203
00204
00205 R *= old_sim->R();
00206
00207 current_trans = new rgrl_trans_rigid(R,trans,covar);
00208
00209
00210 pp->push_back(cur_stat);
00211
00212
00213
00214
00215
00216 if (fro_norm1<1e-2 && fro_norm2<1e-1)
00217 {
00218
00219 break;
00220 }
00221
00222
00223
00224
00225
00226 numiterations++;
00227 } while (true);
00228
00229
00230 vnl_matrix<double> covar(3,3,vnl_matrix_identity);
00231
00232
00233
00234
00235 return current_trans;
00236
00237
00238 }
00239
00240
00241 void rgrl_est_rigid::determine_covariance( rgrl_set_of<rgrl_match_set_sptr> const& matches,
00242 rgrl_transformation_sptr current_trans) const
00243 {
00244
00245 double alpha,theta,phi;
00246
00247 rgrl_trans_rigid* tttt = dynamic_cast<rgrl_trans_rigid*>(current_trans.ptr());
00248
00249 assert(tttt);
00250 tttt->determine_angles(phi,alpha,theta);
00251
00252 vnl_vector<double> t = tttt->t();
00253
00254
00255 vnl_matrix<double> Rphi(3,3,0.0);
00256 vnl_matrix<double> Ralpha(3,3,0.0);
00257 vnl_matrix<double> Rtheta(3,3,0.0);
00258 vnl_matrix<double> Rphid(3,3,0.0);
00259 vnl_matrix<double> Ralphad(3,3,0.0);
00260 vnl_matrix<double> Rthetad(3,3,0.0);
00261
00262 vnl_matrix<double> Rphidd(3,3,0.0);
00263 vnl_matrix<double> Ralphadd(3,3,0.0);
00264 vnl_matrix<double> Rthetadd(3,3,0.0);
00265
00266
00267 Rtheta(0,0) = vcl_cos(theta);
00268 Rtheta(0,1) = -vcl_sin(theta);
00269 Rtheta(1,0) = vcl_sin(theta);
00270 Rtheta(1,1) = vcl_cos(theta);
00271 Rtheta(2,2) = 1;
00272
00273 Ralpha(0,0) = vcl_cos(alpha);
00274 Ralpha(0,2) = vcl_sin(alpha);
00275 Ralpha(1,1) = 1;
00276 Ralpha(2,0) = -vcl_sin(alpha);
00277 Ralpha(2,2) = vcl_cos(alpha);
00278
00279 Rphi(0,0) = 1;
00280 Rphi(1,1) = vcl_cos(phi);
00281 Rphi(1,2) = -vcl_sin(phi);
00282 Rphi(2,1) = vcl_sin(phi);
00283 Rphi(2,2) = vcl_cos(phi);
00284
00285
00286 Rthetad(0,0) = -vcl_sin(theta);
00287 Rthetad(0,1) = -vcl_cos(theta);
00288 Rthetad(1,0) = vcl_cos(theta);
00289 Rthetad(1,1) = -vcl_sin(theta);
00290
00291 Ralphad(0,0) = -vcl_sin(alpha);
00292 Ralphad(0,2) = vcl_cos(alpha);
00293 Ralphad(2,0) = -vcl_cos(alpha);
00294 Ralphad(2,2) = -vcl_sin(alpha);
00295
00296 Rphid(1,1) = -vcl_sin(phi);
00297 Rphid(1,2) = -vcl_cos(phi);
00298 Rphid(2,1) = vcl_cos(phi);
00299 Rphid(2,2) = -vcl_sin(phi);
00300
00301
00302 Rthetadd(0,0) = -vcl_cos(theta);
00303 Rthetadd(0,1) = vcl_sin(theta);
00304 Rthetadd(1,0) = -vcl_sin(theta);
00305 Rthetadd(1,1) = -vcl_cos(theta);
00306
00307 Ralphadd(0,0) = -vcl_cos(alpha);
00308 Ralphadd(0,2) = -vcl_sin(alpha);
00309 Ralphadd(2,0) = vcl_sin(alpha);
00310 Ralphadd(2,2) = -vcl_cos(alpha);
00311
00312 Rphidd(1,1) = -vcl_cos(phi);
00313 Rphidd(1,2) = vcl_sin(phi);
00314 Rphidd(2,1) = -vcl_sin(phi);
00315 Rphidd(2,2) = -vcl_cos(phi);
00316
00317
00318
00319 vnl_matrix<double> R = Rphi * Ralpha * Rtheta;
00320 vnl_matrix<double> dRdphi = Rphid * Ralpha * Rtheta;
00321 vnl_matrix<double> dRdalpha = Rphi * Ralphad * Rtheta;
00322 vnl_matrix<double> dRdtheta = Rphi * Ralpha * Rthetad;
00323
00324 vnl_matrix<double> d2Rdphidtheta = Rphid * Ralpha * Rthetad;
00325 vnl_matrix<double> d2Rdphidalpha = Rphid * Ralphad * Rtheta;
00326 vnl_matrix<double> d2Rdthetadalpha = Rphi * Ralphad * Rthetad;
00327
00328
00329 vnl_matrix<double> d2Rdphi2 = Rphidd * Ralpha * Rtheta;
00330 vnl_matrix<double> d2Rdalpha2 = Rphi * Ralphadd * Rtheta;
00331 vnl_matrix<double> d2Rdtheta2 = Rphi * Ralpha * Rthetadd;
00332
00333
00334
00335
00336 vnl_matrix<double> Htt(3,3,0.0);
00337 vnl_matrix<double> Hoo(3,3,0.0);
00338 vnl_matrix<double> Hot(3,3,0.0);
00339
00340 const unsigned m = 3;
00341
00342 vnl_vector<double> from_pt( m );
00343 vnl_vector<double> to_pt( m );
00344
00345 typedef rgrl_match_set::const_from_iterator FIter;
00346 typedef FIter::to_iterator TIter;
00347
00348
00349 for (unsigned int ms=0; ms < matches.size(); ++ms )
00350 {
00351 rgrl_match_set const& match_set = *matches[ms];
00352 for (FIter fi = match_set.from_begin(); fi != match_set.from_end(); ++fi )
00353 {
00354 for (TIter ti = fi.begin(); ti != fi.end(); ++ti )
00355 {
00356 from_pt = fi.from_feature()->location();
00357 to_pt = ti.to_feature()->location();
00358 vnl_matrix<double> const& B = ti.to_feature()->error_projector();
00359 double const wgt = ti.cumulative_weight();
00360
00361 Htt = Htt + wgt*2*B;
00362 Hot.set_row(0,Hot.get_row(0) + wgt*2*(B*dRdtheta*from_pt));
00363 Hot.set_row(1,Hot.get_row(1) + wgt*2*(B*dRdalpha*from_pt));
00364 Hot.set_row(2,Hot.get_row(2) + wgt*2*(B*dRdphi*from_pt));
00365
00366
00367 Hoo(0,0) = Hoo(0,0) + wgt*2* (
00368 inner_product ((t - to_pt), B * d2Rdtheta2 * from_pt) +
00369 inner_product (from_pt , ( dRdtheta.transpose() * B * dRdtheta + R.transpose()*B*d2Rdtheta2) * from_pt ));
00370
00371 Hoo(1,1) = Hoo(1,1) + wgt*2* (
00372 inner_product ((t - to_pt), B * d2Rdalpha2 * from_pt) +
00373 inner_product (from_pt , ( dRdalpha.transpose() * B * dRdalpha + R.transpose()*B*d2Rdalpha2) * from_pt ));
00374
00375 Hoo(2,2) = Hoo(2,2) + wgt*2* (
00376 inner_product ((t - to_pt), B * d2Rdphi2 * from_pt) +
00377 inner_product (from_pt , ( dRdphi.transpose() * B * dRdphi+ R.transpose()*B*d2Rdphi2) * from_pt ));
00378
00379 Hoo(0,1) = Hoo(0,1) + wgt*2* (
00380 inner_product ((t - to_pt), B * d2Rdthetadalpha * from_pt) +
00381 inner_product (from_pt , ( dRdtheta.transpose() * B * dRdalpha + R.transpose()*B*d2Rdthetadalpha) * from_pt ));
00382
00383
00384 Hoo(0,2) = Hoo(0,2) + wgt*2* (
00385 inner_product ((t - to_pt), B * d2Rdphidtheta * from_pt) +
00386 inner_product (from_pt , ( dRdtheta.transpose() * B * dRdphi + R.transpose()*B*d2Rdphidtheta) * from_pt ));
00387
00388 Hoo(1,2) = Hoo(1,2) + wgt*2* (
00389 inner_product ((t - to_pt), B * d2Rdphidalpha * from_pt) +
00390 inner_product (from_pt , ( dRdalpha.transpose() * B * dRdphi + R.transpose()*B*d2Rdphidalpha) * from_pt ));
00391 }
00392 }
00393 }
00394
00395 Hoo(1,0) = Hoo(0,1);
00396 Hoo(2,0) = Hoo(0,2);
00397 Hoo(2,1) = Hoo(1,2);
00398
00399 vnl_matrix<double> hessian(6,6,0.0);
00400
00401
00402
00403
00404 hessian.update(Hoo,0,0);
00405 hessian.update(Htt,3,3);
00406 hessian.update(Hot,0,3);
00407 hessian.update(Hot.transpose(),3,0);
00408
00409 #if 0
00410 vnl_matrix<double> covar = vnl_matrix_inverse<double>(hessian);
00411 #endif
00412
00413 vnl_svd<double> svd(hessian);
00414
00415 vnl_matrix<double> covar = svd.inverse();
00416
00417 rgrl_trans_rigid* rigid = dynamic_cast<rgrl_trans_rigid*>(current_trans.ptr());
00418
00419 current_trans = new rgrl_trans_rigid(rigid->R(),rigid->t(),covar);
00420 }
00421
00422
00423 rgrl_transformation_sptr
00424 rgrl_est_rigid::
00425 estimate( rgrl_match_set_sptr matches,
00426 rgrl_transformation const& cur_transform ) const
00427 {
00428
00429 return rgrl_estimator::estimate( matches, cur_transform );
00430 }
00431
00432 const vcl_type_info&
00433 rgrl_est_rigid::
00434 transformation_type() const
00435 {
00436 return rgrl_trans_rigid::type_id();
00437 }