contrib/rpl/rgrl/rgrl_matcher_k_nearest_adv.cxx
Go to the documentation of this file.
00001 #include "rgrl_matcher_k_nearest_adv.h"
00002 //:
00003 // \file
00004 // \author Gehua Yang
00005 // \date   Dec 2006
00006 
00007 #include <rgrl/rgrl_feature.h>
00008 #include <rgrl/rgrl_feature_set.h>
00009 #include <rgrl/rgrl_transformation.h>
00010 #include <rgrl/rgrl_view.h>
00011 #include <rgrl/rgrl_match_set.h>
00012 // not used? #include <vcl_vector.h>
00013 #include <vcl_map.h>
00014 #include <vcl_cassert.h>
00015 
00016 //-----------------------------------------------
00017 //: a struct for fast look up of the from feature
00018 struct feature_sptr_iterator_pair {
00019 
00020   typedef rgrl_match_set::const_from_iterator  from_feature_iterator;
00021   rgrl_feature_sptr                   feature_;
00022   from_feature_iterator               fea_iterator_;
00023 
00024   feature_sptr_iterator_pair()
00025   { }
00026 
00027   feature_sptr_iterator_pair( rgrl_feature_sptr const& fea, from_feature_iterator const& it )
00028   : feature_( fea), fea_iterator_( it )
00029   { }
00030 
00031   bool operator< ( feature_sptr_iterator_pair const& rhs ) const
00032   { return this->feature_ < rhs.feature_; }
00033 
00034   bool operator== ( feature_sptr_iterator_pair const& rhs ) const
00035   { return this->feature_ == rhs.feature_; }
00036 };
00037 
00038 rgrl_matcher_k_nearest_adv::
00039 rgrl_matcher_k_nearest_adv( unsigned int k )
00040   : rgrl_matcher_k_nearest(k),
00041     min_mapped_scale_( -1 ),
00042     sqr_thres_for_reuse_match_( -1 )
00043 {
00044 }
00045 
00046 
00047 rgrl_matcher_k_nearest_adv::
00048 rgrl_matcher_k_nearest_adv( unsigned int k, double dist_thres, double min_mapped_scale, double thres_reuse_match )
00049   : rgrl_matcher_k_nearest( k, dist_thres ),
00050     min_mapped_scale_( min_mapped_scale ),
00051     sqr_thres_for_reuse_match_( thres_reuse_match )
00052 {
00053   if ( sqr_thres_for_reuse_match_ > 0 )
00054     sqr_thres_for_reuse_match_ = sqr_thres_for_reuse_match_*sqr_thres_for_reuse_match_;
00055 }
00056 
00057 
00058 rgrl_match_set_sptr
00059 rgrl_matcher_k_nearest_adv::
00060 compute_matches( rgrl_feature_set const&       from_set,
00061                  rgrl_feature_set const&       to_set,
00062                  rgrl_view const&              current_view,
00063                  rgrl_transformation const&    current_xform,
00064                  rgrl_scale const&             /* current_scale */,
00065                  rgrl_match_set_sptr const&    old_matches )
00066 {
00067   typedef rgrl_view::feature_vector feat_vector;
00068   typedef feat_vector::const_iterator feat_iter;
00069 
00070   assert( current_view.xform_estimate().as_pointer() == &current_xform );
00071 
00072   // faster to check a boolean variable
00073   const bool allow_reuse_match = ( sqr_thres_for_reuse_match_ > 0) && (prev_xform_) && (old_matches);
00074 
00075   // create a map for from feature and the match iterator
00076   //
00077   typedef rgrl_match_set::const_from_iterator  from_feature_iterator;
00078   vcl_map< rgrl_feature_sptr, from_feature_iterator > feature_sptr_iterator_map;
00079   if ( allow_reuse_match )
00080   {
00081     for ( from_feature_iterator i=old_matches->from_begin(); i!=old_matches->from_end(); ++i )
00082       feature_sptr_iterator_map[ i.from_feature() ] = i;
00083   }
00084 
00085   // create the new match set
00086   //
00087   rgrl_match_set_sptr matches_sptr
00088     = new rgrl_match_set( from_set.type(), to_set.type(), from_set.label(), to_set.label() );
00089 
00090   //  get the features in the current view
00091   feat_vector from;
00092   if ( !current_view.features_in_region( from, from_set ) ) {
00093     DebugMacro( 1, "Cannot get features in current region!!!\n");
00094     return matches_sptr;
00095   }
00096 
00097   // reserve size
00098   feat_vector matching_features, pruned_set;
00099   matching_features.reserve( 10 );
00100   pruned_set.reserve( 10 );
00101 
00102   matches_sptr->reserve( from.size() );
00103 
00104   //  generate the matches for each feature of this feature type in the current region
00105   vnl_vector<double> prev_mapped;
00106   int reuse_match_count = 0;
00107   for ( feat_iter fitr = from.begin(); fitr != from.end(); ++fitr )
00108   {
00109     rgrl_feature_sptr mapped = (*fitr)->transform( current_xform );
00110     if ( !validate( mapped, current_view.to_image_roi() ) )
00111       continue;   // feature is invalid
00112 
00113     matching_features.clear();
00114 
00115     if ( allow_reuse_match )
00116     {
00117       prev_xform_->map_location( (*fitr)->location(), prev_mapped );
00118 
00119       // if the mapping difference is smaller than this threshold
00120       vcl_map< rgrl_feature_sptr, from_feature_iterator >::const_iterator map_itr;
00121       if ( vnl_vector_ssd( prev_mapped, mapped->location() ) < sqr_thres_for_reuse_match_  &&
00122            (map_itr=feature_sptr_iterator_map.find( *fitr )) != feature_sptr_iterator_map.end() )
00123       {
00124         // re-use the to features
00125         const from_feature_iterator& prev_from_iter = map_itr->second;
00126         for ( from_feature_iterator::to_iterator titr=prev_from_iter.begin(); titr!=prev_from_iter.end(); ++titr )
00127           matching_features.push_back( titr.to_feature() );
00128 
00129         // increament the count
00130         ++reuse_match_count;
00131       }
00132       else
00133         to_set.k_nearest_features( matching_features, mapped, k_ );
00134     }
00135     else
00136       to_set.k_nearest_features( matching_features, mapped, k_ );
00137 
00138     // prune the matches to satisfy the threshold
00139     //
00140     if ( thres_ > 0 ) {
00141       pruned_set.clear();
00142       for ( feat_iter i = matching_features.begin(); i != matching_features.end(); ++i ) {
00143         if ( vnl_vector_ssd( (*i)->location(), mapped->location() ) < thres_ ) {
00144           pruned_set.push_back( *i );
00145         }
00146       }
00147       if ( !pruned_set.empty() ) {
00148         matches_sptr->add_feature_and_matches( *fitr, mapped,
00149                                                pruned_set );
00150       }
00151     } else {
00152       matches_sptr->add_feature_and_matches( *fitr, mapped,
00153                                              matching_features );
00154     }
00155   }
00156 
00157   DebugMacro( 1, "There are " << reuse_match_count << " reuse of previous matches out of " << from.size() << vcl_endl );
00158 
00159   // store xform
00160   prev_xform_ = current_view.xform_estimate();
00161 
00162   return matches_sptr;
00163 }
00164 
00165 inline
00166 bool
00167 rgrl_matcher_k_nearest_adv::
00168 validate( rgrl_feature_sptr const& mapped, rgrl_mask_sptr const& roi_sptr ) const
00169 {
00170   // if the mapped point is not in the image
00171   if ( !roi_sptr->inside( mapped->location() ) )
00172     return false;
00173 
00174   // Suppose scale=1 is the lowest scale, or the finest resolution
00175   // Any mapped scale below 1 cannot find any correspondence
00176   // due to the pixel discretization.
00177   // In practice, the threshold is a number less than one,
00178   // as feature of real scale=0.9 is still likely to be detected.
00179 
00180   // if the scale is too small to be detected on the other image
00181   const double scale = mapped->scale();
00182   if ( scale!=0 && min_mapped_scale_>0 && scale<min_mapped_scale_ ) {
00183     return false;
00184   }
00185 
00186   // by default,
00187   return true;
00188 }