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