ANIMA  4.0
animaNLMeansVectorPatchSearcher.hxx
Go to the documentation of this file.
1 #pragma once
3 
5 #include <itkSymmetricEigenAnalysis.h>
6 #include <itkImageRegionConstIterator.h>
7 
8 namespace anima
9 {
10 
11 template <class ImageScalarType, class DataImageType>
12 NLMeansVectorPatchSearcher <ImageScalarType, DataImageType>
14 {
15  m_BetaParameter = 1.0;
16 
17  m_MeanThreshold = 0.95;
18  m_VarianceThreshold = 0.5;
19 }
20 
21 template <class ImageScalarType, class DataImageType>
22 void
24 ::ComputeInputProperties(const IndexType &refIndex, ImageRegionType &refPatch)
25 {
26  unsigned int ndim = this->GetInputImage()->GetVectorLength();
27  if (m_RefPatchMean.GetSize() != ndim)
28  {
29  m_RefPatchMean.SetSize(ndim);
30  m_RefPatchCovariance.set_size(ndim,ndim);
31  m_LogRefPatchCovariance.set_size(ndim,ndim);
32  }
33 
34  m_RefPatchNumElements = anima::computePatchMeanAndCovariance(this->GetInputImage(),refPatch,
35  m_RefPatchMean,m_RefPatchCovariance);
36 
37  CovarianceType eVec(ndim,ndim);
38  vnl_diag_matrix <double> eVals(ndim);
39 
40  itk::SymmetricEigenAnalysis <vnl_matrix <double>, vnl_diag_matrix <double>, vnl_matrix <double> > EigenAnalysis(ndim);
41  EigenAnalysis.ComputeEigenValuesAndVectors(m_RefPatchCovariance, eVals, eVec);
42 
43  for (unsigned int i = 0;i < ndim;++i)
44  eVals[i] = std::log(eVals[i]);
45 
46  m_LogRefPatchCovariance = eVec.transpose() * eVals * eVec;
47 
48  ImageRegionType regionLocalVariance = refPatch;
49  for (unsigned int i = 0;i < DataImageType::ImageDimension;++i)
50  {
51  regionLocalVariance.SetIndex(i,std::max(0,(int)refIndex[i] - 2));
52  regionLocalVariance.SetSize(i,std::min((unsigned int)(this->GetInputImage()->GetLargestPossibleRegion().GetSize()[i] - 1),(unsigned int)(refIndex[i] + 2)) - regionLocalVariance.GetIndex(i) + 1);
53  }
54 
55  anima::computeAverageLocalCovariance(m_NoiseCovariance,this->GetInputImage(),m_DataMask.GetPointer(),regionLocalVariance,2);
56 
57  vnl_matrix_inverse <double> covInverse(m_NoiseCovariance);
58  m_NoiseSigma = covInverse.inverse();
59 }
60 
61 template <class ImageScalarType, class DataImageType>
62 void
64 ::ComputeComparisonProperties(unsigned int index, ImageRegionType &movingPatch)
65 {
66  unsigned int ndim = this->GetInputImage()->GetVectorLength();
67  if (m_MovingPatchMean.GetSize() != ndim)
68  {
69  m_MovingPatchMean.SetSize(ndim);
70  m_MovingPatchCovariance.set_size(ndim,ndim);
71  }
72 
73  m_MovingPatchNumElements = anima::computePatchMeanAndCovariance(this->GetComparisonImage(index),movingPatch,
74  m_MovingPatchMean,m_MovingPatchCovariance);
75 }
76 
77 template <class ImageScalarType, class DataImageType>
78 bool
80 ::TestPatchConformity(unsigned int index, const IndexType &refIndex, const IndexType &movingIndex)
81 {
82  double covStdValue = m_DatabaseCovarianceDistanceStd->GetPixel(refIndex);
83  double covMeanValue = m_DatabaseCovarianceDistanceAverage->GetPixel(refIndex);
84  double meanStdValue = m_DatabaseMeanDistanceStd->GetPixel(refIndex);
85  double meanMeanValue = m_DatabaseMeanDistanceAverage->GetPixel(refIndex);
86 
87  double varTest = anima::VectorCovarianceTest(m_LogRefPatchCovariance,m_MovingPatchCovariance);
88 
89  if (varTest > covMeanValue + m_VarianceThreshold * covStdValue)
90  return false;
91 
92  double meanTestValue = anima::VectorMeansTest(m_RefPatchMean,m_MovingPatchMean,m_RefPatchNumElements,
93  m_MovingPatchNumElements,m_RefPatchCovariance,m_MovingPatchCovariance);
94 
95  if (meanTestValue > meanMeanValue + m_MeanThreshold * meanStdValue)
96  return false;
97 
98  return true;
99 }
100 
101 template <class ImageScalarType, class DataImageType>
102 double
104 ::ComputeWeightValue(unsigned int index, ImageRegionType &refPatch, ImageRegionType &movingPatch)
105 {
106  typedef itk::ImageRegionConstIterator <RefImageType> InIteratorType;
107 
108  InIteratorType tmpIt (this->GetInputImage(), refPatch);
109  InIteratorType tmpMovingIt (this->GetComparisonImage(index), movingPatch);
110 
111  VectorType tmpDiffValue;
112 
113  double weightValue = 0.0;
114  unsigned int numVoxels = 0;
115  unsigned int ndim = this->GetInputImage()->GetVectorLength();
116 
117  while (!tmpIt.IsAtEnd())
118  {
119  tmpDiffValue = tmpIt.Get() - tmpMovingIt.Get();
120  for (unsigned int i = 0;i < ndim;++i)
121  for (unsigned int j = i;j < ndim;++j)
122  {
123  if (j != i)
124  weightValue += 2.0 * m_NoiseSigma(i,j) * tmpDiffValue[i] * tmpDiffValue[j];
125  else
126  weightValue += m_NoiseSigma(i,j) * tmpDiffValue[i] * tmpDiffValue[j];
127  }
128 
129  ++numVoxels;
130  ++tmpIt;
131  ++tmpMovingIt;
132  }
133 
134  weightValue = std::exp(- weightValue / (2.0 * ndim * m_BetaParameter * numVoxels));
135  return weightValue;
136 }
137 
138 } // end namespace anima
unsigned int computePatchMeanAndCovariance(const itk::VectorImage< T1, Dimension > *inputImage, const itk::ImageRegion< Dimension > &patchRegion, itk::VariableLengthVector< T2 > &patchMean, vnl_matrix< T2 > &patchCov)
Computes the average and covariance matrix from a patch of a vector image.
double VectorCovarianceTest(vnl_matrix< T > &logRefPatchCov, vnl_matrix< T > &movingPatchCov)
Test if covariance matrices are different (returns distance)
double VectorMeansTest(itk::VariableLengthVector< T > &refPatchMean, itk::VariableLengthVector< T > &movingPatchMean, const unsigned int &refPatchNumElts, const unsigned int &movingPatchNumElts, vnl_matrix< T > &refPatchCov, vnl_matrix< T > &movingPatchCov)
Test if vector means are different (returns distance)
void computeAverageLocalCovariance(vnl_matrix< T2 > &resVariance, itk::VectorImage< T1, Dimension > *inputImage, itk::Image< unsigned char, Dimension > *maskImage, const itk::ImageRegion< Dimension > &averagingRegion, int localNeighborhood)
Noise estimation for a patch of a vector image.