21 #ifndef otbMNFImageFilter_hxx
22 #define otbMNFImageFilter_hxx
27 #include <vnl/vnl_matrix.h>
28 #include <vnl/algo/vnl_cholesky.h>
29 #include <vnl/algo/vnl_matrix_inverse.h>
30 #include <vnl/algo/vnl_symmetric_eigensystem.h>
31 #include <vnl/algo/vnl_generalized_eigensystem.h>
35 template <
class TInputImage,
class TOutputImage,
class TNoiseImageFilter, Transform::TransformDirection TDirectionOfTransformation>
38 this->SetNumberOfRequiredInputs(1);
40 m_NumberOfPrincipalComponentsRequired = 0;
42 m_UseNormalization =
false;
43 m_GivenMeanValues =
false;
44 m_GivenStdDevValues =
false;
46 m_GivenCovarianceMatrix =
false;
47 m_GivenNoiseCovarianceMatrix =
false;
48 m_GivenTransformationMatrix =
false;
49 m_IsTransformationMatrixForward =
true;
51 m_Normalizer = NormalizeFilterType::New();
52 m_NoiseImageFilter = NoiseImageFilterType::New();
53 m_CovarianceEstimator = CovarianceEstimatorFilterType::New();
54 m_NoiseCovarianceEstimator = CovarianceEstimatorFilterType::New();
55 m_Transformer = TransformFilterType::New();
56 m_Transformer->MatrixByVectorOn();
59 template <
class TInputImage,
class TOutputImage,
class TNoiseImageFilter, Transform::TransformDirection TDirectionOfTransformation>
63 Superclass::GenerateOutputInformation();
65 switch (
static_cast<int>(DirectionOfTransformation))
69 if (m_NumberOfPrincipalComponentsRequired == 0 || m_NumberOfPrincipalComponentsRequired > this->GetInput()->GetNumberOfComponentsPerPixel())
71 m_NumberOfPrincipalComponentsRequired = this->GetInput()->GetNumberOfComponentsPerPixel();
74 this->GetOutput()->SetNumberOfComponentsPerPixel(m_NumberOfPrincipalComponentsRequired);
79 unsigned int theOutputDimension = 0;
80 if (m_GivenTransformationMatrix)
82 theOutputDimension = m_TransformationMatrix.Rows() >= m_TransformationMatrix.Cols() ? m_TransformationMatrix.Rows() : m_TransformationMatrix.Cols();
84 else if (m_GivenCovarianceMatrix)
86 theOutputDimension = m_CovarianceMatrix.Rows() >= m_CovarianceMatrix.Cols() ? m_CovarianceMatrix.Rows() : m_CovarianceMatrix.Cols();
90 throw itk::ExceptionObject(__FILE__, __LINE__,
"Covariance or transformation matrix required to know the output size", ITK_LOCATION);
93 m_NumberOfPrincipalComponentsRequired = 0;
94 this->GetOutput()->SetNumberOfComponentsPerPixel(theOutputDimension);
98 throw itk::ExceptionObject(__FILE__, __LINE__,
"Class should be templeted with FORWARD or INVERSE only...", ITK_LOCATION);
102 switch (
static_cast<int>(DirectionOfTransformation))
106 ForwardGenerateOutputInformation();
111 ReverseGenerateOutputInformation();
117 template <
class TInputImage,
class TOutputImage,
class TNoiseImageFilter, Transform::TransformDirection TDirectionOfTransformation>
120 typename InputImageType::Pointer inputImgPtr =
const_cast<InputImageType*
>(this->GetInput());
122 if (m_GivenMeanValues)
123 m_Normalizer->SetMean(this->GetMeanValues());
125 if (m_UseNormalization)
127 m_Normalizer->SetUseStdDev(
true);
128 if (m_GivenStdDevValues)
129 m_Normalizer->SetStdDev(this->GetStdDevValues());
132 m_Normalizer->SetUseStdDev(
false);
134 m_Normalizer->SetInput(inputImgPtr);
135 m_Normalizer->GetOutput()->UpdateOutputInformation();
137 if (!m_GivenMeanValues)
138 m_MeanValues = m_Normalizer->GetCovarianceEstimator()->GetMean();
140 if (m_UseNormalization)
142 if (!m_GivenStdDevValues)
143 m_StdDevValues = m_Normalizer->GetFunctor().GetStdDev();
146 if (!m_GivenTransformationMatrix)
148 if (!m_GivenNoiseCovarianceMatrix)
150 m_NoiseImageFilter->SetInput(m_Normalizer->GetOutput());
151 m_NoiseCovarianceEstimator->SetInput(m_NoiseImageFilter->GetOutput());
152 m_NoiseCovarianceEstimator->Update();
154 m_NoiseCovarianceMatrix = m_NoiseCovarianceEstimator->GetCovariance();
157 if (!m_GivenCovarianceMatrix)
159 m_CovarianceEstimator->SetInput(m_Normalizer->GetOutput());
160 m_CovarianceEstimator->Update();
162 m_CovarianceMatrix = m_CovarianceEstimator->GetCovariance();
165 GenerateTransformationMatrix();
167 else if (!m_IsTransformationMatrixForward)
170 m_IsTransformationMatrixForward =
true;
171 if (m_TransformationMatrix.Rows() == m_TransformationMatrix.Cols())
173 m_TransformationMatrix = m_TransformationMatrix.GetInverse();
177 vnl_svd<MatrixElementType> invertor(m_TransformationMatrix.GetVnlMatrix());
178 m_TransformationMatrix = invertor.pinverse();
182 if (m_TransformationMatrix.GetVnlMatrix().empty())
184 throw itk::ExceptionObject(__FILE__, __LINE__,
"Empty transformation matrix", ITK_LOCATION);
187 m_Transformer->SetInput(m_Normalizer->GetOutput());
188 m_Transformer->SetMatrix(m_TransformationMatrix.GetVnlMatrix());
191 template <
class TInputImage,
class TOutputImage,
class TNoiseImageFilter, Transform::TransformDirection TDirectionOfTransformation>
194 if (!m_GivenTransformationMatrix)
196 if (!m_GivenCovarianceMatrix)
198 throw itk::ExceptionObject(__FILE__, __LINE__,
"Inverse Transformation or at least Covariance matrix is required to invert MNF", ITK_LOCATION);
201 if (!m_GivenNoiseCovarianceMatrix)
203 throw itk::ExceptionObject(__FILE__, __LINE__,
"Inverse Transformation or at least Noise Covariance matrix is required to invert MNF", ITK_LOCATION);
206 GenerateTransformationMatrix();
208 m_IsTransformationMatrixForward =
false;
209 if (m_TransformationMatrix.Rows() == m_TransformationMatrix.Cols())
210 m_TransformationMatrix = vnl_matrix_inverse<MatrixElementType>(m_TransformationMatrix.GetVnlMatrix());
213 vnl_svd<MatrixElementType> invertor(m_TransformationMatrix.GetVnlMatrix());
214 m_TransformationMatrix = invertor.inverse();
217 else if (m_IsTransformationMatrixForward)
220 m_IsTransformationMatrixForward =
false;
221 if (m_TransformationMatrix.Rows() == m_TransformationMatrix.Cols())
223 m_TransformationMatrix = vnl_matrix_inverse<MatrixElementType>(m_TransformationMatrix.GetVnlMatrix());
227 vnl_svd<MatrixElementType> invertor(m_TransformationMatrix.GetVnlMatrix());
228 m_TransformationMatrix = invertor.pinverse();
232 if (m_TransformationMatrix.GetVnlMatrix().empty())
234 throw itk::ExceptionObject(__FILE__, __LINE__,
"Empty transformation matrix", ITK_LOCATION);
237 m_Transformer->SetInput(this->GetInput());
238 m_Transformer->SetMatrix(m_TransformationMatrix.GetVnlMatrix());
240 if (!m_GivenMeanValues)
242 throw itk::ExceptionObject(__FILE__, __LINE__,
"Initial means required for correct data centering", ITK_LOCATION);
244 if (m_UseNormalization)
246 if (!m_GivenStdDevValues)
248 throw itk::ExceptionObject(__FILE__, __LINE__,
"Initial StdDevs required for de-normalization", ITK_LOCATION);
252 for (
unsigned int i = 0; i < m_StdDevValues.Size(); ++i)
253 revStdDev[i] = 1. / m_StdDevValues[i];
254 m_Normalizer->SetStdDev(revStdDev);
257 for (
unsigned int i = 0; i < m_MeanValues.Size(); ++i)
258 revMean[i] = -m_MeanValues[i] / m_StdDevValues[i];
259 m_Normalizer->SetMean(revMean);
264 for (
unsigned int i = 0; i < m_MeanValues.Size(); ++i)
265 revMean[i] = -m_MeanValues[i];
266 m_Normalizer->SetMean(revMean);
267 m_Normalizer->SetUseStdDev(
false);
270 m_Normalizer->SetInput(m_Transformer->GetOutput());
274 template <
class TInputImage,
class TOutputImage,
class TNoiseImageFilter, Transform::TransformDirection TDirectionOfTransformation>
277 switch (
static_cast<int>(DirectionOfTransformation))
280 return ForwardGenerateData();
282 return ReverseGenerateData();
284 throw itk::ExceptionObject(__FILE__, __LINE__,
"Class should be templated with FORWARD or INVERSE only...", ITK_LOCATION);
288 template <
class TInputImage,
class TOutputImage,
class TNoiseImageFilter, Transform::TransformDirection TDirectionOfTransformation>
291 m_Transformer->GraftOutput(this->GetOutput());
292 m_Transformer->Update();
293 this->GraftOutput(m_Transformer->GetOutput());
296 template <
class TInputImage,
class TOutputImage,
class TNoiseImageFilter, Transform::TransformDirection TDirectionOfTransformation>
299 m_Normalizer->GraftOutput(this->GetOutput());
300 m_Normalizer->Update();
301 this->GraftOutput(m_Normalizer->GetOutput());
304 template <
class TInputImage,
class TOutputImage,
class TNoiseImageFilter, Transform::TransformDirection TDirectionOfTransformation>
307 vnl_cholesky choleskySolver(m_NoiseCovarianceMatrix.GetVnlMatrix(), vnl_cholesky::estimate_condition);
310 InternalMatrixType C = Rn_inv.transpose() * m_CovarianceMatrix.GetVnlMatrix() * Rn_inv;
312 vnl_svd<MatrixElementType> solver(C);
318 transf.inplace_transpose();
320 if (m_NumberOfPrincipalComponentsRequired != this->GetInput()->GetNumberOfComponentsPerPixel())
321 m_TransformationMatrix = transf.get_n_rows(0, m_NumberOfPrincipalComponentsRequired);
323 m_TransformationMatrix = transf;
325 m_EigenValues.SetSize(m_NumberOfPrincipalComponentsRequired);
326 for (
unsigned int i = 0; i < m_NumberOfPrincipalComponentsRequired; ++i)
327 m_EigenValues[i] =
static_cast<RealType>(valP(i, i));
330 template <
class TInputImage,
class TOutputImage,
class TNoiseImageFilter, Transform::TransformDirection TDirectionOfTransformation>
333 Superclass::PrintSelf(os, indent);
335 if (m_UseNormalization)
337 os << indent <<
"Normalisation with :\n" << indent <<
"Mean: ";
338 for (
unsigned int i = 0; i < m_MeanValues.Size(); ++i)
339 os << m_MeanValues[i] <<
" ";
340 os <<
"\n" << indent <<
"StdDev: ";
341 for (
unsigned int i = 0; i < m_StdDevValues.Size(); ++i)
342 os << m_StdDevValues[i] <<
" ";
346 os << indent <<
"No normalisation\n";
348 if (!m_NoiseCovarianceMatrix.GetVnlMatrix().empty())
350 os << indent <<
"Noise Covariance matrix";
351 if (m_GivenNoiseCovarianceMatrix)
355 m_NoiseCovarianceMatrix.GetVnlMatrix().print(os);
358 if (!m_CovarianceMatrix.GetVnlMatrix().empty())
360 os << indent <<
"Covariance matrix";
361 if (m_GivenCovarianceMatrix)
365 m_CovarianceMatrix.GetVnlMatrix().print(os);
368 if (!m_TransformationMatrix.GetVnlMatrix().empty())
370 os << indent <<
"Transformation matrix";
371 if (m_GivenTransformationMatrix)
375 m_TransformationMatrix.GetVnlMatrix().print(os);
378 if (m_EigenValues.Size() > 0)
380 os << indent <<
"RMS value :";
381 for (
unsigned int i = 0; i < m_EigenValues.Size(); ++i)
382 os <<
" " << m_EigenValues[i];
389 #endif // otbMNFImageFilter_hxx