contrib/rpl/rrel/rrel_util.txx
Go to the documentation of this file.
00001 // This is rpl/rrel/rrel_util.txx
00002 #ifndef rrel_util_txx_
00003 #define rrel_util_txx_
00004 
00005 #include "rrel_util.h"
00006 
00007 #include <vcl_cassert.h>
00008 #include <vcl_cmath.h>
00009 #include <vcl_algorithm.h>
00010 #include <vcl_vector.h>
00011 
00012 #include <vnl/vnl_math.h>
00013 
00014 
00015 template <class O, class T>
00016 O
00017 rrel_util_median_abs_dev_scale( const T& begin,  const T& end, int dof, O* /*dummy*/ )
00018 {
00019   long count = long(end - begin); // VC6 & 7 has broken iterator_traits
00020   assert( count > 0);
00021 
00022   if ( count <= dof )
00023     return 0;
00024 
00025   for ( T i=begin; i!=end; ++i ) {
00026     *i = vnl_math_abs( *i );
00027   }
00028   T loc = begin + ((count-dof)/2 + dof);
00029   vcl_nth_element( begin, loc, end );
00030   return O (1.4826 * (1 + 5.0/(count-dof)) * *loc);
00031 }
00032 
00033 
00034 template <class O, class T>
00035 O
00036 rrel_util_weighted_scale( const T& residuals_first, const T& residuals_end,
00037                           const T& weights_first, int dof, O* /*dummy*/ )
00038 {
00039   O sum = 0;
00040   O sum_weights = 0;
00041   int num = 0;
00042 
00043   T r_itr = residuals_first;
00044   T w_itr = weights_first;
00045   for ( ; r_itr != residuals_end; ++ r_itr, ++ w_itr ) {
00046     sum += *w_itr * vnl_math_sqr( *r_itr );
00047     sum_weights += *w_itr;
00048     ++num;
00049   }
00050   if ( num <= dof )
00051     return 0;
00052 
00053   O divisor = sum_weights * ( num - dof ) / num;
00054   return vcl_sqrt( sum / divisor );
00055 }
00056 
00057 
00058 template <class T, class Ran>
00059 void rrel_util_median_and_scale( Ran first, Ran last,
00060                                  T& median, T& scale,
00061                                  int dof )
00062 {
00063   long count = long(last-first); // VC6 & 7 has broken iterator_traits
00064   assert( count > 0 );
00065   assert( count > dof );
00066 
00067   Ran loc = first + count/2;
00068   vcl_nth_element( first, loc, last );
00069   median = *loc;
00070   for ( Ran i=first; i!=last; ++i ) {
00071     *i = vnl_math_abs(*i-median);
00072   }
00073   ++loc;
00074   vcl_nth_element( first, loc, last );
00075   scale = T(1.4826 * (1 + 5.0/(count-dof)) * *loc);
00076 }
00077 
00078 
00079 template <class T, class InpIter>
00080 void rrel_util_median_and_scale_copy( InpIter first, InpIter last,
00081                                       T& median, T& scale,
00082                                       int dof )
00083 {
00084   // FIXME: scratch should be vcl_vector<
00085   // vcl_iterator_traits<InpIter>::value_type >, but this is not
00086   // supported under all compilers. In particular, VC++ doesn't
00087   // support it for vector iterators.
00088   //
00089   vcl_vector<T> scratch;
00090   for ( ; first != last; ++first )
00091     scratch.push_back( *first );
00092   rrel_util_median_and_scale( scratch.begin(), scratch.end(), median, scale, dof );
00093 }
00094 
00095 
00096 template <class T, class Ran>
00097 void rrel_util_intercept_adjustment( Ran first, Ran last,
00098                                      T & center, T & half_width,
00099                                      int dof )
00100 {
00101   long count = long(last-first); // VC6 & 7 has broken iterator_traits
00102   assert( count > dof );
00103   vcl_sort( first, last );
00104   int num_in_interval = (count-dof)/2 + dof;
00105   if ( num_in_interval > count ) num_in_interval = count;
00106   T min_start = *first;
00107   T min_width = *(first+num_in_interval-1) - min_start;
00108   Ran start=first+1;
00109   Ran end=first+num_in_interval;
00110   for ( ; end != last; ++start, ++end ) {
00111     T width = *end - *start;
00112     if ( width < min_width ) {
00113       min_start = *start;
00114       min_width = width;
00115     }
00116   }
00117   half_width = min_width/2;
00118   center = min_start + half_width;
00119 }
00120 
00121 
00122 template <class T, class InpIter>
00123 void rrel_util_intercept_adjustment_copy( InpIter first, InpIter last,
00124                                           T & center, T & half_width,
00125                                           int dof )
00126 {
00127   // FIXME: scratch should be vcl_vector<
00128   // vcl_iterator_traits<InpIter>::value_type >, but this is not
00129   // supported under all compilers. In particular, VC++ doesn't
00130   // support it for vector iterators.
00131   //
00132   vcl_vector<T> scratch;
00133   for ( ; first != last; ++first )
00134     scratch.push_back( *first );
00135   rrel_util_intercept_adjustment( scratch.begin(), scratch.end(),
00136                                   center, half_width, dof );
00137 }
00138 
00139 
00140 template <class T, class Ran>
00141 void rrel_util_intercept_adjust_stats( Ran first, Ran last,
00142                                        T & robust_mean, T & robust_std, T & inlier_frac,
00143                                        int dof )
00144 {
00145   long count = long(last-first); // VC6 & 7 has broken iterator_traits
00146   assert( count >= dof );
00147   T center, half_width;
00148   rrel_util_intercept_adjustment( first, last, center, half_width, dof );
00149 
00150   T std_dev = half_width * T(1.4826) * T( 1 + 5.0/(count-dof) );
00151   const T mu = 2.5;
00152   T bound = mu * std_dev;
00153 
00154   Ran begin_itr;
00155   for( begin_itr=first; *begin_itr < center-bound; ++begin_itr ) ;
00156   Ran end_itr=begin_itr;
00157   T sum = *begin_itr;
00158   while ( ++end_itr != last && *end_itr <= center+bound ) {
00159     sum += *end_itr;
00160   }
00161   long inliers = long(end_itr - begin_itr); // VC6 & 7 has broken iterator_traits
00162   robust_mean = sum / inliers;
00163   inlier_frac = T(inliers) / T(count);
00164 
00165   T sum_sq=0;
00166   for ( Ran i=begin_itr; i!=end_itr; ++i ) {
00167     sum_sq += vnl_math_sqr( *i - robust_mean );
00168   }
00169   robust_std = T( vcl_sqrt(sum_sq / (inliers-dof)) );
00170 }
00171 
00172 
00173 template <class T, class InpIter>
00174 void rrel_util_intercept_adjust_stats_copy( InpIter first, InpIter last,
00175                                             T & robust_mean, T & robust_std, T & inlier_frac,
00176                                             int dof )
00177 {
00178   // FIXME: scratch should be vcl_vector<
00179   // vcl_iterator_traits<InpIter>::value_type >, but this is not
00180   // supported under all compilers. In particular, VC++ doesn't
00181   // support it for vector iterators.
00182   //
00183   vcl_vector<T> scratch;
00184   for ( ; first != last; ++first )
00185     scratch.push_back( *first );
00186   rrel_util_intercept_adjust_stats( scratch.begin(), scratch.end(),
00187                                     robust_mean, robust_std, inlier_frac, dof );
00188 }
00189 
00190 
00191 // Instantiation macros
00192 //
00193 #undef RREL_UTIL_INSTANTIATE_RAN_ITER
00194 #define RREL_UTIL_INSTANTIATE_RAN_ITER(VALUE_T, RAN_ITER) \
00195 template VALUE_T \
00196 rrel_util_median_abs_dev_scale( const RAN_ITER&,  const RAN_ITER&, int dof, VALUE_T* ); \
00197 template double \
00198 rrel_util_median_abs_dev_scale( const RAN_ITER&,  const RAN_ITER&, int dof ); \
00199 template VALUE_T \
00200 rrel_util_weighted_scale( const RAN_ITER& residuals_first, const RAN_ITER& residuals_end, \
00201                           const RAN_ITER& weights_first, int dof, VALUE_T* ); \
00202 template \
00203 void rrel_util_median_and_scale( RAN_ITER first, RAN_ITER last, \
00204                                  VALUE_T& median, VALUE_T& scale, \
00205                                  int dof ); \
00206 template \
00207 void rrel_util_median_and_scale_copy( RAN_ITER first, RAN_ITER last, \
00208                                       VALUE_T& median, VALUE_T& scale, \
00209                                       int dof ); \
00210 template \
00211 void rrel_util_intercept_adjustment( RAN_ITER first, RAN_ITER last, \
00212                                      VALUE_T & center, VALUE_T & half_width, \
00213                                      int dof ); \
00214 template \
00215 void rrel_util_intercept_adjustment_copy( RAN_ITER first, RAN_ITER last, \
00216                                           VALUE_T & center, VALUE_T & half_width, \
00217                                           int dof ); \
00218 template \
00219 void rrel_util_intercept_adjust_stats( RAN_ITER first, RAN_ITER last, \
00220                                        VALUE_T & robust_mean, VALUE_T & robust_std, VALUE_T & inlier_frac, \
00221                                        int dof ); \
00222 template \
00223 void rrel_util_intercept_adjust_stats_copy( RAN_ITER first, RAN_ITER last, \
00224                                             VALUE_T & robust_mean, VALUE_T & robust_std, VALUE_T & inlier_frac, \
00225                                             int dof )
00226 
00227 #undef RREL_UTIL_INSTANTIATE_INP_ITER
00228 #define RREL_UTIL_INSTANTIATE_INP_ITER(VALUE_T, INP_ITER) \
00229 template VALUE_T \
00230 rrel_util_weighted_scale( const INP_ITER& residuals_first, const INP_ITER& residuals_end, \
00231                           const INP_ITER& weights_first, int dof, VALUE_T* ); \
00232 template \
00233 void rrel_util_median_and_scale_copy( INP_ITER first, INP_ITER last, \
00234                                       VALUE_T& median, VALUE_T& scale, \
00235                                       int dof ); \
00236 template \
00237 void rrel_util_intercept_adjustment_copy( INP_ITER first, INP_ITER last, \
00238                                           VALUE_T & center, VALUE_T & half_width, \
00239                                           int dof ); \
00240 template \
00241 void rrel_util_intercept_adjust_stats_copy( INP_ITER first, INP_ITER last, \
00242                                             VALUE_T & robust_mean, VALUE_T & robust_std, VALUE_T & inlier_frac, \
00243                                             int dof )
00244 
00245 #endif // rrel_util_txx_