00001
00002
00003
00004
00005
00006 #include "rgrl_est_similarity2d.h"
00007
00008 #include <vcl_cassert.h>
00009 #include <vnl/algo/vnl_svd.h>
00010 #include <vnl/vnl_math.h>
00011 #include <vnl/vnl_matrix_fixed.h>
00012 #include <vnl/vnl_vector_fixed.h>
00013 #include "rgrl_trans_similarity.h"
00014 #include "rgrl_match_set.h"
00015
00016 rgrl_est_similarity2d::
00017 rgrl_est_similarity2d( unsigned int dimension )
00018 {
00019 assert (dimension == 2);
00020
00021
00022 unsigned int param_dof = 2*dimension;
00023
00024
00025
00026 rgrl_estimator::set_param_dof( param_dof );
00027 }
00028
00029 rgrl_transformation_sptr
00030 rgrl_est_similarity2d::
00031 estimate( rgrl_set_of<rgrl_match_set_sptr> const& matches,
00032 rgrl_transformation const& ) const
00033 {
00034
00035
00036 typedef rgrl_match_set::const_from_iterator FIter;
00037 typedef FIter::to_iterator TIter;
00038
00039
00040
00041
00042 unsigned ms = 0;
00043 while ( ms < matches.size() &&
00044 matches[ms]->from_begin() == matches[ms]->from_end() )
00045 ++ms;
00046 if ( ms == matches.size() ) {
00047 DebugMacro( 0, "No data!\n" );
00048 return 0;
00049 }
00050 const unsigned int m = matches[ms]->from_begin().from_feature()->location().size();
00051 assert ( m==2 );
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 vnl_matrix_fixed<double, 4, 4> XtWX;
00064 vnl_vector_fixed<double, 4> XtWy;
00065 XtWX.fill( 0.0 );
00066 XtWy.fill( 0.0 );
00067
00068
00069
00070
00071 vnl_vector_fixed<double, 2> from_centre( 0.0, 0.0 );
00072 vnl_vector_fixed<double, 2> to_centre( 0.0, 0.0 );
00073 vnl_vector_fixed<double, 2> from_pt;
00074 vnl_vector_fixed<double, 2> to_pt;
00075 vnl_vector_fixed<double, 4> DtBq;
00076 vnl_matrix_fixed<double, 2, 4> D;
00077 vnl_matrix_fixed<double, 4, 2> Dt;
00078 vnl_matrix_fixed<double, 4, 2> DtB;
00079 double sum_wgt = 0.0;
00080 D.fill( 0.0 );
00081 Dt.fill( 0.0 );
00082 for ( unsigned ms=0; ms < matches.size(); ++ms ) {
00083 rgrl_match_set const& match_set = *matches[ms];
00084 for ( FIter fi = match_set.from_begin(); fi != match_set.from_end(); ++fi ) {
00085 for ( TIter ti = fi.begin(); ti != fi.end(); ++ti ) {
00086 double const wgt = ti.cumulative_weight();
00087 from_pt = fi.from_feature()->location();
00088 from_pt *= wgt;
00089 from_centre += from_pt;
00090 to_pt = ti.to_feature()->location();
00091 to_pt *= wgt;
00092 to_centre += to_pt;
00093 sum_wgt += wgt;
00094 }
00095 }
00096 }
00097
00098
00099 if ( sum_wgt < 1e-13 ) {
00100 return 0;
00101 }
00102
00103 from_centre /= sum_wgt;
00104 to_centre /= sum_wgt;
00105
00106
00107
00108 unsigned count=0;
00109 for ( unsigned ms=0; ms < matches.size(); ++ms ) {
00110 rgrl_match_set const& match_set = *matches[ms];
00111 for ( FIter fi = match_set.from_begin(); fi != match_set.from_end(); ++fi ) {
00112 for ( TIter ti = fi.begin(); ti != fi.end(); ++ti ) {
00113 from_pt = fi.from_feature()->location();
00114 from_pt -= from_centre;
00115 to_pt = ti.to_feature()->location();
00116 to_pt -= to_centre;
00117 vnl_matrix<double> const& B = ti.to_feature()->error_projector();
00118 double const wgt = ti.cumulative_weight();
00119
00120 assert( from_pt.size() == m );
00121 assert( to_pt.size() == m );
00122 assert( B.cols() == m && B.rows() == m );
00123 ++count;
00124
00125
00126 D(0,0) = from_pt[0]; D(0,1) = -from_pt[1]; D(0,2) = 1;
00127 D(1,0) = from_pt[1]; D(1,1) = from_pt[0]; D(1,3) = 1;
00128
00129 Dt(0,0) = from_pt[0]; Dt(1,0) = -from_pt[1]; Dt(2,0) = 1;
00130 Dt(0,1) = from_pt[1]; Dt(1,1) = from_pt[0]; Dt(3,1) = 1;
00131
00132 DtB = Dt * B;
00133 XtWX += (DtB * D) * wgt;
00134
00135
00136
00137 DtBq = DtB * to_pt;
00138 for ( unsigned i = 0; i<4; ++i)
00139 XtWy[i] += wgt * DtBq[i];
00140 }
00141 }
00142 }
00143
00144
00145
00146 double factor0 = vnl_math_max(XtWX(2,2),XtWX(3,3));
00147 double factor1 = vnl_math_max(XtWX(1,1),XtWX(0,0));
00148 double scale = vcl_sqrt( (factor1 > 0 && factor0 > 0) ? factor1 / factor0 : 1 );
00149
00150 vnl_vector_fixed<double, 4> s;
00151 s(2) = s(3) = scale; s(0) = s(1) = 1;
00152 for ( int i=0; i<4; i++ ) {
00153 XtWy(i) *= s(i);
00154 for ( int j=0; j<4; j++ )
00155 XtWX(i,j) *= s(i) * s(j);
00156 }
00157
00158
00159
00160
00161
00162 vnl_svd<double> svd( XtWX.as_ref() );
00163
00164
00165
00166 svd.zero_out_relative();
00167
00168 if ( (unsigned)svd.rank() < 4) {
00169 DebugMacro(1, "rank ("<<svd.rank()<<") < 4; no solution." );
00170 DebugMacro_abv(1, "(used " << count << " correspondences)\n" );
00171 return 0;
00172 }
00173
00174
00175
00176 vnl_matrix_fixed<double, 4, 4> covar = svd.inverse();
00177 XtWy = covar * XtWy;
00178
00179
00180
00181 for ( int i=0; i<4; i++ ) {
00182 for ( int j=0; j<4; j++ )
00183 covar(i,j) *= s(i) * s(j);
00184 }
00185 for ( int i=0; i<4; i++ ) {
00186 XtWy(i) *= s(i);
00187 }
00188
00189
00190
00191
00192
00193 vnl_vector<double> trans( m );
00194 trans[0] = XtWy[2];
00195 trans[1] = XtWy[3];
00196
00197
00198 vnl_matrix<double> A( m, m );
00199 A(0,0) = A(1,1) = XtWy[0];
00200 A(0,1) = -XtWy[1];
00201 A(1,0) = -A(0,1);
00202
00203 return new rgrl_trans_similarity( A, trans, covar.as_ref(), from_centre.as_ref(), to_centre.as_ref() );
00204 }
00205
00206
00207 rgrl_transformation_sptr
00208 rgrl_est_similarity2d::
00209 estimate( rgrl_match_set_sptr matches,
00210 rgrl_transformation const& cur_transform ) const
00211 {
00212
00213 return rgrl_estimator::estimate( matches, cur_transform );
00214 }
00215
00216 const vcl_type_info&
00217 rgrl_est_similarity2d::
00218 transformation_type() const
00219 {
00220 return rgrl_trans_similarity::type_id();
00221 }