contrib/rpl/rgrl/rgrl_feature_based_registration.cxx
Go to the documentation of this file.
00001 #include "rgrl_feature_based_registration.h"
00002 //:
00003 // \file
00004 #include "rgrl_initializer.h"
00005 #include "rgrl_convergence_tester.h"
00006 #include "rgrl_converge_status.h"
00007 #include "rgrl_estimator.h"
00008 #include "rgrl_scale_estimator.h"
00009 #include "rgrl_weighter_unit.h"
00010 #include "rgrl_matcher.h"
00011 #include "rgrl_match_set.h"
00012 #include "rgrl_scale_est_null.h"
00013 #include "rgrl_cast.h"
00014 #include "rgrl_data_manager.h"
00015 #include "rgrl_scale.h"
00016 #include "rgrl_util.h"
00017 #include "rgrl_convergence_on_median_error.h"
00018 #include "rgrl_event.h"
00019 #include <vcl_cassert.h>
00020 
00021 rgrl_feature_based_registration::
00022 rgrl_feature_based_registration( rgrl_data_manager_sptr data,
00023                                  rgrl_convergence_tester_sptr conv_tester )
00024   :data_( data ),
00025    conv_tester_( conv_tester ),
00026    num_xforms_tested_( 0 ),
00027    max_icp_iter_(25),
00028    expected_max_geometric_scale_ (0),
00029    expected_min_geometric_scale_ (0),
00030    iterations_for_scale_est_(-1),
00031    should_penalize_scaling_(false),
00032    current_stage_( 0 )
00033 {
00034 }
00035 
00036 rgrl_feature_based_registration::
00037 rgrl_feature_based_registration( rgrl_data_manager_sptr data )
00038   :data_( data ),
00039    num_xforms_tested_( 0 ),
00040    max_icp_iter_(25),
00041    expected_max_geometric_scale_ (0),
00042    expected_min_geometric_scale_ (0),
00043    iterations_for_scale_est_(-1),
00044    should_penalize_scaling_(false)
00045 {
00046   double tolerance = 1.0;
00047   conv_tester_ = new rgrl_convergence_on_median_error( tolerance );
00048 }
00049 
00050 rgrl_feature_based_registration::
00051 ~rgrl_feature_based_registration()
00052 {
00053 }
00054 
00055 void
00056 rgrl_feature_based_registration::
00057 clear_results()
00058 {
00059   num_xforms_tested_ = 0;
00060   best_xform_estimate_ = 0;
00061   best_matches_.clear();
00062   best_scales_.clear();
00063   best_status_ = 0;
00064 }
00065 
00066 //: Running from multiple initial estimates, produced by the initializer during registration.
00067 //  Loop through the set of initial estimates, and call the next \a run(.) in the loop.
00068 void
00069 rgrl_feature_based_registration::
00070 run( rgrl_initializer_sptr initializer )
00071 {
00072   //  Clear previous results
00073   this->clear_results();
00074 
00075   rgrl_transformation_sptr          init_xform_estimate;
00076   rgrl_scale_sptr                   prior_scale;
00077   rgrl_estimator_sptr               init_xform_estimator;
00078   unsigned                          init_resolution;
00079 
00080   rgrl_mask_sptr                    from_image_roi; //not used
00081   rgrl_mask_sptr                    to_image_roi;
00082   rgrl_mask_box                     current_region(0); // not used
00083   rgrl_mask_box                     global_region(0);
00084 
00085   while ( initializer->next_initial( from_image_roi, to_image_roi,
00086                                      current_region, global_region,
00087                                      init_xform_estimator, init_xform_estimate,
00088                                      init_resolution, prior_scale ) ) {
00089     DebugMacro(  1, "Try "<< num_xforms_tested_ << " initial estimate\n" );
00090 
00091     // Use the estimated overlap region (global_region) of the
00092     // from_image, instead of the entire ROI of the from_image.
00093     this->run( global_region, to_image_roi-> bounding_box(),
00094                init_xform_estimator, init_xform_estimate,
00095                prior_scale, init_resolution );
00096 
00097     if ( best_status_ && best_status_->is_good_enough() ) break;
00098 
00099     ++num_xforms_tested_;
00100   }
00101 }
00102 
00103 //: Running from a given initial estimate.
00104 //
00105 //  Based on if data_->is_multi_feature(), call run_single_feature(.)
00106 //  or run_multi_feature(.)
00107 //
00108 void
00109 rgrl_feature_based_registration::
00110 run( rgrl_mask_box              from_image_region,
00111      rgrl_mask_box              to_image_region,
00112      rgrl_estimator_sptr        init_xform_estimator,
00113      rgrl_transformation_sptr   initial_xform,
00114      rgrl_scale_sptr            prior_scale,
00115      unsigned                   init_resolution)
00116 {
00117   if ( data_->is_multi_feature() ) {
00118     DebugMacro(1, " Multi-feature Registration:\n");
00119     this->register_multi_feature(from_image_region, to_image_region,
00120                                  init_xform_estimator, initial_xform,
00121                                  prior_scale, init_resolution);
00122   }
00123   else {
00124     DebugMacro(  1, " Single-feature Registration:\n" );
00125 
00126     this->register_single_feature(from_image_region, to_image_region,
00127                                   init_xform_estimator,
00128                                   initial_xform, prior_scale, init_resolution);
00129   }
00130 }
00131 
00132 //////////////// functions to access internal data  ////////////////////////
00133 
00134 //:  Return the final, best estimate
00135 rgrl_transformation_sptr
00136 rgrl_feature_based_registration::
00137 final_transformation() const
00138 {
00139   return best_xform_estimate_;
00140 }
00141 
00142 //:  Return the scales of the best transformation estimate
00143 rgrl_set_of<rgrl_scale_sptr> const&
00144 rgrl_feature_based_registration::
00145 final_scales() const
00146 {
00147   return best_scales_;
00148 }
00149 
00150 rgrl_scale_sptr
00151 rgrl_feature_based_registration::
00152 final_scale() const
00153 {
00154   assert ( !data_->is_multi_feature() );
00155   return best_scales_[0];
00156 }
00157 
00158 //:  Return the status of the best transformation estimate.
00159 rgrl_converge_status_sptr
00160 rgrl_feature_based_registration::
00161 final_status() const
00162 {
00163   return best_status_;
00164 }
00165 
00166 //:  The matches used for the best transformation estimate.
00167 rgrl_set_of<rgrl_match_set_sptr>  const&
00168 rgrl_feature_based_registration::
00169 final_match_sets() const
00170 {
00171   return best_matches_;
00172 }
00173 
00174 rgrl_match_set_sptr
00175 rgrl_feature_based_registration::
00176 final_match_set() const
00177 {
00178   assert ( !data_->is_multi_feature() );
00179   return best_matches_[0];
00180 }
00181 
00182 //:  Return the number of initial transformations tested
00183 unsigned
00184 rgrl_feature_based_registration::
00185 num_initial_xforms_tested() const
00186 {
00187   return num_xforms_tested_;
00188 }
00189 
00190 //:  Return true is has a best xform_estimate
00191 bool
00192 rgrl_feature_based_registration::
00193 has_final_transformation() const
00194 {
00195   return best_xform_estimate_ != 0;
00196 }
00197 
00198 //: Set the max number of icp iteration per level
00199 void
00200 rgrl_feature_based_registration::
00201 set_max_icp_iter( unsigned iter )
00202 {
00203    max_icp_iter_ = iter;
00204 }
00205 
00206 //: Set the expected max scale
00207 void
00208 rgrl_feature_based_registration::
00209 set_expected_max_geometric_scale( double scale)
00210 {
00211   expected_max_geometric_scale_ = scale;
00212 }
00213 
00214 //: Set the expected min scale
00215 void
00216 rgrl_feature_based_registration::
00217 set_expected_min_geometric_scale( double scale)
00218 {
00219   expected_min_geometric_scale_ = scale;
00220 }
00221 
00222 //: Set the number of iteration for scale estimation
00223 void
00224 rgrl_feature_based_registration::
00225 set_iterations_for_scale_est( int iter)
00226 {
00227   iterations_for_scale_est_ = iter;
00228 }
00229 
00230 //: penalize transformation that involves scaling of the registration area
00231 void
00232 rgrl_feature_based_registration::
00233  penalize_scaling( bool penalize)
00234 {
00235   should_penalize_scaling_ = penalize;
00236 }
00237 
00238 
00239 //: Return the current match sets
00240 rgrl_set_of<rgrl_match_set_sptr>  const&
00241 rgrl_feature_based_registration::
00242 current_match_sets() const
00243 {
00244   return current_match_sets_;
00245 }
00246 
00247 //:  Return the current estimate
00248 rgrl_transformation_sptr
00249 rgrl_feature_based_registration::
00250 current_transformation() const
00251 {
00252   return current_xform_estimate_;
00253 }
00254 
00255 //:  Return the current stage
00256 unsigned
00257 rgrl_feature_based_registration::
00258 current_stage() const
00259 {
00260   return current_stage_;
00261 }
00262 
00263 //:  Return the iteration at current stage
00264 unsigned
00265 rgrl_feature_based_registration::
00266 iterations_at_current_stage() const
00267 {
00268   return iterations_at_stage_;
00269 }
00270 
00271 
00272 //////////////////// private functions //////////////////////////
00273 
00274 //: registration of single feature type at each stage/resolution
00275 void
00276 rgrl_feature_based_registration::
00277 register_single_feature( rgrl_mask_box            from_image_region,
00278                          rgrl_mask_box            to_image_region,
00279                          rgrl_estimator_sptr      initial_xform_estimator,
00280                          rgrl_transformation_sptr xform_estimate,
00281                          rgrl_scale_sptr          scale,
00282                          unsigned                 resolution )
00283 {
00284   rgrl_converge_status_sptr         current_status;
00285   rgrl_feature_set_sptr             from_set;
00286   rgrl_feature_set_sptr             to_set;
00287   rgrl_matcher_sptr                 matcher;
00288   rgrl_scale_estimator_unwgted_sptr unwgted_scale_est;
00289   rgrl_scale_estimator_wgted_sptr   wgted_scale_est;
00290   rgrl_weighter_sptr                weighter;
00291   rgrl_match_set_sptr               match_set;
00292   vcl_vector<rgrl_estimator_sptr>   xform_estimators;
00293   rgrl_estimator_sptr               xform_estimator;
00294   bool                              failed, scale_in_range;
00295   unsigned                          prev_resol = 0;
00296 
00297   failed = false;
00298   scale_in_range = true;
00299   current_xform_estimate_ = xform_estimate;
00300 
00301   assert ( data_->has_stage( resolution ) );
00302 
00303   do { // for each stage/resolution
00304     data_->get_data_at_stage( resolution, from_set, to_set, matcher, weighter,
00305                               unwgted_scale_est, wgted_scale_est, xform_estimators);
00306     match_set = 0;
00307     current_stage_ = resolution;
00308 
00309     DebugMacro(  1, " Current resolution "<< resolution <<'\n' );
00310 
00311     // If no estimator found for the current stage, the default is
00312     // from the initializer. Feature_based can only deal with one
00313     // estimator in each stage/resolution. If more than one is found,
00314     // only the first is kept.
00315     //
00316     if ( xform_estimators.empty() )
00317       xform_estimator = initial_xform_estimator;
00318     else xform_estimator = xform_estimators[0];
00319     assert ( xform_estimator );
00320 
00321     iterations_at_stage_ = 0; //keeps track of total iter at stage
00322     current_status = 0;
00323     bool should_estimate_scale = true;
00324     int  scale_est_count = 0;
00325 
00326     do { // for each re-match
00327 
00328       DebugMacro(  2, " Computing matches and scales\n" );
00329       // Compute matches, and scales for each feature set.
00330       //
00331       match_set= matcher->compute_matches( *from_set,
00332                                            *to_set,
00333                                            *current_xform_estimate_,
00334                                            from_image_region,
00335                                            to_image_region,
00336                                            *scale );
00337       current_match_sets_.clear();
00338       current_match_sets_.push_back( match_set );
00339       DebugMacro(  2, "      Matches: " << match_set->from_size() <<'\n' );
00340 
00341       // For the first iteration, use prior scale or estimate the
00342       // scales without weights (since we don't have any...)
00343       //
00344       if ( iterations_for_scale_est_ >= 0 &&
00345            scale_est_count > iterations_for_scale_est_ ) {
00346         should_estimate_scale = false;
00347       }
00348 
00349       rgrl_scale_sptr  new_scale = 0;
00350       if ( !should_estimate_scale ) {
00351         DebugMacro(  2, "No scale estimation\n" );
00352       }
00353       else if ( match_set->from_size() == 0 ) {
00354         DebugMacro(0, "rgrl_feature_based_registration:: Empty match set!!!\n");
00355         failed = true;
00356         continue;
00357       }
00358       else { //should_estimate_scale && match_set->from_size() > 0
00359         if ( !wgted_scale_est ) {
00360           new_scale = unwgted_scale_est->
00361             estimate_unweighted( *match_set, scale, should_penalize_scaling_ );
00362         } else {
00363           if ( iterations_at_stage_ == 0 && !scale ) {
00364             assert ( unwgted_scale_est );
00365             new_scale = unwgted_scale_est->
00366               estimate_unweighted( *match_set, scale, should_penalize_scaling_);
00367           }
00368           else {
00369             weighter->compute_weights(*scale, *match_set);
00370             new_scale = wgted_scale_est->
00371               estimate_weighted( *match_set, scale, should_penalize_scaling_);
00372           }
00373         }
00374 
00375         // If the new scale exists, and the geometric scale is above
00376         // the lower bound, replace the old one by the new one
00377         if ( new_scale ) {
00378           DebugMacro( 2, "New geometric scale = "<<new_scale->geometric_scale()<<'\n' );
00379           if ( new_scale->has_geometric_scale() &&
00380                new_scale->geometric_scale() < expected_min_geometric_scale_ ) {
00381             should_estimate_scale = false;
00382             if (!scale) scale = new_scale;
00383             scale->set_geometric_scale(expected_min_geometric_scale_);
00384             DebugMacro( 2, "Scale below expected_min_geometric_scale. Set to expected_min_geometric_scale.\n" );
00385           }
00386           else {
00387             scale = new_scale;
00388           }
00389           scale_est_count++;
00390         }
00391       }
00392       DebugMacro( 2, "Current geometric scale = "<<scale->geometric_scale()<<'\n' );
00393       assert ( scale );
00394 
00395       // If the scale is above the upper bound of the expected
00396       // geometric scale return with failure
00397       if ( expected_max_geometric_scale_ > 0 &&
00398            scale->has_geometric_scale() &&
00399            scale->geometric_scale() > expected_max_geometric_scale_) {
00400         scale_in_range = false;
00401         failed = true;
00402         continue;
00403       }
00404 
00405       DebugMacro(  2, " Estimate the transformation\n" );
00406 
00407       // Transformation estimation using a simplified irls
00408       // (Iterative-Reweighted Least-Squares) routine.
00409       //
00410       // The match sets and the scales are fixed, but the associated
00411       // weights are updated (hence reweighted-least-squares)
00412       // throughout the estimation.
00413       //
00414       if ( !rgrl_util_irls( match_set, scale, weighter,
00415                             *conv_tester_, xform_estimator,
00416                             current_xform_estimate_,
00417                             false,                   // no fast mapping
00418                             this->debug_flag() ) ) {
00419         failed = true;
00420         continue; //no valid xform, so exit the loop
00421       }
00422 
00423       // For debugging
00424       //
00425       this->invoke_event(rgrl_event_iteration());
00426 
00427       // Update the weights and scale estimates based on the new transform
00428       //
00429       DebugMacro(  2, " Updating scale estimates and checking for validity\n" );
00430 
00431       match_set->remap_from_features( *current_xform_estimate_ );
00432       weighter->compute_weights( *scale, *match_set );
00433 
00434       // compute the scaling factors
00435       {
00436         bool ret_success;
00437         vnl_vector<double> scaling;
00438         ret_success = rgrl_util_geometric_scaling_factors( *match_set, scaling );
00439         if ( ret_success ) {
00440           current_xform_estimate_->set_scaling_factors( scaling );
00441           if (should_penalize_scaling_) {
00442             for ( unsigned ds=0; ds < scaling.size(); ++ds ) {
00443               if (scaling[ds] < 1e-5) {
00444                 DebugMacro(  1," Scaling of dimension "<<ds<<" too high\n");
00445                 failed = true;
00446               }
00447             }
00448           }
00449         }
00450         else
00451           WarningMacro( "cannot compute scaling factors!!!" );
00452       }
00453 
00454 #if 0
00455       // CT: this step seems redundant, since the scale is re-computed
00456       // at the beginning of next iteration.
00457 
00458       if ( should_estimate_scale ) {
00459         if ( !wgted_scale_est )
00460           scale = unwgted_scale_est->
00461             estimate_unweighted( *match_set, scale, should_penalize_scaling_ );
00462         else
00463           scale = wgted_scale_est->
00464             estimate_weighted( *match_set, scale, should_penalize_scaling_ );
00465         DebugMacro(  2, " Geometric scale after converged = "<< scale->geometric_scale()<<'\n' );
00466       }
00467 #endif // 0
00468 
00469       // Perform convergence test
00470       //
00471       DebugMacro(  2, " Perform convergence test\n" );
00472       current_status =
00473         conv_tester_->compute_status( current_status,
00474                                       current_xform_estimate_,
00475                                       xform_estimator,
00476                                       match_set, scale,
00477                                       should_penalize_scaling_);
00478       DebugMacro(  3, "run: (iterations = " << iterations_at_stage_ << ") oscillation count = " << current_status->oscillation_count() << '\n' );
00479       DebugMacro(  3, "run: error = " << current_status->error() << vcl_endl );
00480       DebugMacro(  3, "run: error_diff = " << current_status->error_diff() << vcl_endl );
00481 
00482       ++iterations_at_stage_;
00483     }
00484     while ( !failed &&
00485             !current_status->has_converged() &&
00486             !current_status->has_stagnated() &&
00487             iterations_at_stage_ < max_icp_iter_ );
00488 
00489     if ( failed ) {
00490       if ( !scale_in_range )
00491         DebugMacro(  1, " Geometric scale above the expected value\n" );
00492       else
00493         DebugMacro( 1, " Failed with empty match set, or irls estimation\n" );
00494       continue;
00495     }
00496     if ( current_status->has_converged() )
00497       DebugMacro(  1, " CONVERGED\n" );
00498     if ( current_status->has_stagnated() )
00499       DebugMacro(  1, " STAGNATED\n" );
00500     if ( iterations_at_stage_ == max_icp_iter_ )
00501       DebugMacro(  1, " ICP iteration reached maximum ("<<max_icp_iter_<<" )\n" );
00502 
00503     // Move to the next resolution with proper initialization if not
00504     // at the finest level
00505     //
00506     prev_resol = resolution;
00507     initialize_for_next_resolution( from_image_region, to_image_region,
00508                                     current_xform_estimate_, resolution );
00509     int level_diff = prev_resol - resolution;
00510     double dim_increase = data_->dimension_increase_for_next_stage(prev_resol);
00511 //  double scale_multipler = vcl_pow(dim_increase, level_diff);
00512     scale->set_geometric_scale( scale->geometric_scale()*
00513                                 vcl_pow(dim_increase, level_diff) );
00514   }
00515   while ( !failed && ( resolution != 0 || prev_resol != 0 ) );
00516 
00517   DebugMacro( 1, "Estimation complete\n" );
00518 
00519   //   At this point the iterations are over for this initial
00520   //   estimate.  If the estimate is successful, if it is the first
00521   //   one tested or it is the best seen thus far, record information
00522   //   about this estimate.
00523   //
00524 
00525   if ( !failed ){
00526     DebugMacro( 1, "Obj value after convergence = "<<current_status->objective_value()<<'\n');
00527     if ( !best_status_ ||
00528          current_status->objective_value() < best_status_->objective_value() ) {
00529       best_xform_estimate_ = current_xform_estimate_;
00530       if (best_scales_.size() != 1)
00531         best_scales_.resize(1);
00532       best_scales_[0] = scale;
00533       if (best_matches_.size() != 1)
00534         best_matches_.resize(1);
00535       best_matches_[0] = match_set;
00536       best_status_ = current_status;
00537       DebugMacro( 1, "Set best xform estimate\n" );
00538     }
00539   }
00540 }
00541 
00542 //: registration of multiple feature type at each stage/resolution
00543 void
00544 rgrl_feature_based_registration::
00545 register_multi_feature( rgrl_mask_box            from_image_region,
00546                         rgrl_mask_box            to_image_region,
00547                         rgrl_estimator_sptr      initial_xform_estimator,
00548                         rgrl_transformation_sptr xform_estimate,
00549                         rgrl_scale_sptr          prior_scale,
00550                         unsigned                 resolution )
00551 {
00552   rgrl_converge_status_sptr                     current_status;
00553   vcl_vector<rgrl_feature_set_sptr>             from_sets;
00554   vcl_vector<rgrl_feature_set_sptr>             to_sets;
00555   vcl_vector<rgrl_matcher_sptr>                 matchers;
00556   vcl_vector<rgrl_scale_estimator_unwgted_sptr> unwgted_scale_ests;
00557   vcl_vector<rgrl_scale_estimator_wgted_sptr>   wgted_scale_ests;
00558   vcl_vector<rgrl_weighter_sptr>                weighters;
00559   rgrl_set_of<rgrl_scale_sptr>                  scales;
00560   vcl_vector<rgrl_estimator_sptr>               xform_estimators;
00561   rgrl_estimator_sptr                           xform_estimator;
00562   bool                                          failed, scale_in_range, use_prior_scale;
00563   unsigned                                      prev_resol = 0;
00564 
00565   use_prior_scale = false;
00566   if ( prior_scale ) use_prior_scale = true;
00567   scale_in_range = true;
00568   failed = false;
00569   current_xform_estimate_ = xform_estimate;
00570 
00571   assert ( data_->has_stage( resolution ) );
00572 
00573   do { // for each stage/resolution
00574     data_->get_data_at_stage( resolution, from_sets, to_sets, matchers,
00575                               weighters, unwgted_scale_ests,
00576                               wgted_scale_ests, xform_estimators);
00577     current_stage_ = resolution;
00578     unsigned data_count = from_sets.size();
00579 
00580     DebugMacro(  1, " Current resolution "<< resolution <<'\n' );
00581 
00582     // Initialize the size of match_sets and scales to be the same as
00583     // the from_sets
00584     //
00585     current_match_sets_.clear();
00586     scales.clear();
00587     current_match_sets_.resize( data_count );
00588     scales.resize( data_count );
00589 
00590     // If no estimator found for the current stage, the default is
00591     // from the initializer. Feature_based can only deal with one
00592     // estimator in each stage/resolution. If more than one is found,
00593     // only the first is kept.
00594     //
00595     if ( xform_estimators.size() == 0 )
00596       xform_estimator = initial_xform_estimator;
00597     else xform_estimator = xform_estimators[0];
00598     assert ( xform_estimator );
00599 
00600     // If the initialization comes with a prior scale, initialize the
00601     // scales using the prior scale.
00602     //
00603     if ( use_prior_scale ) {
00604       DebugMacro(  2, "Prior scale = "<<prior_scale->geometric_scale()<<'\n' );
00605       for (  unsigned int fs = 0; fs < data_count; ++fs )
00606         scales[fs] = prior_scale;
00607     }
00608 
00609     iterations_at_stage_ = 0; //keeps track of total iter at level
00610     current_status = 0;
00611     bool should_estimate_scale = true;
00612     int  scale_est_count = 0;
00613 
00614     do { // for each re-matching
00615 
00616       DebugMacro(  2, " Computing matches and scales\n" );
00617       // Compute matches, and scales for each feature set.
00618       //
00619       for ( unsigned int fs=0; fs < data_count; ++fs ) {
00620         DebugMacro(  2, "   Data set " << fs << vcl_endl );
00621         rgrl_match_set_sptr new_matches =
00622           matchers[fs]->compute_matches( *from_sets[fs],
00623                                          *to_sets[fs],
00624                                          *current_xform_estimate_,
00625                                          from_image_region,
00626                                          to_image_region,
00627                                          *scales[fs] );
00628         DebugMacro(  2, "      Matches: " << new_matches->from_size() <<" ("<<new_matches<<")\n" );
00629 
00630         // For the first iteration, use prior scale or estimate the
00631         // scales without weights (since we don't have any...)
00632         //
00633         if ( iterations_for_scale_est_ >= 0 &&
00634              scale_est_count > iterations_for_scale_est_ ) {
00635           should_estimate_scale = false;
00636         }
00637 
00638         rgrl_scale_sptr new_scale = 0;
00639         if ( !should_estimate_scale ) {
00640           DebugMacro(  2, "No scale estimation\n" );
00641         }
00642         else if ( new_matches->from_size() == 0 ) {
00643           DebugMacro(0, "Empty match set!!!\n");
00644           failed = true;
00645           continue;
00646         }
00647         else { //should_estimate_scale && new_matches->from_size() > 0
00648           if ( !wgted_scale_ests[fs] ) {
00649             new_scale = unwgted_scale_ests[fs]->
00650               estimate_unweighted( *new_matches, scales[fs], should_penalize_scaling_ );
00651           } else {
00652             if ( iterations_at_stage_ == 0 && !scales[fs] ) {
00653               assert ( unwgted_scale_ests[fs] );
00654               new_scale = unwgted_scale_ests[fs]->
00655                 estimate_unweighted( *new_matches, scales[fs], should_penalize_scaling_);
00656             }
00657             else {
00658               weighters[fs]->compute_weights(*scales[fs], *new_matches);
00659               new_scale = wgted_scale_ests[fs]->
00660                 estimate_weighted( *new_matches, scales[fs], should_penalize_scaling_);
00661             }
00662           }
00663 
00664           if ( new_scale ) {
00665             DebugMacro(  2, "New geometric scale = "<<new_scale->geometric_scale()<<'\n' );
00666             if ( new_scale->has_geometric_scale() &&
00667                  new_scale->geometric_scale() < expected_min_geometric_scale_ ) {
00668               should_estimate_scale = false;
00669               if (!scales[fs]) scales[fs] = new_scale;
00670               scales[fs]->set_geometric_scale(expected_min_geometric_scale_);
00671               DebugMacro( 2, "Scale below expected_min_geometric_scale. Set to expected_min_geometric_scale.\n" );
00672             }
00673             else {
00674               scales[fs] = new_scale;
00675             }
00676             scale_est_count++;
00677           }
00678         }
00679         assert ( scales[fs] );
00680 
00681         // If the scale is above the upper bound of the expected
00682         // geometric scale return with failure
00683         if ( expected_max_geometric_scale_ > 0 &&
00684              scales[fs]->has_geometric_scale() &&
00685              scales[fs]->geometric_scale() > expected_max_geometric_scale_) {
00686           scale_in_range = false;
00687           failed = true;
00688         }
00689 
00690         // Keep new ones and discard old ones
00691         //
00692         current_match_sets_[fs] = new_matches;
00693       }
00694 
00695       DebugMacro(  2, " Estimate the transformation\n" );
00696 
00697       // Estimate the transformation using a simplified irls
00698       // (Iterative-Reweighted Least-Squares) routine.
00699       //
00700       // The match sets and the scales are fixed, but the associated
00701       // weights are updated (hence reweighted-least-squares)
00702       // throughout the estimation.
00703       if ( !rgrl_util_irls( current_match_sets_, scales, weighters,
00704                             *conv_tester_, xform_estimator,
00705                             current_xform_estimate_,
00706                             false,                   // no fast mapping
00707                             this->debug_flag() ) ) {
00708         failed = true;
00709         continue; //no valid xform, so exit the loop
00710       }
00711 
00712       // For debugging ...
00713       //
00714       this->invoke_event(rgrl_event_iteration());
00715 
00716       // Update the weights and scale estimates based on the new transform
00717       //
00718       DebugMacro(  2, " Updating scale estimates and checking for validity\n" );
00719       for ( unsigned int fs=0; fs < data_count; ++fs ) {
00720         if ( current_match_sets_[fs]->from_size() > 0 ) {
00721           current_match_sets_[fs]->remap_from_features( *current_xform_estimate_ );
00722           weighters[fs]->compute_weights( *scales[fs], *current_match_sets_[fs] );
00723 
00724       // compute image scaling factors
00725       {
00726         bool ret_success;
00727         vnl_vector<double> scaling;
00728         ret_success = rgrl_util_geometric_scaling_factors( current_match_sets_, scaling );
00729         if ( ret_success ) {
00730           current_xform_estimate_->set_scaling_factors( scaling );
00731           if (should_penalize_scaling_) {
00732             for ( unsigned ds=0; ds < scaling.size(); ++ds ) {
00733               if (scaling[ds] < 1e-5) {
00734                 DebugMacro(  1," Scaling of dimension "<<ds<<" too high\n");
00735                 failed = true;
00736               }
00737             }
00738           }
00739         }
00740         else
00741           WarningMacro( "cannot compute scaling factors!!!" );
00742       }
00743 
00744 #if 0
00745           // CT: this step seems redundant, since the scale is re-computed
00746           // at the beginning of next iteration.
00747           if ( should_estimate_scale ) {
00748             if ( !wgted_scale_ests[fs] )
00749               scales[fs] = unwgted_scale_ests[fs]->
00750                 estimate_unweighted( *current_match_sets_[fs], scales[fs], should_penalize_scaling_ );
00751             else scales[fs] = wgted_scale_ests[fs]->
00752                    estimate_weighted( *current_match_sets_[fs], scales[fs], should_penalize_scaling_ );
00753             DebugMacro(  2, " Geometric scale after converged = "<< scales[fs]->geometric_scale()<<'\n' );
00754           }
00755 #endif // 0
00756         }
00757       }
00758 
00759       // Perform convergence test
00760       //
00761       DebugMacro(  2, " Perform convergence test\n" );
00762       current_status =
00763         conv_tester_->compute_status( current_status,
00764                                       current_xform_estimate_,
00765                                       xform_estimator,
00766                                       current_match_sets_, scales,
00767                                       should_penalize_scaling_);
00768       DebugMacro( 3, "run: (iterations = " << iterations_at_stage_ << ") oscillation count = " << current_status->oscillation_count() << '\n' );
00769       DebugMacro( 3, "run: error = " << current_status->error() << vcl_endl );
00770       DebugMacro( 3, "run: error_diff = " << current_status->error_diff() << vcl_endl );
00771 
00772       ++iterations_at_stage_;
00773     }
00774     while ( !failed &&
00775             !current_status->has_converged() &&
00776             !current_status->has_stagnated() &&
00777             iterations_at_stage_ < max_icp_iter_ );
00778 
00779       if ( failed ) {
00780         if ( !scale_in_range )
00781           DebugMacro(  2, " Geometric scale above the expected value\n" );
00782         else
00783           DebugMacro(  2, " Failed with empty match set, or feature_based\n" );
00784         continue;
00785       }
00786       if ( current_status->has_converged() )
00787         DebugMacro( 1, " CONVERGED\n" );
00788       if ( current_status->has_stagnated() )
00789         DebugMacro( 1, " STAGNATED\n" );
00790       if ( iterations_at_stage_ == max_icp_iter_ )
00791         DebugMacro( 1, " ICP iteration reached maximum ("<<max_icp_iter_<<" )\n" );
00792 
00793       // Move to the next resolution with proper initialization if not
00794       // already at the finest level
00795       //
00796       prev_resol = resolution;
00797       initialize_for_next_resolution( from_image_region, to_image_region,
00798                                       current_xform_estimate_, resolution );
00799       int level_diff = prev_resol - resolution;
00800       double dim_increase = data_->dimension_increase_for_next_stage(prev_resol);
00801       double scale_multipler = vcl_pow(dim_increase, level_diff);
00802       for ( unsigned int fs=0; fs < data_count; ++fs ) {
00803         scales[fs]->set_geometric_scale( scales[fs]->geometric_scale()*scale_multipler );
00804       }
00805 
00806       use_prior_scale = true;
00807       prior_scale = scales[0]; //Assuming scales[0] is a good approximate
00808   }
00809   while ( !failed && ( resolution != 0 || prev_resol != 0) );
00810 
00811   DebugMacro( 1, "Estimation complete\n" );
00812 
00813   //   At this point the iterations are over for this initial
00814   //   estimate.  If the estimation is successful, and if it is the
00815   //   first one tested or it is the best seen thus far, record
00816   //   information about this estimate.
00817   //
00818 
00819   if ( !failed ){
00820     DebugMacro( 1, "Obj value after convergence = "<<current_status->objective_value()<<'\n');
00821     if ( !best_status_ ||
00822          current_status->objective_value() < best_status_->objective_value() ) {
00823       best_xform_estimate_ = current_xform_estimate_;
00824       best_scales_         = scales;
00825       best_matches_        = current_match_sets_;
00826       best_status_         = current_status;
00827       DebugMacro( 1, "Set best xform estimate\n" );
00828     }
00829   }
00830 }
00831 
00832 
00833 void
00834 rgrl_feature_based_registration::
00835 initialize_for_next_resolution(  rgrl_mask_box            & from_image_region,
00836                                  rgrl_mask_box            & to_image_region,
00837                                  rgrl_transformation_sptr & xform_estimate,
00838                                  unsigned                 & current_resol ) const
00839 {
00840   // Find the next available level
00841   //
00842   unsigned new_resol = current_resol;
00843   int next_resol = new_resol - 1;
00844   for ( ; next_resol >=0 ; --next_resol) {
00845     if ( data_->has_stage(next_resol) ) {
00846       new_resol = next_resol;
00847       break;
00848     }
00849   }
00850 
00851   // If no next available level return
00852   //
00853   if ( new_resol == current_resol ) return;
00854 
00855 
00856   // Scale the components of the current view for the initial view of the next
00857   // available level
00858   //
00859   int level_diff = current_resol - new_resol;
00860   double dim_increase = data_->dimension_increase_for_next_stage(current_resol);
00861   double scale = vcl_pow(dim_increase, level_diff);
00862 
00863   from_image_region.set_x0( from_image_region.x0()*scale );
00864   from_image_region.set_x1( from_image_region.x1()*scale );
00865 
00866   xform_estimate =  xform_estimate->scale_by( scale );
00867   current_resol = new_resol;
00868 }