contrib/gel/mrc/vpgl/algo/vpgl_fm_compute_reg_ransac.cxx
Go to the documentation of this file.
00001 // This is gel/mrc/vpgl/algo/vpgl_fm_compute_reg_ransac.cxx
00002 #ifndef vpgl_fm_compute_reg_ransac_cxx_
00003 #define vpgl_fm_compute_reg_ransac_cxx_
00004 
00005 #include "vpgl_fm_compute_reg_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 <rrel/rrel_ran_sam_search.h>
00015 #include <rrel/rrel_muset_obj.h>
00016 
00017 
00018 //------------------------------------------
00019 bool
00020 vpgl_fm_compute_reg_ransac::compute(
00021   const vcl_vector< vgl_point_2d<double> >& pr,
00022   const vcl_vector< vgl_point_2d<double> >& pl,
00023   vpgl_reg_fundamental_matrix<double>& fm )
00024 {
00025   // Check that there is at least 1 point.
00026   if ( pr.size() < 1 || pl.size() < 1 ){
00027     vcl_cerr << "vpgl_fm_compute_ransac: Need at least 1 point pair.\n"
00028              << "Number in each set: " << pr.size() << ", " << pl.size() << vcl_endl;
00029     return false;
00030   }
00031 
00032   // Check that the correspondence lists are the same size.
00033   if ( pr.size() != pl.size() ){
00034     vcl_cerr << "vpgl_fm_compute_reg_ransac: Need correspondence lists of same size.\n";
00035     return false;
00036   }
00037 
00038   // The following block is hacked from similar code in rrel_homography2d_est.
00039   rrel_fm_reg_problem* estimator = new rrel_fm_reg_problem( pr, pl );
00040   estimator->verbose=true;
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_reg_ransac_params::vpgl_fm_compute_reg_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_reg_problem::rrel_fm_reg_problem(
00086   const vcl_vector< vgl_point_2d<double> >& pr,
00087   const vcl_vector< vgl_point_2d<double> >& pl ) :
00088   rrel_estimation_problem(2,1) // Really should be 1,1 but can't deal with div/0
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   verbose = false;
00098 }
00099 
00100 
00101 //------------------------------------------
00102 bool
00103 rrel_fm_reg_problem::fit_from_minimal_set(
00104   const vcl_vector<int>& point_indices,
00105   vnl_vector<double>& params ) const
00106 {
00107   if ( verbose ) vcl_cerr << "rrel_fm_reg_problem::fit_from_minimal_set\n";
00108   assert( point_indices.size() == 1 );
00109 
00110   vpgl_reg_fundamental_matrix<double> fm( pr_[point_indices[0]], pl_[point_indices[0]] );
00111 
00112   // 7 point algorithm returns a list of possible fundamental matrices.  I'm not
00113   // sure which one to take, so i'm taking the first.
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_reg_problem::compute_residuals(
00123   const vnl_vector<double>& params,
00124   vcl_vector<double>& residuals ) const
00125 {
00126   if ( verbose ) vcl_cerr << "rrel_fm_reg_problem::compute_residuals\n";
00127 
00128   vpgl_reg_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     vgl_homg_line_2d<double> lr =
00138       fm.r_epipolar_line( vgl_homg_point_2d<double>( pl_[i] ) );
00139     vgl_homg_line_2d<double> ll =
00140       fm.l_epipolar_line( vgl_homg_point_2d<double>( pr_[i] ) );
00141     residuals[i] = vgl_homg_operators_2d<double>::perp_dist_squared( lr,
00142                                                                      vgl_homg_point_2d<double>( pr_[i] ) )
00143                  + vgl_homg_operators_2d<double>::perp_dist_squared( ll,
00144                                                                      vgl_homg_point_2d<double>( pl_[i] ) );
00145   }
00146 }
00147 
00148 
00149 //-------------------------------------------
00150 void
00151 rrel_fm_reg_problem::fm_to_params(
00152   const vpgl_reg_fundamental_matrix<double>& fm,
00153   vnl_vector<double>& p ) const
00154 {
00155   p.set_size(2);
00156   vnl_matrix_fixed<double,3,3> fm_vnl = fm.get_matrix();
00157   p(0) = fm_vnl(0,2);
00158   p(1) = fm_vnl(2,1);
00159 }
00160 
00161 
00162 //-------------------------------------------
00163 void
00164 rrel_fm_reg_problem::params_to_fm(
00165   const vnl_vector<double>& p,
00166   vpgl_reg_fundamental_matrix<double>& fm ) const
00167 {
00168   fm.set_from_params( p(0), p(1) );
00169 }
00170 
00171 
00172 //--------------------------------------------
00173 bool
00174 rrel_fm_reg_problem::weighted_least_squares_fit(
00175   vnl_vector<double>& /*params*/,
00176   vnl_matrix<double>& /*norm_covar*/,
00177   const vcl_vector<double>* /*weights*/ ) const
00178 {
00179   vcl_cerr << "rrel_fm_reg_problem::weighted_least_squares_fit was called, but is not implemented.\n";
00180   return false;
00181 }
00182 
00183 
00184 #endif // vpgl_fm_compute_reg_ransac_cxx_