contrib/rpl/rrel/rrel_mlesac_obj.cxx
Go to the documentation of this file.
00001 // This is rpl/rrel/rrel_mlesac_obj.cxx
00002 #include "rrel_mlesac_obj.h"
00003 
00004 #include <vnl/vnl_math.h>
00005 
00006 #include <vcl_cstdlib.h>
00007 #include <vcl_cmath.h>
00008 
00009 
00010 namespace {
00011   inline double sqr( double x ) { return x*x; }
00012 }
00013 
00014 
00015 rrel_mlesac_obj::rrel_mlesac_obj(unsigned int residual_dof, double outlier_sigma, double outlier_frac)
00016   : outlier_sigma_(outlier_sigma),
00017     outlier_frac_(outlier_frac),
00018     residual_dof_(residual_dof)
00019 {
00020 }
00021 
00022 double
00023 rrel_mlesac_obj::fcn( vect_const_iter begin, vect_const_iter end,
00024                       vect_const_iter scale,
00025                       vnl_vector<double>* /* param_vector */ ) const
00026 {
00027   double value=0;
00028   double pi,p0,zi;
00029   vect_const_iter begin0 = begin;
00030   unsigned long num_residual = end - begin;
00031   double mult1 = 1.0 / (vcl_sqrt( 2 * vnl_math::pi ));
00032 
00033   double inlier_frac = 1.0;
00034   double new_inlier_frac = 1 - outlier_frac_;
00035 
00036   const double EPS = 0.01;
00037 
00038   //EM algorithm to get outlier_frac, the mixing parameter
00039   while ( new_inlier_frac > EPS && vcl_abs((new_inlier_frac - inlier_frac) / inlier_frac) > EPS) {
00040     begin = begin0;
00041     inlier_frac = new_inlier_frac;
00042     new_inlier_frac = 0;
00043     for  (; begin != end; ++begin, ++scale) {
00044       double const1 = vcl_pow(mult1 / (*scale), (int)residual_dof_) ;
00045       pi = inlier_frac * const1 * vcl_exp( - sqr(*begin) / ( 2.0 * sqr(*scale) ) );
00046       p0 = (1 - inlier_frac) / outlier_sigma_;
00047       zi = pi / ( pi + p0 );
00048       new_inlier_frac += zi;
00049     }
00050     new_inlier_frac = new_inlier_frac / num_residual;
00051   }
00052 
00053   begin = begin0;
00054   //the negative log likelihood
00055   for ( ; begin != end; ++begin) {
00056     double const1 = vcl_pow(mult1 / (*scale), (int)residual_dof_) ;
00057     pi = new_inlier_frac * const1 * vcl_exp( - sqr(*begin) / ( 2.0 * sqr(*scale) ) );
00058     p0= ( 1 - new_inlier_frac ) / outlier_sigma_;
00059     value -= vcl_log( pi + p0 );
00060   }
00061 
00062   return value;
00063 }
00064 
00065 double
00066 rrel_mlesac_obj::fcn( vect_const_iter begin, vect_const_iter end,
00067                       double scale,
00068                       vnl_vector<double>* ) const
00069 {
00070   double value=0;
00071   double pi,p0,zi;
00072   vect_const_iter begin0 = begin;
00073   unsigned long num_residual = end - begin;
00074 
00075   double inlier_frac = 1.0;
00076   double new_inlier_frac = 1 - outlier_frac_;
00077   double mult1 = 1.0 / (vcl_sqrt( 2 * vnl_math::pi ) * scale);
00078   double const1 = vcl_pow(mult1, (int)residual_dof_) ;
00079   double exp_mult2 = -1.0 / (2.0 * sqr(scale));
00080 
00081   const double EPS = 0.01;
00082 
00083   //EM algorithm to get outlier_frac, the mixing parameter
00084   while ( new_inlier_frac > EPS && vcl_abs((new_inlier_frac - inlier_frac) / inlier_frac) > EPS) {
00085     begin = begin0;
00086     inlier_frac = new_inlier_frac;
00087     new_inlier_frac = 0;
00088     for  (; begin != end; ++begin) {
00089       pi = inlier_frac * const1 * vcl_exp( sqr(*begin) * exp_mult2 );
00090       p0 = (1 - inlier_frac) / outlier_sigma_;
00091       zi = pi / ( pi + p0 );
00092       new_inlier_frac += zi;
00093     }
00094     new_inlier_frac = new_inlier_frac / num_residual;
00095   }
00096 
00097   begin = begin0;
00098   //the negative log likelihood
00099   for ( ; begin != end; ++begin) {
00100     pi = new_inlier_frac * const1 * vcl_exp( sqr(*begin) * exp_mult2 );
00101     p0= ( 1 - new_inlier_frac ) / outlier_sigma_;
00102     value -= vcl_log( pi + p0 );
00103   }
00104 
00105   return value;
00106 }