00001
00002
00003
00004
00005
00006 #include "rgrl_est_quadratic.h"
00007
00008 #include <vcl_cassert.h>
00009 #include <vnl/algo/vnl_svd.h>
00010 #include <vnl/vnl_math.h>
00011 #include "rgrl_trans_quadratic.h"
00012 #include "rgrl_match_set.h"
00013
00014 rgrl_est_quadratic::
00015 rgrl_est_quadratic()
00016 : condition_num_thrd_( 0.0 )
00017 {}
00018
00019 rgrl_est_quadratic::
00020 rgrl_est_quadratic( unsigned int dimension,
00021 double condition_num_thrd )
00022 : condition_num_thrd_( condition_num_thrd )
00023
00024 {
00025
00026
00027 unsigned int param_dof = (dimension == 2)? 12 : 30;
00028
00029
00030
00031 rgrl_estimator::set_param_dof( param_dof );
00032 }
00033
00034 rgrl_transformation_sptr
00035 rgrl_est_quadratic::
00036 estimate( rgrl_set_of<rgrl_match_set_sptr> const& matches,
00037 rgrl_transformation const& ) const
00038 {
00039
00040
00041 typedef rgrl_match_set::const_from_iterator FIter;
00042 typedef FIter::to_iterator TIter;
00043
00044
00045
00046
00047 unsigned ms = 0;
00048 while( ms < matches.size() &&
00049 matches[ms]->from_begin() == matches[ms]->from_end() )
00050 ++ms;
00051 if( ms == matches.size() ) {
00052 DebugMacro( 0, "No data!\n" );
00053 return 0;
00054 }
00055 const unsigned int m = matches[ms]->from_begin().from_feature()->location().size();
00056 assert ( m==3 || m==2 );
00057
00058
00059
00060
00061
00062
00063
00064
00065 unsigned p_size = 1+ 2*m + m*(m-1)/2;
00066 vnl_matrix<double> ptp( p_size, p_size );
00067
00068 vnl_vector<double> Bq( m );
00069
00070
00071
00072
00073
00074
00075
00076 vnl_matrix<double> XtWX( m*p_size, m*p_size );
00077 vnl_vector<double> XtWy( m*p_size );
00078 XtWX.fill( 0.0 );
00079 XtWy.fill( 0.0 );
00080
00081
00082
00083
00084 vnl_vector<double> from_centre( m, 0.0 );
00085 vnl_vector<double> to_centre( m, 0.0 );
00086 vnl_vector<double> from_pt( m );
00087 vnl_vector<double> to_pt( m );
00088 double sum_wgt = 0.0;
00089 for( unsigned ms=0; ms < matches.size(); ++ms ) {
00090 rgrl_match_set const& match_set = *matches[ms];
00091 for( FIter fi = match_set.from_begin(); fi != match_set.from_end(); ++fi ) {
00092 for( TIter ti = fi.begin(); ti != fi.end(); ++ti ) {
00093 double const wgt = ti.cumulative_weight();
00094 from_pt = fi.from_feature()->location();
00095 from_pt *= wgt;
00096 from_centre += from_pt;
00097 to_pt = ti.to_feature()->location();
00098 to_pt *= wgt;
00099 to_centre += to_pt;
00100 sum_wgt += wgt;
00101 }
00102 }
00103 }
00104 from_centre /= sum_wgt;
00105 to_centre /= sum_wgt;
00106
00107
00108
00109 if( sum_wgt < 1e-13 ) {
00110 return 0;
00111 }
00112
00113
00114
00115
00116
00117
00118 unsigned count=0;
00119 vnl_vector<double> p (p_size);
00120 for( unsigned ms=0; ms < matches.size(); ++ms ) {
00121 rgrl_match_set const& match_set = *matches[ms];
00122 for( FIter fi = match_set.from_begin(); fi != match_set.from_end(); ++fi ) {
00123 for( TIter ti = fi.begin(); ti != fi.end(); ++ti ) {
00124 from_pt = fi.from_feature()->location();
00125 from_pt -= from_centre;
00126 to_pt = ti.to_feature()->location();
00127 to_pt -= to_centre;
00128 vnl_matrix<double> const& B = ti.to_feature()->error_projector();
00129 double const wgt = ti.cumulative_weight();
00130
00131 assert( from_pt.size() == m );
00132 assert( to_pt.size() == m );
00133 assert( B.cols() == m && B.rows() == m );
00134 ++count;
00135
00136
00137
00138 if (m == 3) {
00139 p[0] = vnl_math_sqr(from_pt[0]);
00140 p[1] = vnl_math_sqr(from_pt[1]);
00141 p[2] = vnl_math_sqr(from_pt[2]);
00142 p[3] = from_pt[0]*from_pt[1];
00143 p[4] = from_pt[1]*from_pt[2];
00144 p[5] = from_pt[0]*from_pt[2];
00145 p[6] = from_pt[0];
00146 p[7] = from_pt[1];
00147 p[8] = from_pt[2];
00148 p[9] = 1;
00149 }
00150 else {
00151 p[0] = vnl_math_sqr(from_pt[0]);
00152 p[1] = vnl_math_sqr(from_pt[1]);
00153 p[2] = from_pt[0]*from_pt[1];
00154 p[3] = from_pt[0];
00155 p[4] = from_pt[1];
00156 p[5] = 1;
00157 }
00158 for( unsigned i=0; i < p_size; ++i ) {
00159 for( unsigned j=0; j < p_size; ++j ) {
00160 ptp(i,j) = p[i] * p[j];
00161 }
00162 }
00163
00164
00165
00166 for( unsigned i=0; i < m; ++i ) {
00167 for( unsigned j=i; j < m; ++j ) {
00168 if( B(i,j) != 0.0 ) {
00169 double wBij = wgt * B(i,j);
00170 unsigned off_r = i*p_size;
00171 unsigned off_c = j*p_size;
00172 for( unsigned r=0; r < p_size; ++r ) {
00173 for( unsigned c=0; c < p_size; ++c ) {
00174 XtWX(off_r+r,off_c+c) += wBij * ptp(r,c);
00175 }
00176 }
00177 }
00178 }
00179 }
00180
00181
00182
00183 Bq = B * to_pt;
00184 for( unsigned i=0; i < m; ++i ) {
00185 double wBqi = wgt * Bq[i];
00186 unsigned off = i*p_size;
00187 for( unsigned j=0; j < p_size; ++j ) {
00188 XtWy[off+j] += wBqi * p[j];
00189 }
00190 }
00191 }
00192 }
00193 }
00194
00195
00196
00197
00198 for( unsigned i=0; i < m*p_size; ++i ) {
00199 for( unsigned j=0; j < i; ++j ) {
00200 XtWX(i,j) = XtWX(j,i);
00201 }
00202 }
00203
00204
00205
00206
00207 double factor0, factor1, factor2;
00208 vnl_vector<double> s(p_size*m, 1);
00209 if (m == 2) {
00210 factor0 = vnl_math_max(XtWX(5,5), XtWX(11,11));
00211 factor1 = vnl_math_max(vnl_math_max(XtWX(3,3), XtWX(4,4)),
00212 vnl_math_max(XtWX(10,10), XtWX(9,9)));
00213 factor2 = vnl_math_max(vnl_math_max(XtWX(0,0), XtWX(1,1)),
00214 vnl_math_max(XtWX(6,6), XtWX(7,7)));
00215
00216 double scale0 = vcl_sqrt( (factor0 > 0 && factor2 > 0) ? factor2 / factor0 : 1 );
00217 double scale1 = vcl_sqrt( (factor1 > 0 && factor2 > 0) ? factor2 / factor1 : 1 );
00218
00219 s(3) = s(4) = s(9) = s(10) = scale1;
00220 s(5) = s(11) = scale0;
00221 }
00222 else {
00223 factor0 = vnl_math_max( vnl_math_max(XtWX(9,9), XtWX(19,19)),
00224 XtWX(29,29));
00225 factor1 = max_of_9_elements( XtWX(6,6), XtWX(7,7), XtWX(8,8),
00226 XtWX(16,16), XtWX(17,17), XtWX(18,18),
00227 XtWX(26,26), XtWX(27,27), XtWX(28,28) );
00228 factor2 = max_of_9_elements( XtWX(0,0), XtWX(1,1), XtWX(2,2),
00229 XtWX(10,10), XtWX(11,11), XtWX(12,12),
00230 XtWX(20,20), XtWX(21,21), XtWX(22,22) );
00231
00232 double scale0 = vcl_sqrt( (factor0 > 0 && factor2 > 0) ? factor2 / factor0 : 1 );
00233 double scale1 = vcl_sqrt( (factor1 > 0 && factor2 > 0) ? factor2 / factor1 : 1 );
00234
00235 s(6) = s(7) = s(8) = s(16) = s(17) = s(18) = s(26) = s(27) = s(28) = scale1;
00236 s(9) = s(19) = s(29) = scale0;
00237 }
00238
00239 for ( unsigned i=0; i<p_size*m; i++ ) {
00240 XtWy(i) *= s(i);
00241 for ( unsigned j=0; j<p_size*m; j++ )
00242 XtWX(i,j) *= s(i) * s(j);
00243 }
00244
00245
00246
00247
00248
00249 vnl_svd<double> svd( XtWX, 1e-5);
00250
00251
00252
00253
00254
00255 if( (unsigned)svd.rank() < p_size*m ) {
00256 DebugMacro(1, "rank ("<<svd.rank()<<") < "<<p_size*m<<"; no solution." );
00257 DebugMacro_abv(1,"(used " << count << " correspondences)\n" );
00258 return 0;
00259 }
00260 double cond_num = svd.well_condition();
00261 if ( condition_num_thrd_ > cond_num ) {
00262 DebugMacro(1, "Unstable xform with condition number = "<<cond_num<<"\n" );
00263 return 0;
00264 }
00265
00266
00267
00268 vnl_matrix<double> covar = svd.inverse();
00269 XtWy.pre_multiply( covar );
00270
00271
00272
00273 for ( unsigned i=0; i<p_size*m; i++ ) {
00274 for ( unsigned j=0; j<p_size*m; j++ )
00275 covar(i,j) *= s(i) * s(j);
00276 }
00277 for ( unsigned i=0; i<p_size*m; i++ ) {
00278 XtWy(i) *= s(i);
00279 }
00280
00281
00282
00283
00284
00285 vnl_vector<double> trans( m );
00286 for( unsigned i=0; i < m; ++i ) {
00287 trans[i] = XtWy[ i*p_size + (p_size-1) ];
00288 }
00289
00290
00291 unsigned Q_size = m + m*(m-1)/2;
00292 vnl_matrix<double> Q( m, Q_size );
00293 for( unsigned i=0; i < m; ++i ) {
00294 for( unsigned j=0; j < Q_size; ++j ) {
00295 Q(i,j) = XtWy[ i*p_size+j ];
00296 }
00297 }
00298
00299
00300 vnl_matrix<double> A( m, m );
00301 for( unsigned i=0; i < m; ++i ) {
00302 for( unsigned j=0; j < m; ++j ) {
00303 A(i,j) = XtWy[ i*p_size + (Q_size+j) ];
00304 }
00305 }
00306
00307 return new rgrl_trans_quadratic( Q, A, trans, covar, from_centre, to_centre );
00308 }
00309
00310
00311 rgrl_transformation_sptr
00312 rgrl_est_quadratic::
00313 estimate( rgrl_match_set_sptr matches,
00314 rgrl_transformation const& cur_transform ) const
00315 {
00316
00317 return rgrl_estimator::estimate( matches, cur_transform );
00318 }
00319
00320 const vcl_type_info&
00321 rgrl_est_quadratic::
00322 transformation_type() const
00323 {
00324 return rgrl_trans_quadratic::type_id();
00325 }
00326
00327 double
00328 rgrl_est_quadratic::
00329 max_of_9_elements(double elt1, double elt2, double elt3,
00330 double elt4, double elt5, double elt6,
00331 double elt7, double elt8, double elt9 ) const
00332 {
00333 double max = vnl_math_max( elt1, vnl_math_max( elt2, elt3 ) );
00334 max = vnl_math_max ( max, vnl_math_max( elt4, elt5 ) );
00335 max = vnl_math_max ( max, vnl_math_max( elt6, elt7 ) );
00336 return vnl_math_max ( max, vnl_math_max( elt8, elt9 ) );
00337 }