contrib/rpl/rgrl/rgrl_initializer_ran_sam.cxx
Go to the documentation of this file.
00001 // This is rpl/rgrl/rgrl_initializer_ran_sam.cxx
00002 #include "rgrl_initializer_ran_sam.h"
00003 //:
00004 // \file
00005 // \author Charlene Tsai
00006 // \date   Sep 2003
00007 
00008 #include <vcl_cmath.h>
00009 #include <vcl_cassert.h>
00010 
00011 #include "rgrl_match_set.h"
00012 #include "rgrl_estimator.h"
00013 #include "rgrl_scale_estimator.h"
00014 #include "rgrl_scale.h"
00015 #include "rgrl_trans_affine.h"
00016 #include "rgrl_view.h"
00017 #include "rgrl_util.h"
00018 
00019 #include <vnl/vnl_random.h>
00020 
00021 static const unsigned verbose_ = 0;
00022 
00023 // Random number generator. This will be shared by all ran_sam instances.
00024 static vnl_random global_generator_;
00025 
00026 // Iterators to go over the matches
00027 //
00028 typedef rgrl_match_set::from_iterator FIter;
00029 typedef FIter::to_iterator TIter;
00030 
00031 rgrl_initializer_ran_sam::
00032 rgrl_initializer_ran_sam( )
00033   : generate_all_(false),
00034     generator_( &global_generator_ ),
00035     own_generator_( false ),
00036     xform_(0), scale_(0),
00037     samples_to_take_(0)
00038 {
00039   set_sampling_params();
00040 }
00041 
00042 rgrl_initializer_ran_sam::
00043 rgrl_initializer_ran_sam( int seed )
00044   : generate_all_(false),
00045     generator_( new vnl_random( seed ) ),
00046     own_generator_( true ),
00047     xform_(0), scale_(0),
00048     samples_to_take_(0)
00049 {
00050   set_sampling_params();
00051 }
00052 
00053 rgrl_initializer_ran_sam::
00054 ~rgrl_initializer_ran_sam()
00055 {
00056   if ( own_generator_ )
00057     delete generator_;
00058 }
00059 
00060 void
00061 rgrl_initializer_ran_sam::
00062 set_gen_all_samples()
00063 {
00064   generate_all_ = true;
00065 }
00066 
00067 void
00068 rgrl_initializer_ran_sam::
00069 set_sampling_params( double max_outlier_frac,
00070                      double desired_prob_good,
00071                      unsigned int max_populations_expected,
00072                      unsigned int min_samples )
00073 {
00074   data_set_ = false;
00075   generate_all_ = false;
00076   max_outlier_frac_ = max_outlier_frac;
00077   desired_prob_good_ = desired_prob_good;
00078   max_populations_expected_ = max_populations_expected;
00079   min_samples_ = min_samples;
00080 }
00081 
00082 void
00083 rgrl_initializer_ran_sam::
00084 set_data(rgrl_match_set_sptr                init_match_set,
00085          rgrl_scale_estimator_unwgted_sptr  scale_est,
00086          rgrl_view_sptr                     prior_view,
00087          bool should_estimate_global_region)
00088 {
00089   match_set_ = init_match_set;
00090   transform_estiamtor_ = prior_view->xform_estimator();
00091   scale_estimator_ = scale_est;
00092   init_view_ = prior_view;
00093   data_set_ = true;
00094   called_before_ = false;
00095   should_estimate_global_region_ = should_estimate_global_region;
00096 }
00097 
00098 void
00099 rgrl_initializer_ran_sam::
00100 set_data(rgrl_match_set_sptr                init_match_set,
00101          rgrl_scale_estimator_unwgted_sptr  scale_est,
00102          rgrl_mask_sptr           const&    from_image_roi,
00103          rgrl_mask_sptr           const&    to_image_roi,
00104          rgrl_mask_box            const&    initial_from_image_roi,
00105          rgrl_estimator_sptr                xform_estimator,
00106          unsigned                           initial_resolution,
00107          bool should_estimate_global_region)
00108 {
00109   rgrl_mask_box global_region( from_image_roi->bounding_box() );
00110   rgrl_view_sptr  prior_view  = new rgrl_view( from_image_roi, to_image_roi,
00111                                                initial_from_image_roi,
00112                                                global_region, xform_estimator,
00113                                                0, initial_resolution );
00114   set_data( init_match_set, scale_est, prior_view, should_estimate_global_region );
00115 }
00116 
00117 void
00118 rgrl_initializer_ran_sam::
00119 set_data(rgrl_match_set_sptr                init_match_set,
00120          rgrl_scale_estimator_unwgted_sptr  scale_est,
00121          rgrl_mask_sptr      const&         from_image_roi,
00122          rgrl_mask_sptr      const&         to_image_roi,
00123          rgrl_estimator_sptr                xform_estimator,
00124          unsigned                           initial_resolution )
00125 {
00126   rgrl_mask_box global_region( from_image_roi->bounding_box() );
00127   rgrl_view_sptr  prior_view  = new rgrl_view( from_image_roi, to_image_roi,
00128                                                global_region, global_region,
00129                                                xform_estimator, 0,
00130                                                initial_resolution );
00131   set_data( init_match_set, scale_est, prior_view, false );
00132 }
00133 
00134 void
00135 rgrl_initializer_ran_sam::
00136 set_data(rgrl_match_set_sptr                init_match_set,
00137          rgrl_scale_estimator_unwgted_sptr  scale_est,
00138          rgrl_mask_sptr      const&         from_image_roi,
00139          rgrl_estimator_sptr                xform_estimator,
00140          unsigned                           initial_resolution )
00141 {
00142   rgrl_mask_box global_region( from_image_roi->bounding_box() );
00143   rgrl_view_sptr  prior_view  = new rgrl_view( from_image_roi, from_image_roi,
00144                                                global_region, global_region,
00145                                                xform_estimator, 0,
00146                                                initial_resolution );
00147   set_data( init_match_set, scale_est, prior_view, false );
00148 }
00149 
00150 bool
00151 rgrl_initializer_ran_sam::
00152 next_initial( rgrl_view_sptr           & view,
00153               rgrl_scale_sptr          & prior_scale)
00154 {
00155   if ( called_before_ ) return false;
00156 
00157   if (!estimate()) return false;
00158 
00159   int dim = init_view_->from_image_roi()->x0().size();
00160   rgrl_mask_box global_region( dim );
00161 
00162   if ( should_estimate_global_region_ )
00163     global_region =
00164       rgrl_util_estimate_global_region(init_view_->from_image_roi(),
00165                                        init_view_->to_image_roi(),
00166                                        init_view_->global_region(),
00167                                        *xform_);
00168   else {
00169     global_region.set_x0( init_view_->from_image_roi()->x0() );
00170     global_region.set_x1( init_view_->from_image_roi()->x1() );
00171   }
00172 
00173   view = new rgrl_view(init_view_->from_image_roi(), init_view_->to_image_roi(),
00174                        init_view_->region(), global_region,
00175                        init_view_-> xform_estimator(),
00176                        xform_,
00177                        init_view_->resolution());
00178   prior_scale = scale_;
00179 
00180   called_before_ = true;
00181 
00182   return true;
00183 }
00184 
00185 bool
00186 rgrl_initializer_ran_sam::
00187 estimate()
00188 {
00189   //
00190   //  Initialize the random sampling.
00191   //
00192   // Calculate the total number of matches. In most problems, this equals
00193   // the match_set_->size() (number of "unique samples"). With estimation
00194   // problems involving non-unique correspondences, however, the total
00195   // number of possible correspondences generally
00196   // much greater than the number of unique samples
00197   //
00198   unsigned int total_num_matches = 0;
00199   for ( FIter fi = match_set_->from_begin(); fi != match_set_->from_end(); ++fi ) {
00200     total_num_matches += fi.size();
00201   }
00202   this->calc_num_samples( total_num_matches );
00203 
00204   DebugMacro_abv( 1 , "Samples = " << samples_to_take_ <<'\n' );
00205 
00206   unsigned int points_per = (int)vcl_floor((double)transform_estiamtor_->param_dof()/match_set_->num_constraints_per_match());
00207   vcl_vector<int> point_indices( points_per );
00208   rgrl_trans_affine dummy_trans(3);
00209   rgrl_scale_sptr dummy_scale;
00210   bool  scale_set=false;
00211 
00212   //
00213   //  The main loop repeatedly establishes a sample, generates fit
00214   //  parameters from the sample, calculates the error scale
00215   //  value, and tests the value against the best found thus far.  If
00216   //  a sample doesn't yield a parameter vector, it is still counted
00217   //  toward the total number to take.  This prevents errors that
00218   //  would arise when all samples are to be used, but still works
00219   //  correctly for probabilistic sampling because the possibility
00220   //  is rare.
00221   //
00222   for ( unsigned int s = 0; s<samples_to_take_; ++s )
00223   {
00224     this->next_sample( s, total_num_matches, point_indices, points_per );
00225     rgrl_match_set_sptr
00226       sub_match_set = this->get_matches(point_indices,total_num_matches );
00227     if (this->debug_flag() > 2) this->trace_sample( point_indices );
00228 
00229     rgrl_transformation_sptr
00230       new_xform = transform_estiamtor_->estimate( sub_match_set, dummy_trans );
00231     if ( new_xform )
00232     {
00233       match_set_->remap_from_features(*new_xform);
00234       rgrl_scale_sptr
00235         new_scale = scale_estimator_->estimate_unweighted(*match_set_, dummy_scale);
00236 
00237       if ( !scale_set || (new_scale->has_geometric_scale() &&
00238                           new_scale->geometric_scale() < scale_->geometric_scale()) ) {
00239         scale_ = new_scale;
00240         xform_ = new_xform;
00241         scale_set = true;
00242       }
00243     }
00244     else DebugMacro_abv(1, "No fit to sample.\n");
00245   }
00246 
00247   if ( ! scale_set ) {
00248     return false;
00249   }
00250 
00251   DebugMacro_abv(1,"Final geometric scale = "<<scale_->geometric_scale()<<'\n');
00252 
00253   return true;
00254 }
00255 
00256 //
00257 //: Calculate number of samples --- non-unique matching estimation problems
00258 void
00259 rgrl_initializer_ran_sam::
00260 calc_num_samples( unsigned int num_matches )
00261 {
00262   if ( generate_all_ ) {
00263     //
00264     //  Calculate C(num_points, points_per_sample)
00265     //
00266     unsigned long numer=1;
00267     unsigned long denom=1;
00268     unsigned int n=num_matches;
00269     unsigned int k=(int)vcl_floor((double)transform_estiamtor_->param_dof()/match_set_->num_constraints_per_match());
00270     for ( ; k>0; --k, --n ) {
00271       numer *= n;
00272       denom *= k;
00273     }
00274     samples_to_take_ = (unsigned int)( numer / denom );
00275   }
00276   else {
00277     //
00278     //  Calculate the probability that a sample is good.  Then, use this
00279     //  to determine the minimum number of samples required.
00280     //
00281     int num_samples_to_instantiate =
00282       (int)vcl_floor((double)transform_estiamtor_->param_dof()/match_set_->num_constraints_per_match());
00283     unsigned int num_unique_matches = match_set_->from_size();
00284     double prob_pt_inlier = (1 - max_outlier_frac_) * num_unique_matches / double(num_matches);
00285     double prob_pt_good
00286       = max_populations_expected_
00287       * vcl_pow( prob_pt_inlier / max_populations_expected_, num_samples_to_instantiate );
00288     samples_to_take_ = int(vcl_ceil( vcl_log(1.0 - desired_prob_good_) /
00289                                      vcl_log(1.0 - prob_pt_good) ));
00290     if ( samples_to_take_ < min_samples_ )
00291       samples_to_take_ = min_samples_;
00292   }
00293 }
00294 
00295 //: Determine the next random sample, filling in the "sample" vector.
00296 void
00297 rgrl_initializer_ran_sam::
00298 next_sample( unsigned int taken, unsigned int num_points,
00299              vcl_vector<int>& sample,
00300              unsigned int points_per_sample )
00301 {
00302   assert( sample.size() == points_per_sample );
00303 
00304   if ( generate_all_ ) {
00305     if ( taken == 0 ) {  //  initial sample
00306       for ( unsigned int i=0; i<points_per_sample; ++i )
00307         sample[i] = i;
00308     }
00309     else if ( taken >= samples_to_take_ )
00310       vcl_cerr << "rrel_ran_sam_search::next_sample -- ERROR: used all samples\n";
00311     else {
00312       //
00313       //  Generate the subsets in lexicographic order.
00314       //
00315       unsigned int i=points_per_sample-1;
00316       unsigned int k=num_points-1;
00317       while ( sample[i] == (int)k ) { --i; --k; }
00318       k = ++ sample[i];
00319       for ( ++k, ++i; i<points_per_sample; ++i, ++k )
00320         sample[i]=k;
00321     }
00322   }
00323   else if ( num_points == 1 ) {
00324     sample[0] = 0;
00325   }
00326   else
00327   {
00328     unsigned int k=0, counter=0;
00329     while ( k<points_per_sample ) // This might be an infinite loop!
00330     {
00331       int id = generator_->lrand32( 0, num_points-1 );
00332       if ( id >= int(num_points) ) {   //  safety check
00333         vcl_cerr << "rrel_ran_sam_search::next_sample --- "
00334                  << "WARNING: random value out of range\n";
00335       }
00336       else
00337       {
00338         ++counter;
00339         bool different = true;
00340         for ( int i=k-1; i>=0 && different; --i )
00341           different = (id != sample[i]);
00342         if ( different )
00343           sample[k++] = id, counter = 0;
00344         else if (counter > 100)
00345         {
00346           vcl_cerr << "rrel_ran_sam_search::next_sample --- WARNING: "
00347                    << "lrand32() generated 100x the same value "<< id
00348                    << " from the range [0," << num_points-1 << "]\n";
00349           sample[k++] = id+1;
00350         }
00351       }
00352     }
00353   }
00354 }
00355 
00356 rgrl_match_set_sptr
00357 rgrl_initializer_ran_sam::
00358 get_matches(const vcl_vector<int>&  point_indices, unsigned int total_num_matches)
00359 {
00360   rgrl_match_set_sptr
00361     sub_match_set = new rgrl_match_set( match_set_->from_feature_type(), match_set_->to_feature_type() );
00362 
00363   if ( total_num_matches == match_set_->from_size() ) { //unique matches
00364     for (unsigned int i = 0; i<point_indices.size(); ++i) {
00365       FIter fi = match_set_->from_begin() + point_indices[i];
00366       TIter ti = fi.begin();
00367       sub_match_set->add_feature_and_match( fi.from_feature(),
00368                                             fi.mapped_from_feature(),
00369                                             ti.to_feature() );
00370     }
00371   }
00372   else {
00373     int match_count = 0;
00374     for ( FIter fi = match_set_->from_begin(); fi != match_set_->from_end(); ++fi ) {
00375       for (unsigned int i = 0; i<point_indices.size(); ++i) {
00376         if ( match_count <= point_indices[i] && match_count + (int)fi.size() > point_indices[i]) {
00377           unsigned int offset = point_indices[i] - match_count;
00378           TIter ti = fi.begin() + offset;
00379           sub_match_set->add_feature_and_match( fi.from_feature(),
00380                                                 fi.mapped_from_feature(),
00381                                                 ti.to_feature() );
00382         }
00383       }
00384       match_count += fi.size();
00385     }
00386   }
00387 
00388   return sub_match_set;
00389 }
00390 
00391 void
00392 rgrl_initializer_ran_sam::
00393 trace_sample( const vcl_vector<int>& indices ) const
00394 {
00395   vcl_cout << "\nNew sample: ";
00396   for ( unsigned int i=0; i<indices.size(); ++i)
00397     vcl_cout << ' ' << indices[i];
00398   vcl_cout << vcl_endl;
00399 }