contrib/rpl/rgrl/rgrl_weighter_indiv_scale.cxx
Go to the documentation of this file.
00001 #include "rgrl_weighter_indiv_scale.h"
00002 //:
00003 // \file
00004 // \author Gehua Yang
00005 // \date   March 2006
00006 
00007 #include <vcl_cmath.h>
00008 #include <vcl_cassert.h>
00009 #include <vnl/vnl_matrix.h>
00010 #include <rrel/rrel_m_est_obj.h>
00011 
00012 #include <rgrl/rgrl_match_set.h>
00013 #include <rgrl/rgrl_scale.h>
00014 #include <rgrl/rgrl_transformation.h>
00015 
00016 rgrl_weighter_indiv_scale::
00017 rgrl_weighter_indiv_scale( vcl_auto_ptr<rrel_m_est_obj>  m_est,
00018                      bool                          use_signature_error,
00019                      bool                          use_precomputed_signature_wgt )
00020  :rgrl_weighter_m_est( m_est, use_signature_error, use_precomputed_signature_wgt )
00021 {
00022 }
00023 
00024 
00025 rgrl_weighter_indiv_scale::
00026 ~rgrl_weighter_indiv_scale()
00027 {
00028 }
00029 
00030 
00031 void
00032 rgrl_weighter_indiv_scale::
00033 compute_weights( rgrl_scale const&  scales,
00034                  rgrl_match_set&    match_set ) const
00035 {
00036   //  Cache the inverse covariance of the signature error if signature
00037   //  errors are used.  Be careful of null entries.
00038 
00039   vnl_matrix<double> signature_inv_covar;
00040   if ( use_signature_error_ && !signature_precomputed_ ) {
00041     assert ( scales.has_signature_inv_covar() );
00042     signature_inv_covar = scales.signature_inv_covar();
00043   }
00044 
00045   //  cache the geometric scale.
00046   assert ( scales.has_geometric_scale() );
00047   double geometric_scale = scales.geometric_scale();
00048 
00049   typedef rgrl_match_set::from_iterator from_iter;
00050   typedef from_iter::to_iterator        to_iter;
00051 
00052   DebugMacro(1,'\n');
00053   DebugMacro_abv(1, "Matched points : from\t to\t geo_err\t geo_wgt\t cum_wgt:\n" );
00054 
00055   //  for each from image feature being matched
00056   for ( from_iter fitr = match_set.from_begin();
00057        fitr != match_set.from_end(); ++fitr ) {
00058 
00059     DebugMacro_abv(1, fitr.from_feature()->location() << '\t');
00060     if ( fitr.empty() ) DebugMacro_abv(2, '\n' );
00061 
00062     if ( fitr.size() == 0 )  continue;
00063 
00064     double sum_weights = 0; // for normalizing, later
00065     rgrl_feature_sptr mapped_from = fitr.mapped_from_feature();
00066 
00067     for ( to_iter titr = fitr.begin(); titr != fitr.end(); ++titr )
00068     {
00069       DebugMacro_abv( 1, titr.to_feature()->location() << "\t " );
00070 
00071       //  for each match with a "to" image feature
00072       rgrl_feature_sptr to_feature = titr.to_feature();
00073       const double scaled_err = to_feature->geometric_error( *mapped_from );
00074 
00075       // It is important to factor in the feature scale, along with geometric scale
00076       // As the error projector is already divided by feature scale square,
00077       //
00078       const double geometric_wgt = m_est_->wgt( scaled_err, geometric_scale );
00079 
00080       DebugMacro_abv(1, scaled_err << "\t " << geometric_wgt << "\t " );
00081 
00082       double signature_wgt = 1.0;
00083       if ( signature_precomputed_ ) {
00084         signature_wgt = titr . signature_weight( );
00085       }
00086       else if ( use_signature_error_ ) {
00087         vnl_vector<double> error_vector = to_feature->signature_error_vector( *mapped_from );
00088         assert ( error_vector.size() > 0 );
00089         double signature_err = vcl_sqrt( dot_product( error_vector * signature_inv_covar, error_vector ) );
00090         // CS: we may need to add some chi-squared normalization here for large signature vectors.
00091         signature_wgt = m_est_->wgt( signature_err );  // already normalized at this point
00092       }
00093 
00094       double cumul_wgt = geometric_wgt * signature_wgt;
00095 
00096       DebugMacro_abv(1, cumul_wgt << vcl_endl );
00097 
00098       titr.set_geometric_weight( geometric_wgt );
00099       if ( !signature_precomputed_ ) titr.set_signature_weight( signature_wgt );
00100       titr.set_cumulative_weight( cumul_wgt );
00101       sum_weights += cumul_wgt;
00102     }
00103 
00104     // Now, assign the cumulative weights for each match by scaling
00105     // the initial cumulative weight by the fraction of the total
00106     // cumulative weight.
00107     // If weight_more_on_distinct_match_ is set,
00108     // a feature with more matches will be penalized for the
00109     // ambiguity, and a feature with a unique match will not be
00110     // affected at all.
00111 
00112     if ( sum_weights > 1e-16 ) { //sum_weights not approaching 0
00113       if ( weight_more_on_distinct_match_ )
00114         for ( to_iter titr = fitr.begin(); titr != fitr.end(); ++titr ) {
00115           double wgt = titr.cumulative_weight();
00116             titr.set_cumulative_weight( wgt*wgt / sum_weights );
00117         }
00118       else
00119         for ( to_iter titr = fitr.begin(); titr != fitr.end(); ++titr ) {
00120           double wgt = titr.cumulative_weight();
00121             titr.set_cumulative_weight( wgt / sum_weights );
00122         }
00123     }
00124   }
00125 }
00126 
00127 // It is unclear how to handle multiple matches.
00128 // The current method is to pick the one with minimum distance
00129 // and evaluate the likelihood based on that.
00130 //
00131 double
00132 rgrl_weighter_indiv_scale::
00133 aux_sum_rho_values( rgrl_scale const&  scale,
00134                     rgrl_match_set&    match_set,
00135                     rgrl_transformation const&  xform )
00136 {
00137   typedef rgrl_match_set::from_iterator  from_iter;
00138   typedef from_iter::to_iterator         to_iter;
00139 
00140   if ( match_set.from_size() == 0 ) return 0;
00141 
00142   double sum_rho = 0;
00143 
00144   for ( from_iter fitr = match_set.from_begin(); fitr != match_set.from_end(); ++fitr )
00145   {
00146     if ( fitr.size() == 0 )  continue;
00147 
00148     rgrl_feature_sptr mapped_from = fitr.from_feature()->transform( xform );
00149     to_iter titr = fitr.begin();
00150     double min_val = titr.to_feature()->geometric_error( *mapped_from );
00151     double fea_scale = titr.to_feature()->scale();
00152 
00153     for ( ++titr; titr != fitr.end(); ++titr ) {
00154       //  for each match with a "to" image feature
00155       rgrl_feature_sptr to_feature = titr.to_feature();
00156       const double scaled_err = to_feature->geometric_error( *mapped_from );
00157 
00158       // signature weight
00159       //
00160       //GY: don't know how to handle this in a correct way
00161       // double signature_wgt = 1.0;
00162       //if ( signature_precomputed_ ) {
00163       //  signature_wgt = titr . signature_weight( );
00164       //}
00165 
00166       if ( min_val > scaled_err ) {
00167         min_val = scaled_err;
00168         fea_scale = to_feature->scale();
00169       }
00170     }
00171     // sum of rho is weighted by signature??
00172     sum_rho += vcl_log(fea_scale) +
00173                m_est_->rho(min_val, scale.geometric_scale()*fea_scale);
00174   }
00175 
00176   return sum_rho;
00177 }