00001
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* )
00018 {
00019 long count = long(end - begin);
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* )
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);
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
00085
00086
00087
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);
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
00128
00129
00130
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);
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);
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
00179
00180
00181
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
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_