contrib/gel/mrc/vpgl/algo/vpgl_fm_compute_affine_ransac.cxx
Go to the documentation of this file.
00001 // This is gel/mrc/vpgl/algo/vpgl_fm_compute_affine_ransac.cxx
00002 #ifndef vpgl_fm_compute_affine_ransac_cxx_
00003 #define vpgl_fm_compute_affine_ransac_cxx_
00004 
00005 #include "vpgl_fm_compute_affine_ransac.h"
00006 
00007 #include <vcl_iostream.h>
00008 #include <vcl_cassert.h>
00009 #include <vcl_cmath.h>
00010 #include <vgl/vgl_point_2d.h>
00011 #include <vgl/vgl_homg_point_2d.h>
00012 #include <vgl/vgl_homg_line_2d.h>
00013 #include <vgl/algo/vgl_homg_operators_2d.h>
00014 #include <vnl/algo/vnl_svd.h>
00015 #include <rrel/rrel_ran_sam_search.h>
00016 #include <rrel/rrel_muset_obj.h>
00017 
00018 
00019 //------------------------------------------
00020 bool
00021 vpgl_fm_compute_affine_ransac::compute(
00022   const vcl_vector< vgl_point_2d<double> >& pr,
00023   const vcl_vector< vgl_point_2d<double> >& pl,
00024   vpgl_affine_fundamental_matrix<double>& fm )
00025 {
00026   // Check that there are at least 5 points.
00027   if ( pr.size() < 4 || pl.size() < 4 ){
00028     vcl_cerr << "vpgl_fm_compute_ransac: Need at least 4 point pairs.\n"
00029              << "Number in each set: " << pr.size() << ", " << pl.size() << vcl_endl;
00030     return false;
00031   }
00032 
00033   // Check that the correspondence lists are the same size.
00034   if ( pr.size() != pl.size() ){
00035     vcl_cerr << "vpgl_fm_compute_affine_ransac: Need correspondence lists of same size.\n";
00036     return false;
00037   }
00038 
00039   // The following block is hacked from similar code in rrel_homography2d_est.
00040   rrel_fm_affine_problem* estimator = new rrel_fm_affine_problem( pr, pl );
00041   rrel_muset_obj* ransac = new rrel_muset_obj((int)vcl_floor(pr.size()*.75));
00042   estimator->set_prior_scale( 1.0 );
00043   rrel_ran_sam_search* ransam = new rrel_ran_sam_search;
00044   ransam->set_trace_level(params_->trace_level);
00045   ransam->set_sampling_params( params_->max_outlier_frac,
00046                                params_->desired_prob_good,
00047                                params_->max_pops );
00048   bool ransac_succeeded = ransam->estimate( estimator, ransac );
00049 
00050   if ( ransac_succeeded )
00051   estimator->params_to_fm( ransam->params(), fm );
00052 
00053   // Get a list of the outliers.
00054   vcl_vector<double> residuals;
00055   estimator->compute_residuals( ransam->params(), residuals );
00056 
00057   outliers = vcl_vector<bool>();
00058   for ( unsigned i = 0; i < pr.size(); i++ ){
00059     if ( residuals[i] > params_->residual_thresh )
00060       outliers.push_back( true );
00061     else
00062       outliers.push_back( false );
00063   }
00064 
00065   delete ransac;
00066   delete ransam;
00067   delete estimator;
00068 
00069   return ransac_succeeded;
00070 }
00071 
00072 
00073 //------------------------------------------
00074 vpgl_fm_compute_affine_ransac_params::vpgl_fm_compute_affine_ransac_params() :
00075   max_outlier_frac(0.5),
00076   desired_prob_good(0.99),
00077   max_pops(1),
00078   trace_level(0),
00079   residual_thresh(1)
00080 {
00081 }
00082 
00083 
00084 //------------------------------------------
00085 rrel_fm_affine_problem::rrel_fm_affine_problem(
00086   const vcl_vector< vgl_point_2d<double> >& pr,
00087   const vcl_vector< vgl_point_2d<double> >& pl ) :
00088   rrel_estimation_problem(4,4)
00089 {
00090   assert( pr.size() == pl.size() );
00091 
00092   for ( unsigned int i=0; i < pr.size(); i++ )
00093   {
00094     pr_.push_back( pr[i] );
00095     pl_.push_back( pl[i] );
00096   }
00097 }
00098 
00099 
00100 //------------------------------------------
00101 bool
00102 rrel_fm_affine_problem::fit_from_minimal_set(
00103   const vcl_vector<int>& point_indices,
00104   vnl_vector<double>& params ) const
00105 {
00106   if ( verbose ) vcl_cerr << "rrel_fm_affine_problem::fit_from_minimal_set\n";
00107   assert( point_indices.size() == 4 );
00108 
00109   vnl_matrix<double> S(4,5);
00110   for ( int i = 0; i < 4; i++ ){
00111     S(i,0)=pr_[point_indices[i]].x(); S(i,1)=pr_[point_indices[i]].y();
00112     S(i,2)=1;
00113     S(i,3)=pl_[point_indices[i]].y(); S(i,4)=pl_[point_indices[i]].x();
00114   }
00115   vnl_svd<double> svdS( S );
00116   params = svdS.nullvector();
00117 
00118   if ( verbose ) vcl_cerr << "params: " << params << '\n';
00119   return true;
00120 }
00121 
00122 
00123 //------------------------------------------
00124 void
00125 rrel_fm_affine_problem::compute_residuals(
00126   const vnl_vector<double>& params,
00127   vcl_vector<double>& residuals ) const
00128 {
00129   if ( verbose ) vcl_cerr << "rrel_fm_affine_problem::compute_residuals: ";
00130 
00131   vpgl_affine_fundamental_matrix<double> fm;
00132   params_to_fm(params, fm);
00133 
00134   if ( residuals.size() != pr_.size() )
00135     residuals.resize( pr_.size() );
00136   double ressum = 0;
00137 
00138   // The residual for each correspondence is the sum of the squared distances from
00139   // the points to their epipolar lines.
00140   for ( unsigned i = 0; i < pr_.size(); i++ ){
00141     vgl_homg_line_2d<double> lr =
00142       fm.r_epipolar_line( vgl_homg_point_2d<double>( pl_[i] ) );
00143     vgl_homg_line_2d<double> ll =
00144       fm.l_epipolar_line( vgl_homg_point_2d<double>( pr_[i] ) );
00145     residuals[i] = vgl_homg_operators_2d<double>::perp_dist_squared( lr,
00146                                                                      vgl_homg_point_2d<double>( pr_[i] ) )
00147                  + vgl_homg_operators_2d<double>::perp_dist_squared( ll,
00148                                                                      vgl_homg_point_2d<double>( pl_[i] ) );
00149     ressum+=residuals[i];
00150   }
00151   if ( verbose ) vcl_cerr << ressum << '\n';
00152 }
00153 
00154 
00155 //-------------------------------------------
00156 void
00157 rrel_fm_affine_problem::fm_to_params(
00158   const vpgl_affine_fundamental_matrix<double>& fm,
00159   vnl_vector<double>& p ) const
00160 {
00161   p.set_size(2);
00162   vnl_matrix_fixed<double,3,3> fm_vnl = fm.get_matrix();
00163   p(0) = fm_vnl(2,0);
00164   p(1) = fm_vnl(2,1);
00165   p(2) = fm_vnl(2,2);
00166   p(3) = fm_vnl(1,2);
00167   p(4) = fm_vnl(0,2);
00168   double norm = vcl_sqrt( p(0)*p(0)+p(1)*p(1) );
00169   p=p/norm;
00170 }
00171 
00172 
00173 //-------------------------------------------
00174 void
00175 rrel_fm_affine_problem::params_to_fm(
00176   const vnl_vector<double>& p,
00177   vpgl_affine_fundamental_matrix<double>& fm ) const
00178 {
00179   fm.set_from_params( p(0), p(1), p(2), p(3), p(4) );
00180 }
00181 
00182 
00183 //--------------------------------------------
00184 bool
00185 rrel_fm_affine_problem::weighted_least_squares_fit(
00186   vnl_vector<double>& /*params*/,
00187   vnl_matrix<double>& /*norm_covar*/,
00188   const vcl_vector<double>* /*weights*/ ) const
00189 {
00190   vcl_cerr << "rrel_fm_affine_problem::weighted_least_squares_fit was called, but is not implemented.\n";
00191   return false;
00192 }
00193 
00194 
00195 #endif // vpgl_fm_compute_affine_ransac_cxx_