]> Creatis software - cpPlugins.git/blobdiff - lib/cpPlugins/Extensions/Algorithms/IterativeGaussianModelEstimator.hxx
...
[cpPlugins.git] / lib / cpPlugins / Extensions / Algorithms / IterativeGaussianModelEstimator.hxx
index bf87054cf79a25fc68047b3365315b9627e015a1..b0d0505fc2a90de2c8cd98641117cf6413f8436f 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <cmath>
 #include <cstdarg>
+#include <fstream>
 #include <vnl/vnl_math.h>
 #include <vnl/vnl_inverse.h>
 
 template< class S, unsigned int D >
 void
 cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, D >::
-UpdateModel( )
+SetNumberOfSamples( unsigned long n )
 {
-  if( this->m_Updated )
-    return;
-
-  this->m_Cov.set_size( D, D );
-  this->m_Mean.set_size( D, 1 );
-
-  // Compute covariance matrix and mean vector
-  unsigned long N = this->m_Samples.size( );
-  this->m_Mean = this->m_S1;
-  if( N > 0 )
-    this->m_Mean /= S( N );
-  if( N > 1 )
+  this->m_N = S( n );
+  this->m_Updated = false;
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class S, unsigned int D >
+void
+cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, D >::
+SetMu( const TMatrix& m )
+{
+  if( m.rows( ) == D && m.columns( ) == 1 )
   {
-    this->m_Cov  = this->m_S2;
-    this->m_Cov -= ( this->m_S1 * this->m_S1.transpose( ) ) / S( N );
-    this->m_Cov /= S( N - 1 );
+    this->m_M = m;
+    this->m_Updated = false;
+    this->Modified( );
   }
   else
-    this->m_Cov.fill( S( 0 ) );
+  {
+    itkExceptionMacro(
+      << "Input Mu matrix is not a " << D << "x1 matrix"
+      );
 
-  // Compute inverse and determinant
-  S det = vnl_determinant( this->m_Cov );
-  if( !( det > S( 0 ) ) )
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class S, unsigned int D >
+void
+cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, D >::
+SetOmega( const TMatrix& O )
+{
+  if( O.rows( ) == D && O.columns( ) == D )
   {
-    this->m_InvCov.set_size( D, D );
-    this->m_InvCov.fill( S( 0 ) );
-    this->m_DensityCoeff = S( 0 );
+    this->m_O = O;
+    this->m_Updated = false;
+    this->Modified( );
   }
   else
   {
-    this->m_InvCov = vnl_inverse( this->m_Cov );
-    double _2piD = std::pow( double( 2 ) * double( vnl_math::pi ), D );
-    this->m_DensityCoeff = S( 1 ) / S( std::sqrt( _2piD * double( det ) ) );
+    itkExceptionMacro(
+      << "Input Omega matrix is not a " << D << "x" << D << " matrix"
+      );
 
   } // fi
+}
 
-  // Compute minimum and maximum probabilities from input samples
-  static S sample[ D ];
-  for( unsigned long i = 0; i < this->m_Samples.size( ); ++i )
+// -------------------------------------------------------------------------
+template< class S, unsigned int D >
+bool
+cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, D >::
+SaveModelToFile( const std::string& filename ) const
+{
+  std::ofstream out( filename.c_str( ) );
+  if( out )
   {
-    for( unsigned int d = 0; d < D; ++d )
-      sample[ d ] = this->m_Samples[ i ][ d ][ 0 ];
-    S p = this->Probability( sample );
-    if( i == 0 )
-    {
-      this->m_MinimumProbability = p;
-      this->m_MaximumProbability = p;
-    }
-    else
-    {
-      if( p < this->m_MinimumProbability ) this->m_MinimumProbability = p;
-      if( this->m_MaximumProbability < p ) this->m_MaximumProbability = p;
-
-    } // fi
+    out << this->m_N << std::endl;
+    out << this->m_M << std::endl;
+    out << this->m_O << std::endl;
+    out.close( );
+    return( true );
+  }
+  else
+    return( false );
+}
 
-  } // rof
-  this->m_Updated = true;
+// -------------------------------------------------------------------------
+template< class S, unsigned int D >
+bool
+cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, D >::
+LoadModelFromFile( const std::string& filename )
+{
+  std::ifstream in( filename.c_str( ) );
+  if( in )
+  {
+    this->Clear( );
+    in >> this->m_N;
+    for( unsigned int i = 0; i < D; ++i )
+      in >> this->m_M[ i ][ 0 ];
+    for( unsigned int j = 0; j < D; ++j )
+      for( unsigned int i = 0; i < D; ++i )
+        in >> this->m_O[ i ][ j ];
+    in.close( );
+    return( true );
+  }
+  else
+    return( false );
 }
 
 // -------------------------------------------------------------------------
@@ -81,13 +112,16 @@ template< class V >
 S cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, D >::
 Probability( const V& sample ) const
 {
+  if( !this->m_Updated )
+    this->_UpdateModel( );
+
   TMatrix c( D, 1 );
   for( unsigned int d = 0; d < D; ++d )
-    c[ d ][ 0 ] = S( sample[ d ] ) - this->m_Mean[ d ][ 0 ];
-  if( S( 0 ) < this->m_DensityCoeff )
+    c[ d ][ 0 ] = S( sample[ d ] ) - this->m_M[ d ][ 0 ];
+  if( S( 0 ) < this->m_Norm )
   {
     // Covariance is NOT null
-    double v = double( ( c.transpose( ) * ( this->m_InvCov * c ) )[ 0 ][ 0 ] );
+    double v = double( ( c.transpose( ) * ( this->m_Inv * c ) )[ 0 ][ 0 ] );
     v /= double( 2 );
 
     return( S( std::exp( -v ) ) );
@@ -95,9 +129,10 @@ Probability( const V& sample ) const
   else
   {
     // Covariance is null
-    bool equal = true;
-    for( unsigned int d = 0; d < D && equal; ++d )
-      equal &= !( S( 0 ) < S( std::fabs( double( c[ d ][ 0 ] ) ) ) );
+    S n = S( 0 );
+    for( unsigned int d = 0; d < D; ++d )
+      n += c[ d ][ 0 ] * c[ d ][ 0 ];
+    bool equal = ( double( n ) < double( 1e-10 ) );
     return( ( equal )? S( 1 ): S( 0 ) );
 
   } // fi
@@ -127,9 +162,11 @@ void
 cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, D >::
 GetModel( V& m, M& E ) const
 {
+  if( !this->m_Updated )
+    this->_UpdateModel( );
   for( unsigned int i = 0; i < D; ++i )
   {
-    m[ i ] = double( this->m_Mean[ i ][ 0 ] );
+    m[ i ] = double( this->m_M[ i ][ 0 ] );
     for( unsigned int j = 0; j < D; ++j )
       E[ i ][ j ] = double( this->m_Cov[ i ][ j ] );
 
@@ -142,12 +179,12 @@ void
 cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, D >::
 Clear( )
 {
+  this->m_N = S( 0 );
+  this->m_M.set_size( D, 1 );
+  this->m_O.set_size( D, D );
+  this->m_M.fill( S( 0 ) );
+  this->m_O.fill( S( 0 ) );
   this->m_Updated = false;
-  this->m_Samples.clear( );
-  this->m_S1.set_size( D, 1 );
-  this->m_S2.set_size( D, D );
-  this->m_S1.fill( S( 0 ) );
-  this->m_S2.fill( S( 0 ) );
   this->Modified( );
 }
 
@@ -162,9 +199,24 @@ AddSample( const V& sample )
   for( unsigned int d = 0; d < D; ++d )
     s[ d ][ 0 ] = S( sample[ d ] );
 
-  this->m_Samples.push_back( s );
-  this->m_S1 += s;
-  this->m_S2 += s * s.transpose( );
+  // Update mean
+  S coeff = this->m_N;
+  this->m_N += S( 1 );
+  coeff /= this->m_N;
+  this->m_M = ( this->m_M * coeff ) + ( s / this->m_N );
+
+  // Update omega operand
+  if( this->m_N == 1 )
+    this->m_O  = s * s.transpose( );
+  else if( this->m_N == 2 )
+    this->m_O += s * s.transpose( );
+  else
+  {
+    S inv = S( 1 ) / ( this->m_N - S( 1 ) );
+    this->m_O  = this->m_O * ( this->m_N - S( 2 ) ) * inv;
+    this->m_O += ( s * s.transpose( ) ) * inv;
+
+  } // fi
 
   this->m_Updated = false;
   this->Modified( );
@@ -181,10 +233,14 @@ AddSample( const S& s_x, const S& s_y, ... )
   std::va_list args_lst;
   va_start( args_lst, s_y );
   sample[ 0 ] = s_x;
-  sample[ 1 ] = s_y;
-  for( unsigned int d = 2; d < D; ++d )
-    sample[ d ] = S( va_arg( args_lst, double ) );
-  va_end( args_lst );
+  if( D > 1 )
+  {
+    sample[ 1 ] = s_y;
+    for( unsigned int d = 2; d < D; ++d )
+      sample[ d ] = S( va_arg( args_lst, double ) );
+    va_end( args_lst );
+
+  } // fi
   this->AddSample( sample );
 }
 
@@ -204,6 +260,42 @@ cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, D >::
 {
 }
 
+// -------------------------------------------------------------------------
+template< class S, unsigned int D >
+void
+cpPlugins::Extensions::Algorithms::IterativeGaussianModelEstimator< S, D >::
+_UpdateModel( ) const
+{
+  static const double _2piD =
+    std::pow( double( 2 ) * double( vnl_math::pi ), D );
+
+  // Update covariance
+  this->m_Cov =
+    this->m_O -
+    (
+      ( this->m_M * this->m_M.transpose( ) ) *
+      ( this->m_N / ( this->m_N - S( 1 ) ) )
+      );
+
+  // Compute inverse and determinant
+  S det = vnl_determinant( this->m_Cov );
+  if( !( det > S( 0 ) ) )
+  {
+    this->m_Inv.set_size( D, D );
+    this->m_Inv.fill( S( 0 ) );
+    this->m_Norm = S( 0 );
+  }
+  else
+  {
+    this->m_Inv = vnl_inverse( this->m_Cov );
+    this->m_Norm = S( 1 ) / S( std::sqrt( _2piD * double( det ) ) );
+
+  } // fi
+
+  // Object now is updated
+  this->m_Updated = true;
+}
+
 #endif // __CPPLUGINS__EXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__
 
 // eof - $RCSfile$