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