contrib/rpl/rgrl/rgrl_convergence_on_weighted_error.cxx
Go to the documentation of this file.
00001 #include "rgrl_convergence_on_weighted_error.h"
00002 //:
00003 // \file
00004 #include <vcl_cassert.h>
00005 
00006 #include <rgrl/rgrl_match_set.h>
00007 #include <rgrl/rgrl_set_of.h>
00008 #include <rgrl/rgrl_converge_status.h>
00009 #include <rgrl/rgrl_view.h>
00010 #include <rgrl/rgrl_util.h>
00011 
00012 rgrl_convergence_on_weighted_error::
00013 rgrl_convergence_on_weighted_error( double tol )
00014   : tolerance_( tol )
00015 {
00016 }
00017 
00018 rgrl_convergence_on_weighted_error::
00019 ~rgrl_convergence_on_weighted_error()
00020 {
00021 }
00022 
00023 rgrl_converge_status_sptr
00024 rgrl_convergence_on_weighted_error::
00025 compute_status( rgrl_converge_status_sptr               prev_status,
00026                 rgrl_view                        const& prev_view,
00027                 rgrl_view                        const& current_view,
00028                 rgrl_set_of<rgrl_match_set_sptr> const& current_match_sets,
00029                 rgrl_set_of<rgrl_scale_sptr>     const& /*current_scales*/,
00030                 bool                                    penalize_scaling) const
00031 {
00032   // Step2: Take the weighted average of errors as the objective
00033   //        value.  To avoid the low error given by an infeasible
00034   //        transformation, the error is scaled by the scaling of
00035   //        the spread of the transformed data points
00036   //
00037   double scaling = 1;
00038   if ( penalize_scaling ) {
00039     scaling =  rgrl_util_geometric_error_scaling( current_match_sets );
00040     DebugMacro(1, "geometric_error_scaling = "<<scaling<<'\n');
00041   }
00042 
00043   double new_error = scaling * compute_alignment_error( current_match_sets );
00044 
00045   bool good = new_error < tolerance_;
00046 
00047   return compute_status_helper( new_error, good, prev_status, prev_view, current_view );
00048 }
00049 
00050 double
00051 rgrl_convergence_on_weighted_error::
00052 compute_alignment_error( rgrl_set_of<rgrl_match_set_sptr> const& current_match_sets ) const
00053 {
00054   typedef rgrl_match_set::const_from_iterator from_iter;
00055   typedef from_iter::to_iterator              to_iter;
00056 
00057   // Step1: Compute the errors of all matches. The weights of the
00058   //        matches are precomputed.
00059   //
00060   double error_sum = 0, weight_sum = 0;
00061   double error, weight;
00062   for ( unsigned ds=0; ds < current_match_sets.size(); ++ds ) {
00063     rgrl_match_set const& ms = *current_match_sets[ds];
00064     for ( from_iter fitr = ms.from_begin(); fitr != ms.from_end(); ++fitr ) {
00065       //rgrl_feature_sptr mapped = fitr.from_feature()->transform( *current_xform );
00066       rgrl_feature_sptr mapped = fitr.mapped_from_feature();
00067       for ( to_iter titr = fitr.begin(); titr != fitr.end(); ++titr )
00068       {
00069         error = titr.to_feature()->geometric_error( *mapped );
00070         weight = titr.cumulative_weight(); //take the precomputed wgt
00071 
00072         error_sum += error * weight;
00073         weight_sum += weight;
00074       }
00075     }
00076   }
00077   return error_sum/weight_sum;
00078 }
00079 
00080 
00081 double
00082 rgrl_convergence_on_weighted_error::
00083 compute_alignment_error( rgrl_match_set_sptr const& current_match_set ) const
00084 {
00085   assert( current_match_set );
00086 
00087   typedef rgrl_match_set::const_from_iterator from_iter;
00088   typedef from_iter::to_iterator              to_iter;
00089 
00090   // Step1: Compute the errors of all matches. The weights of the
00091   //        matches are precomputed.
00092   //
00093   double error_sum = 0, weight_sum = 0;
00094   double error, weight;
00095   rgrl_match_set const& ms = *current_match_set;
00096   for ( from_iter fitr = ms.from_begin(); fitr != ms.from_end(); ++fitr ) {
00097     //rgrl_feature_sptr mapped = fitr.from_feature()->transform( *current_xform );
00098     rgrl_feature_sptr mapped = fitr.mapped_from_feature();
00099     for ( to_iter titr = fitr.begin(); titr != fitr.end(); ++titr )
00100     {
00101       error = titr.to_feature()->geometric_error( *mapped );
00102       weight = titr.cumulative_weight(); //take the precomputed wgt
00103 
00104       error_sum += error * weight;
00105       weight_sum += weight;
00106     }
00107   }
00108 
00109   return error_sum/weight_sum;
00110 }
00111 
00112 //: verify the final alignment
00113 rgrl_converge_status_sptr
00114 rgrl_convergence_on_weighted_error::
00115 verify( rgrl_transformation_sptr         const& /*xform_estimate*/,
00116         rgrl_set_of<rgrl_match_set_sptr> const& current_match_sets,
00117         rgrl_set_of<rgrl_scale_sptr>     const& /*current_scales*/ )const
00118 {
00119   //
00120   // this should be penalized by the scaling as well.
00121   // However, I don't like current implementation that
00122   // bool penalize_scaling is passed on every function.
00123   // I think it should be made a member variable at construction
00124   // time.
00125   // GY
00126 
00127   double error = compute_alignment_error( current_match_sets );
00128 
00129   bool good_enough_to_terminate = error < tolerance_;
00130   rgrl_converge_status_sptr status = new rgrl_converge_status( true, false, good_enough_to_terminate,
00131                                                                !good_enough_to_terminate, error, 0, 0 );
00132   if ( good_enough_to_terminate )
00133   {
00134     status -> set_current_status( rgrl_converge_status::good_and_terminate );
00135   }
00136   else
00137   {
00138     // imitate the previous behavior
00139     // if it is not good enough to terminate it is still good result
00140     status -> set_current_status( rgrl_converge_status::good_enough );
00141   }
00142 
00143   return status;
00144 }