18 #ifndef __otbPCAImageFilter_txx
19 #define __otbPCAImageFilter_txx
24 #include <vnl/vnl_matrix.h>
25 #include <vnl/algo/vnl_symmetric_eigensystem.h>
26 #include <vnl/algo/vnl_generalized_eigensystem.h>
31 template <
class TInputImage,
class TOutputImage,
36 this->SetNumberOfRequiredInputs(1);
38 m_NumberOfPrincipalComponentsRequired = 0;
40 m_UseNormalization =
false;
41 m_UseVarianceForNormalization =
false;
42 m_GivenMeanValues =
false;
43 m_GivenStdDevValues =
false;
45 m_GivenCovarianceMatrix =
false;
46 m_GivenTransformationMatrix =
false;
47 m_IsTransformationMatrixForward =
true;
49 m_CovarianceEstimator = CovarianceEstimatorFilterType::New();
50 m_Transformer = TransformFilterType::New();
51 m_Transformer->MatrixByVectorOn();
52 m_Normalizer = NormalizeFilterType::New();
55 template <
class TInputImage,
class TOutputImage,
61 Superclass::GenerateOutputInformation();
63 switch ( static_cast<int>(DirectionOfTransformation) )
67 if ( m_NumberOfPrincipalComponentsRequired == 0
68 || m_NumberOfPrincipalComponentsRequired
69 > this->GetInput()->GetNumberOfComponentsPerPixel() )
71 m_NumberOfPrincipalComponentsRequired =
72 this->GetInput()->GetNumberOfComponentsPerPixel();
75 this->GetOutput()->SetNumberOfComponentsPerPixel(
76 m_NumberOfPrincipalComponentsRequired );
81 unsigned int theOutputDimension = 0;
82 if ( m_GivenTransformationMatrix )
84 theOutputDimension = m_TransformationMatrix.Rows() >= m_TransformationMatrix.Cols() ?
85 m_TransformationMatrix.Rows() : m_TransformationMatrix.Cols();
87 else if ( m_GivenCovarianceMatrix )
89 theOutputDimension = m_CovarianceMatrix.Rows() >= m_CovarianceMatrix.Cols() ?
90 m_CovarianceMatrix.Rows() : m_CovarianceMatrix.Cols();
95 "Covariance or transformation matrix required to know the output size",
99 this->GetOutput()->SetNumberOfComponentsPerPixel( theOutputDimension );
105 "Class should be templeted with FORWARD or INVERSE only...",
110 template <
class TInputImage,
class TOutputImage,
116 switch ( static_cast<int>(DirectionOfTransformation) )
119 return ForwardGenerateData();
121 return ReverseGenerateData();
124 "Class should be templated with FORWARD or INVERSE only...",
129 template <
class TInputImage,
class TOutputImage,
135 typename InputImageType::Pointer inputImgPtr
138 if ( !m_GivenTransformationMatrix )
140 if ( !m_GivenCovarianceMatrix )
142 if ( m_UseNormalization )
144 m_Normalizer->SetInput( inputImgPtr );
145 m_Normalizer->SetUseStdDev( m_UseVarianceForNormalization );
147 if ( m_GivenMeanValues )
148 m_Normalizer->SetMean( m_MeanValues );
150 if ( m_GivenStdDevValues )
151 m_Normalizer->SetStdDev( m_StdDevValues );
153 m_Normalizer->Update();
155 if ( !m_GivenMeanValues )
157 m_MeanValues = m_Normalizer->GetCovarianceEstimator()->GetMean();
159 if ( !m_GivenStdDevValues )
160 m_StdDevValues = m_Normalizer->GetFunctor().GetStdDev();
162 if ( m_UseVarianceForNormalization )
163 m_CovarianceMatrix = m_Normalizer->GetCovarianceEstimator()->GetCorrelation();
165 m_CovarianceMatrix = m_Normalizer->GetCovarianceEstimator()->GetCovariance();
169 m_CovarianceEstimator->SetInput( m_Normalizer->GetOutput() );
170 m_CovarianceEstimator->Update();
172 m_CovarianceMatrix = m_CovarianceEstimator->GetCovariance();
175 m_Transformer->SetInput( m_Normalizer->GetOutput() );
179 m_CovarianceEstimator->SetInput( inputImgPtr );
180 m_CovarianceEstimator->Update();
182 m_CovarianceMatrix = m_CovarianceEstimator->GetCovariance();
184 m_Transformer->SetInput( inputImgPtr );
189 m_Transformer->SetInput( inputImgPtr );
192 GenerateTransformationMatrix();
194 else if ( !m_IsTransformationMatrixForward )
197 m_TransformationMatrix = m_TransformationMatrix.GetInverse();
199 m_Transformer->SetInput( inputImgPtr );
202 if ( m_TransformationMatrix.GetVnlMatrix().empty() )
205 "Empty transformation matrix",
209 m_Transformer->SetMatrix( m_TransformationMatrix.GetVnlMatrix() );
210 m_Transformer->GraftOutput( this->GetOutput() );
211 m_Transformer->Update();
212 this->GraftOutput( m_Transformer->GetOutput() );
215 template <
class TInputImage,
class TOutputImage,
221 if ( !m_GivenTransformationMatrix )
223 if ( !m_GivenCovarianceMatrix )
226 "No Covariance nor Transformation matrix given",
230 GenerateTransformationMatrix();
232 m_TransformationMatrix = m_TransformationMatrix.GetInverse();
234 else if ( m_IsTransformationMatrixForward )
237 m_IsTransformationMatrixForward =
false;
239 m_TransformationMatrix = m_TransformationMatrix.GetInverse();
242 if ( m_TransformationMatrix.GetVnlMatrix().empty() )
245 "Empty transformation matrix",
249 m_Transformer->SetInput( this->GetInput() );
250 m_Transformer->SetMatrix( m_TransformationMatrix.GetVnlMatrix() );
252 if ( m_GivenMeanValues || m_GivenStdDevValues )
254 m_Normalizer->SetInput( m_Transformer->GetOutput() );
256 if ( m_GivenStdDevValues )
258 VectorType revStdDev ( m_StdDevValues.Size() );
259 for (
unsigned int i = 0; i < m_StdDevValues.Size(); ++i )
260 revStdDev[i] = 1. / m_StdDevValues[i];
261 m_Normalizer->SetStdDev( revStdDev );
264 if ( m_GivenMeanValues )
267 if ( m_GivenStdDevValues )
269 for (
unsigned int i = 0; i < m_MeanValues.Size(); ++i )
270 revMean[i] = - m_MeanValues[i] / m_StdDevValues[i];
271 m_Normalizer->SetUseStdDev(
true );
275 for (
unsigned int i = 0; i < m_MeanValues.Size(); ++i )
276 revMean[i] = -m_MeanValues[i];
277 m_Normalizer->SetUseStdDev(
false );
279 m_Normalizer->SetMean( revMean );
282 m_Normalizer->GraftOutput( this->GetOutput() );
283 m_Normalizer->Update();
284 this->GraftOutput( m_Normalizer->GetOutput() );
288 m_Transformer->GraftOutput( this->GetOutput() );
289 m_Transformer->Update();
290 this->GraftOutput( m_Transformer->GetOutput() );
294 template <
class TInputImage,
class TOutputImage,
308 typename MatrixType::InternalMatrixType A = m_CovarianceMatrix.GetVnlMatrix();
309 typename MatrixType::InternalMatrixType I = Id.GetVnlMatrix();
311 vnl_generalized_eigensystem solver ( A, I );
313 typename MatrixType::InternalMatrixType transf = solver.V;
315 transf.inplace_transpose();
323 for (
unsigned int i = 0; i < valP.size(); ++i )
326 valP[i] = 1. / vcl_sqrt( vcl_abs( valP[i] ) );
329 "Null Eigen value !!", ITK_LOCATION );
331 valP.post_multiply( transf );
333 if ( m_NumberOfPrincipalComponentsRequired
334 != this->GetInput()->GetNumberOfComponentsPerPixel() )
335 m_TransformationMatrix = transf.get_n_rows( 0, m_NumberOfPrincipalComponentsRequired );
337 m_TransformationMatrix = transf;
340 m_EigenValues.SetSize( m_NumberOfPrincipalComponentsRequired );
341 for (
unsigned int i = 0; i < m_NumberOfPrincipalComponentsRequired; ++i )
342 m_EigenValues[i] = static_cast< RealType >( valP[i] );
346 vnl_symmetric_eigensystem_compute( m_CovarianceMatrix.GetVnlMatrix(), transf, vectValP );
349 for (
unsigned int i = 0; i < vectValP.size(); ++i )
350 valP(i, i) = vectValP[i];
353 for (
unsigned int i = 0; i < valP.rows(); ++i )
355 if ( valP(i, i) > 0. )
357 valP(i, i) = 1. / vcl_sqrt( valP(i, i) );
359 else if ( valP(i, i) < 0. )
361 otbMsgDebugMacro( <<
"ValP(" << i <<
") neg : " << valP(i, i) <<
" taking abs value" );
362 valP(i, i) = 1. / vcl_sqrt( vcl_abs( valP(i, i) ) );
367 "Null Eigen value !!", ITK_LOCATION );
370 transf = valP * transf.transpose();
373 if ( m_NumberOfPrincipalComponentsRequired
374 != this->GetInput()->GetNumberOfComponentsPerPixel() )
375 m_TransformationMatrix = transf.get_n_rows( 0, m_NumberOfPrincipalComponentsRequired );
377 m_TransformationMatrix = transf;
379 m_EigenValues.SetSize( m_NumberOfPrincipalComponentsRequired );
380 for (
unsigned int i = 0; i < m_NumberOfPrincipalComponentsRequired; ++i )
381 m_EigenValues[i] = static_cast< RealType >( valP(i, i) );
387 template <
class TInputImage,
class TOutputImage,
393 Superclass::PrintSelf( os, indent );
395 os << indent <<
"m_UseNormalization = ";
396 if ( m_UseNormalization )
401 if ( m_GivenMeanValues )
402 os << indent <<
"Given Mean : " << m_MeanValues <<
"\n";
404 if ( m_GivenStdDevValues )
405 os << indent <<
"Given StdDev : " << m_StdDevValues <<
"\n";
407 if ( !m_CovarianceMatrix.GetVnlMatrix().empty() )
409 os << indent <<
"Covariance matrix";
410 if ( m_GivenCovarianceMatrix )
414 m_CovarianceMatrix.GetVnlMatrix().print(os);
416 if ( m_GivenCovarianceMatrix )
417 m_CovarianceEstimator->Print( os, indent.GetNextIndent() );
420 if ( !m_TransformationMatrix.GetVnlMatrix().empty() )
423 if ( !m_IsTransformationMatrixForward )
425 os <<
"Transformation matrix";
426 if ( m_GivenTransformationMatrix )
430 m_TransformationMatrix.GetVnlMatrix().print(os);
433 if ( m_EigenValues.Size() > 0 )
435 os << indent <<
"Eigen value :";
436 for (
unsigned int i = 0; i < m_NumberOfPrincipalComponentsRequired; ++i )
437 os <<
" " << m_EigenValues[i];
444 #endif // __otbPCAImageFilter_txx