CVD 0.8
cvd/irls.h
00001 /*                       
00002     This file is part of the CVD Library.
00003 
00004     Copyright (C) 2005 The Authors
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public
00017     License along with this library; if not, write to the Free Software
00018     Foundation, Inc., 
00019     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 */
00021 //-*- c++ -*-
00022 #ifndef __IRLS_H
00023 #define __IRLS_H
00024 
00025 #include <cvd/wls.h>
00026 #include <assert.h>
00027 #include <cmath>
00028 
00029 namespace CVD {
00030 
00035 struct RobustI {
00036   double sd_inlier; 
00037   inline double reweight(double x) {return 1/(sd_inlier+fabs(x));}  
00038   inline double true_scale(double x) {return reweight(x) - fabs(x)*reweight(x)*reweight(x);}  
00039   inline double objective(double x) {return fabs(x) + sd_inlier*log(sd_inlier*reweight(x));}  
00040 };
00041 
00046 struct RobustII {
00047   double sd_inlier; 
00048   inline double reweight(double d){return 1/(sd_inlier+d*d);} 
00049   inline double true_scale(double d){return d - 2*d*reweight(d);} 
00050   inline double objective(double d){return 0.5 * log(1 + d*d/sd_inlier);} 
00051 };
00052 
00057 struct ILinear {
00058   inline double reweight(double d){return 1;} 
00059   inline double true_scale(double d){return 1;} 
00060   inline double objective(double d){return d*d;} 
00061 };
00062 
00063 
00069 template <int Size, class Reweight>
00070 class IRLS
00071   : public Reweight,
00072     public WLS<Size>
00073 {
00074 public:
00075   IRLS(){Identity(my_true_C_inv,0);my_residual=0;}
00076 
00077   inline void add_df(double d, const Vector<Size>& f) {
00078     double scale = reweight(d);
00079     double ts = true_scale(d);
00080     my_residual += objective(d);
00081 
00082     WLS<Size>::add_df(d,f,scale);
00083 
00084     for(int i=0; i<Size; i++){
00085       for(int j=0; j<Size; j++){
00086     my_true_C_inv[i][j]+=f[i]*f[j]*ts;
00087       }
00088     }
00089   }
00090 
00091   void operator += (const IRLS& meas){
00092     WLS<Size>::operator+=(meas);
00093     my_true_C_inv += meas.my_true_C_inv;
00094   }
00095 
00096 
00097   Matrix<Size,Size,RowMajor>& get_true_C_inv() {return my_true_C_inv;}
00098   const Matrix<Size,Size,RowMajor>& get_true_C_inv()const {return my_true_C_inv;}
00099 
00100   double get_residual() {return my_residual;}
00101 
00102 private:
00103 
00104   double my_residual;
00105 
00106   Matrix<Size,Size,RowMajor> my_true_C_inv;
00107 
00108   // comment out to allow bitwise copying
00109   IRLS( IRLS& copyof );
00110   int operator = ( IRLS& copyof );
00111 };
00112 
00113 }
00114 
00115 #endif