contrib/rpl/rgrl/rgrl_scale_est_closest.cxx
Go to the documentation of this file.
00001 //:
00002 // \file
00003 // \author Chuck Stewart
00004 
00005 #include "rgrl_scale_est_closest.h"
00006 
00007 #include <rrel/rrel_objective.h>
00008 #include <vnl/vnl_math.h>
00009 
00010 #include "rgrl_scale.h"
00011 #include "rgrl_match_set.h"
00012 #include "rgrl_util.h"
00013 
00014 #include <vcl_iostream.h>
00015 #include <vcl_cassert.h>
00016 
00017 rgrl_scale_est_closest::
00018 rgrl_scale_est_closest( vcl_auto_ptr<rrel_objective>  obj,
00019                         bool                          do_signature_scale )
00020   : do_signature_scale_( do_signature_scale ),
00021     obj_( obj )
00022 {
00023   assert( obj_->can_estimate_scale() );
00024 }
00025 
00026 
00027 rgrl_scale_est_closest::
00028 ~rgrl_scale_est_closest()
00029 {
00030 }
00031 
00032 
00033 rgrl_scale_sptr
00034 rgrl_scale_est_closest::
00035 estimate_unweighted( rgrl_match_set const& match_set,
00036                      rgrl_scale_sptr const& /*current_scales*/,
00037                      bool penalize_scaling ) const
00038 {
00039   rgrl_scale_sptr scales = new rgrl_scale;
00040 
00041   double scale = -1.0;
00042   vnl_matrix<double> inv_covar;
00043   
00044   if( compute_geometric_scale( scale, match_set, penalize_scaling ) )
00045     scales->set_geometric_scale( scale );
00046 
00047   if ( do_signature_scale_ && compute_signature_inv_covar( inv_covar, match_set ) ) {
00048     scales->set_signature_inv_covar( inv_covar );
00049   }
00050 
00051   return scales;
00052 }
00053 
00054 
00055 bool
00056 rgrl_scale_est_closest::
00057 compute_geometric_scale( double& return_scale,
00058                          rgrl_match_set const& match_set,
00059                          bool penalize_scaling ) const
00060 {
00061   typedef rgrl_match_set::const_from_iterator from_iter;
00062   typedef from_iter::to_iterator              to_iter;
00063 
00064   double scaling = 1;
00065   if ( penalize_scaling ) {
00066     // scaling applied here to penalize xform with distortion
00067     scaling =  rgrl_util_geometric_error_scaling( match_set );
00068   }
00069 
00070   vcl_vector<double> error_distances;
00071   error_distances.reserve( match_set.from_size() );
00072   DebugMacro(1, "\n");
00073 
00074   for ( from_iter fitr = match_set.from_begin(); fitr != match_set.from_end(); ++fitr ) {
00075     //  If there aren't any matches, set the error_distance to an
00076     //  arbitrarily large number.
00077     if ( fitr.empty() ) {
00078       DebugMacro_abv(1," no matched points for from: "<< fitr.from_feature()->location()<< ", set its error distances = 1.0e30\n");
00079       error_distances.push_back( 1.0e30 );
00080     } else {
00081       to_iter titr = fitr.begin();
00082 
00083       rgrl_feature_sptr mapped_from = fitr.mapped_from_feature();
00084       double min_distance = titr.to_feature()->geometric_error( *mapped_from );
00085 
00086       for ( ++titr; titr != fitr.end(); ++titr ) {
00087         double distance = titr.to_feature()->geometric_error( *mapped_from );
00088         if ( distance < min_distance ) {
00089           min_distance = distance;
00090         }
00091       }
00092       error_distances.push_back( min_distance );
00093     }
00094   }
00095 
00096 #if 0 // commented out
00097   vcl_cout << " error_distance :\n" << vcl_endl;
00098   unsigned zeros = 0;
00099   for ( unsigned i = 0; i < error_distances.size(); ++i ) {
00100     if ( error_distances[ i ] == 0 )
00101       ++zeros;
00102     vcl_cout << error_distances[ i ] << vcl_endl;
00103   }
00104   vcl_cout << " number of zers : " << zeros << " out of " << error_distances.size() << vcl_endl;
00105 #endif // 0
00106 
00107   // empty set
00108   if( error_distances.empty() )
00109     return false;
00110     
00111   const double epsilon = 1e-16;
00112   return_scale = scaling * vnl_math_max( obj_->scale( error_distances.begin(), error_distances.end() ), epsilon );
00113 
00114   // is finite?
00115   if( !vnl_math_isfinite( return_scale ) )
00116     return false;
00117   
00118   // success
00119   return true;
00120 }
00121 
00122 bool
00123 rgrl_scale_est_closest::
00124 compute_signature_inv_covar( vnl_matrix<double>& inv_covar, rgrl_match_set const& match_set ) const
00125 {
00126   if( !match_set.from_size() ) return false;
00127     
00128   //  Do the same as above, one component at a time, BUT use the
00129   //  closest geometric feature to determine which signature vector to
00130   //  use.  (We really need to do better.)  This yields a diagonal
00131   //  matrix.  Be sure to set the size of the matrix.
00132 
00133   typedef rgrl_match_set::const_from_iterator from_iter;
00134   typedef from_iter::to_iterator              to_iter;
00135 
00136   from_iter fitr = match_set.from_begin();
00137   const unsigned nrows = fitr.from_feature()->signature_error_dimension( match_set.to_feature_type() );
00138   
00139   // check on the error vector dimension
00140   if( !nrows ) return false;
00141 
00142   vcl_vector< vcl_vector<double> > all_errors( nrows );
00143   bool success = true;
00144 
00145   for ( ; fitr != match_set.from_end(); ++fitr ) {
00146     //  If there aren't any matches, set the error_distance to an
00147     //  arbitrarily large number.
00148     if ( fitr.empty() ) {
00149       for ( unsigned r=0; r<nrows; ++r ) {
00150         all_errors[r].push_back( 1.0e30 );
00151       }
00152     } else {
00153       to_iter titr = fitr.begin();
00154       to_iter best_titr = titr;
00155 
00156       rgrl_feature_sptr mapped_from = fitr.mapped_from_feature();
00157       double min_distance = titr.to_feature()->geometric_error( *mapped_from );
00158 
00159       for ( ++titr; titr != fitr.end(); ++titr ) {
00160         double distance = titr.to_feature()->geometric_error( *mapped_from );
00161         if ( distance < min_distance ) {
00162           min_distance = distance;
00163           best_titr = titr;
00164         }
00165       }
00166 
00167       vnl_vector<double> signature_error = best_titr.to_feature()->signature_error_vector( *mapped_from );
00168       for ( unsigned r = 0; r < nrows; ++r ) {
00169         all_errors[r].push_back( signature_error[r] );
00170       }
00171     }
00172   }
00173 
00174   inv_covar.set_size( nrows, nrows );
00175   inv_covar.fill( 0.0 );
00176 
00177   for ( unsigned r = 0; r < nrows&&success; ++r ) {
00178     
00179     if( all_errors[r].empty() ) {
00180       success = false;
00181       break;
00182     }
00183     
00184     const double std = obj_->scale( all_errors[r].begin(), all_errors[r].end() );
00185     success = success && vnl_math_isfinite( std );
00186     if( std < 1e-10 )  // if variance is too small
00187       inv_covar(r,r) = 0.0;
00188     else
00189       inv_covar(r,r) = 1 / vnl_math_sqr( std );
00190   }
00191 
00192   return success;
00193 }
00194 
00195 
00196 rgrl_scale_sptr
00197 rgrl_scale_est_closest::
00198 estimate_weighted( rgrl_match_set const& match_set,
00199                    rgrl_scale_sptr const& scales,
00200                    bool /*use_signature_only*/,
00201                    bool penalize_scaling ) const
00202 {
00203   return estimate_unweighted( match_set, scales, penalize_scaling );
00204 }