contrib/gel/mrc/vpgl/algo/vpgl_fm_compute_ransac.cxx
Go to the documentation of this file.
00001 // This is gel/mrc/vpgl/algo/vpgl_fm_compute_ransac.cxx
00002 #ifndef vpgl_fm_compute_ransac_cxx_
00003 #define vpgl_fm_compute_ransac_cxx_
00004 
00005 #include "vpgl_fm_compute_ransac.h"
00006 #include "vpgl_fm_compute_8_point.h"
00007 
00008 #include <vcl_iostream.h>
00009 #include <vcl_cassert.h>
00010 #include <vcl_cmath.h>
00011 #include <vgl/vgl_point_2d.h>
00012 #include <vgl/vgl_homg_point_2d.h>
00013 #include <vgl/vgl_homg_line_2d.h>
00014 #include <vgl/algo/vgl_homg_operators_2d.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_ransac::compute(
00022   const vcl_vector< vgl_point_2d<double> >& pr,
00023   const vcl_vector< vgl_point_2d<double> >& pl,
00024   vpgl_fundamental_matrix<double>& fm )
00025 {
00026   // Check that there are at least 8 points.
00027   if ( pr.size() < 8 || pl.size() < 8 ){
00028     vcl_cerr << "vpgl_fm_compute_ransac: Need at least 8 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_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_problem* estimator = new rrel_fm_problem( pr, pl );
00041   estimator->verbose = false;
00042   rrel_muset_obj* ransac = new rrel_muset_obj((int)vcl_floor(pr.size()*.75));
00043   estimator->set_prior_scale( 1.0 );
00044   rrel_ran_sam_search* ransam = new rrel_ran_sam_search;
00045   ransam->set_trace_level(trace_level_);
00046 
00047   if (!gen_all_)
00048     ransam->set_sampling_params( max_outlier_frac_,
00049                                  desired_prob_good_, max_pops_);
00050   else
00051     ransam->set_gen_all_samples();
00052 
00053   bool ransac_succeeded = ransam->estimate( estimator, ransac );
00054   if ( ransac_succeeded )
00055   estimator->params_to_fm( ransam->params(), fm );
00056 
00057   // Get a list of the outliers.
00058   estimator->compute_residuals( ransam->params(), residuals );
00059 
00060   outliers = vcl_vector<bool>();
00061   for ( unsigned i = 0; i < pr.size(); i++ ){
00062     if ( residuals[i] > outlier_thresh_ )
00063       outliers.push_back( true );
00064     else
00065       outliers.push_back( false );
00066   }
00067 
00068   delete ransac;
00069   delete ransam;
00070   delete estimator;
00071 
00072   return ransac_succeeded;
00073 }
00074 
00075 
00076 //------------------------------------------
00077 rrel_fm_problem::rrel_fm_problem(
00078   const vcl_vector< vgl_point_2d<double> >& pr,
00079   const vcl_vector< vgl_point_2d<double> >& pl ) :
00080   rrel_estimation_problem(7,8)
00081 {
00082   assert( pr.size() == pl.size() );
00083 
00084   for ( unsigned int i=0; i < pr.size(); i++ )
00085   {
00086     pr_.push_back( pr[i] );
00087     pl_.push_back( pl[i] );
00088   }
00089   verbose = false;
00090 }
00091 
00092 
00093 //------------------------------------------
00094 bool
00095 rrel_fm_problem::fit_from_minimal_set(
00096   const vcl_vector<int>& point_indices,
00097   vnl_vector<double>& params ) const
00098 {
00099   if ( verbose ) vcl_cerr << "rrel_fm_problem::fit_from_minimal_set\n";
00100   assert( point_indices.size() == 8 );
00101 
00102   vcl_vector< vgl_homg_point_2d<double> > set_pr, set_pl;
00103   for ( int i = 0; i < 8; i++ ){
00104     int index = point_indices[i];
00105     set_pr.push_back( vgl_homg_point_2d<double>( pr_[index] ) );
00106     set_pl.push_back( vgl_homg_point_2d<double>( pl_[index] ) );
00107   }
00108 
00109   vpgl_fundamental_matrix<double> fm;
00110   vpgl_fm_compute_8_point fmc8(true);
00111   if ( !fmc8.compute( set_pr, set_pl, fm ) )
00112     return false;
00113 
00114   fm_to_params( fm, params );
00115   if ( verbose ) vcl_cerr << "params: " << params << '\n';
00116   return true;
00117 }
00118 
00119 
00120 //------------------------------------------
00121 void
00122 rrel_fm_problem::compute_residuals(
00123   const vnl_vector<double>& params,
00124   vcl_vector<double>& residuals ) const
00125 {
00126   if ( verbose ) vcl_cerr << "rrel_fm_problem::compute_residuals\n";
00127 
00128   vpgl_fundamental_matrix<double> fm;
00129   params_to_fm(params, fm);
00130 
00131   if ( residuals.size() != pr_.size() )
00132     residuals.resize( pr_.size() );
00133 
00134   // The residual for each correspondence is the sum of the squared distances from
00135   // the points to their epipolar lines.
00136   for ( unsigned i = 0; i < pr_.size(); i++ )
00137   {
00138     vgl_homg_line_2d<double> lr =
00139       fm.r_epipolar_line( vgl_homg_point_2d<double>( pl_[i] ) );
00140     vgl_homg_line_2d<double> ll =
00141       fm.l_epipolar_line( vgl_homg_point_2d<double>( pr_[i] ) );
00142     residuals[i] = vgl_homg_operators_2d<double>::perp_dist_squared( lr,
00143                                                                      vgl_homg_point_2d<double>( pr_[i] ) )
00144                  + vgl_homg_operators_2d<double>::perp_dist_squared( ll,
00145                                                                      vgl_homg_point_2d<double>( pl_[i] ) );
00146   }
00147 }
00148 
00149 
00150 //-------------------------------------------
00151 void
00152 rrel_fm_problem::fm_to_params(
00153   const vpgl_fundamental_matrix<double>& fm,
00154   vnl_vector<double>& p ) const
00155 {
00156   p.set_size(9);
00157   vnl_matrix_fixed<double,3,3> fm_vnl = fm.get_matrix();
00158   for ( int r = 0; r < 3; r++ )
00159     for ( int c = 0; c < 3; c++ )
00160       p( 3*r + c ) = fm_vnl( r, c );
00161 }
00162 
00163 
00164 //-------------------------------------------
00165 void
00166 rrel_fm_problem::params_to_fm(
00167   const vnl_vector<double>& p,
00168   vpgl_fundamental_matrix<double>& fm ) const
00169 {
00170   vnl_matrix_fixed<double,3,3> fm_vnl;
00171   for ( int r = 0; r < 3; r++ )
00172     for ( int c = 0; c < 3; c++ )
00173       fm_vnl( r, c ) = p( 3*r + c );
00174   fm.set_matrix( fm_vnl );
00175 }
00176 
00177 
00178 //--------------------------------------------
00179 bool
00180 rrel_fm_problem::weighted_least_squares_fit(
00181   vnl_vector<double>& /*params*/,
00182   vnl_matrix<double>& /*norm_covar*/,
00183   const vcl_vector<double>* /*weights*/ ) const
00184 {
00185   vcl_cerr << "rrel_fm_problem::weighted_least_squares_fit was called, but is not implemented.\n";
00186   return false;
00187 }
00188 
00189 
00190 #endif // vpgl_fm_compute_ransac_cxx_