ANIMA  4.0
animaTensorGeneralizedCorrelationImageToImageMetric.hxx
Go to the documentation of this file.
1 #pragma once
3 
4 #include <itkImageRegionConstIteratorWithIndex.h>
5 #include <itkSymmetricEigenAnalysis.h>
6 
7 namespace anima
8 {
9 
13 template < class TFixedImagePixelType, class TMovingImagePixelType, unsigned int ImageDimension >
16 {
17  m_OrientationPenalty = true;
18  m_VarianceThreshold = 0.000001;
19 
20  m_FixedImagePoints.clear();
21  m_FixedImageValues.clear();
22 
23  m_leCalculator = LECalculatorType::New();
24 }
25 
29 template < class TFixedImagePixelType, class TMovingImagePixelType, unsigned int ImageDimension >
32 ::GetValue( const TransformParametersType & parameters ) const
33 {
34  FixedImageConstPointer fixedImage = this->m_FixedImage;
35  MovingImageConstPointer movingImage = this->m_Interpolator->GetInputImage();
36 
37  if(!fixedImage)
38  itkExceptionMacro("Fixed image has not been assigned");
39 
40  if (this->m_NumberOfPixelsCounted <= 1)
41  return 0;
42 
43  this->SetTransformParameters( parameters );
44 
45  unsigned int vectorSize = m_FixedMean.GetSize();
46 
47  vnl_matrix <double> Sigma_YY(vectorSize,vectorSize);
48  Sigma_YY.fill(0);
49 
50  vnl_matrix <double> Sigma_XY(vectorSize,vectorSize);
51  Sigma_XY.fill(0);
52 
53  PixelType movingMean(vectorSize);
54  movingMean.Fill(0);
55 
56  OutputPointType transformedPoint;
57  ContinuousIndexType transformedIndex;
58 
59  unsigned int tensorDimension = 3;
60  vnl_matrix <double> tmpMat(tensorDimension, tensorDimension);
61  vnl_matrix <double> currentTensor(tensorDimension, tensorDimension);
62  vnl_matrix <double> ppdOrientationMatrix(tensorDimension, tensorDimension);
63  typedef itk::Matrix <double, 3, 3> EigVecMatrixType;
64  typedef vnl_vector_fixed <double,3> EigValVectorType;
65  itk::SymmetricEigenAnalysis < EigVecMatrixType, EigValVectorType, EigVecMatrixType> eigenComputer(3);
66  EigVecMatrixType eigVecs;
67  EigValVectorType eigVals;
68 
69  std::vector <PixelType> movingValues(this->m_NumberOfPixelsCounted);
70  unsigned int numOutside = 0;
71  PixelType zeroVector(vectorSize);
72  zeroVector.Fill(0.0);
73 
74  for (unsigned int i = 0;i < this->m_NumberOfPixelsCounted;++i)
75  {
76  transformedPoint = this->m_Transform->TransformPoint(m_FixedImagePoints[i]);
77  movingImage->TransformPhysicalPointToContinuousIndex(transformedPoint,transformedIndex);
78 
79  if (this->m_Interpolator->IsInsideBuffer(transformedIndex))
80  {
81  movingValues[i] = this->m_Interpolator->EvaluateAtContinuousIndex(transformedIndex);
82 
83  if (this->GetModelRotation() != Superclass::NONE)
84  {
85  // Rotating tensor
86  anima::GetTensorFromVectorRepresentation(movingValues[i],tmpMat,tensorDimension,true);
87 
88  if (this->GetModelRotation() == Superclass::FINITE_STRAIN)
89  anima::RotateSymmetricMatrix(tmpMat,this->m_OrientationMatrix,currentTensor);
90  else
91  {
92  eigenComputer.ComputeEigenValuesAndVectors(tmpMat,eigVals,eigVecs);
93  anima::ExtractPPDRotationFromJacobianMatrix(this->m_OrientationMatrix,ppdOrientationMatrix,eigVecs);
94  anima::RotateSymmetricMatrix(tmpMat,ppdOrientationMatrix,currentTensor);
95  }
96 
97  anima::GetVectorRepresentation(currentTensor,movingValues[i],vectorSize,true);
98  }
99 
100  for (unsigned int j = 0;j < vectorSize;++j)
101  movingMean[j] += movingValues[i][j];
102  }
103  else
104  {
105  ++numOutside;
106  movingValues[i] = zeroVector;
107  }
108  }
109 
110  if (this->m_NumberOfPixelsCounted / 2.0 < numOutside)
111  return 0.0;
112 
113  movingMean /= this->m_NumberOfPixelsCounted;
114 
115  for (unsigned int i = 0;i < this->m_NumberOfPixelsCounted;++i)
116  {
117  for (unsigned int j = 0;j < vectorSize;++j)
118  {
119  for (unsigned int k = 0;k < vectorSize;++k)
120  Sigma_XY(j,k) += (m_FixedImageValues[i][j] - m_FixedMean[j]) * (movingValues[i][k] - movingMean[k]);
121 
122  for (unsigned int k = j;k < vectorSize;++k)
123  Sigma_YY(j,k) += (movingValues[i][j] - movingMean[j]) * (movingValues[i][k] - movingMean[k]);
124  }
125  }
126 
127  Sigma_YY /= (this->m_NumberOfPixelsCounted - 1.0);
128 
129  bool isNull = true;
130  for (unsigned int i = 0;i < vectorSize;++i)
131  {
132  for (unsigned int j = i;j < vectorSize;++j)
133  {
134  if (Sigma_YY(i,j) != 0)
135  {
136  isNull = false;
137  break;
138  }
139  }
140 
141  if (!isNull)
142  break;
143  }
144 
145  if (isNull)
146  return 0.0;
147 
148  double movingVariance = 0;
149  for (unsigned int j = 0;j < vectorSize;++j)
150  for (unsigned int k = j;k < vectorSize;++k)
151  {
152  if (j == k)
153  movingVariance += Sigma_YY(j,k) * Sigma_YY(j,k);
154  else
155  movingVariance += 2 * Sigma_YY(j,k) * Sigma_YY(j,k);
156  }
157 
158  movingVariance = std::sqrt(movingVariance);
159  if (movingVariance <= m_VarianceThreshold)
160  return 0.0;
161 
162  Sigma_XY /= (this->m_NumberOfPixelsCounted - 1.0);
163 
164  for (unsigned int j = 0;j < vectorSize;++j)
165  for (unsigned int k = j + 1;k < vectorSize;++k)
166  Sigma_YY(k,j) = Sigma_YY(j,k);
167 
168  double ovlWeight = 1.0;
169  if (m_OrientationPenalty)
170  {
171  vnl_matrix <double> tmpXEVecs(tensorDimension,tensorDimension), tmpYEVecs(tensorDimension,tensorDimension);
172  vnl_diag_matrix <double> tmpEigX(tensorDimension), tmpEigY(tensorDimension);
173 
174  for (unsigned int i = 0;i < vectorSize;++i)
175  movingMean[i] /= this->m_NumberOfPixelsCounted;
176 
177  itk::SymmetricEigenAnalysis < vnl_matrix <double>, vnl_diag_matrix<double>, vnl_matrix <double> > eigenComputer(tensorDimension);
178 
179  anima::GetTensorFromVectorRepresentation(m_FixedMean,tmpMat,tensorDimension,true);
180  eigenComputer.ComputeEigenValuesAndVectors(tmpMat, tmpEigX, tmpXEVecs);
181 
182  anima::GetTensorFromVectorRepresentation(movingMean,tmpMat,tensorDimension,true);
183  eigenComputer.ComputeEigenValuesAndVectors(tmpMat, tmpEigY, tmpYEVecs);
184 
185  for (unsigned int a = 0;a < tensorDimension;++a)
186  {
187  tmpEigX[a] = std::exp(tmpEigX[a]);
188  tmpEigY[a] = std::exp(tmpEigY[a]);
189  }
190 
191  ovlWeight = anima::ovlScore(tmpEigX,tmpXEVecs,tmpEigY,tmpYEVecs);
192  }
193 
194  m_leCalculator->GetTensorPower(Sigma_YY,Sigma_YY,-0.5);
195 
196  tmpMat = m_FixedHalfInvCovarianceMatrix * Sigma_XY * Sigma_YY;
197 
198  double measure = 0;
199 
200  for (unsigned int i = 0;i < vectorSize;++i)
201  for (unsigned int j = 0;j < vectorSize;++j)
202  measure += tmpMat(i,j)*tmpMat(i,j);
203 
204  double tentativeMeasure = ovlWeight * measure / vectorSize;
205  measure = std::min(1.0,std::max(tentativeMeasure,0.0));
206 
207  return measure;
208 }
209 
210 template < class TFixedImagePixelType, class TMovingImagePixelType, unsigned int ImageDimension >
211 void
214 {
215  FixedImageConstPointer fixedImage = this->m_FixedImage;
216 
217  if (!fixedImage)
218  itkExceptionMacro("Fixed image has not been assigned");
219 
220  unsigned int vectorSize = fixedImage->GetNumberOfComponentsPerPixel();
221  if (m_FixedMean.GetSize() != vectorSize)
222  m_FixedMean.SetSize(vectorSize);
223  m_FixedMean.Fill(0);
224 
225  vnl_matrix <double> covarianceMatrix(vectorSize,vectorSize,0);
226 
227  typedef itk::ImageRegionConstIteratorWithIndex<FixedImageType> FixedIteratorType;
228 
229  FixedIteratorType ti( fixedImage, this->GetFixedImageRegion() );
230 
231  this->m_NumberOfPixelsCounted = this->GetFixedImageRegion().GetNumberOfPixels();
232 
233  m_FixedImagePoints.resize(this->m_NumberOfPixelsCounted);
234  m_FixedImageValues.resize(this->m_NumberOfPixelsCounted);
235 
236  InputPointType inputPoint;
237 
238  unsigned int pos = 0;
239  while (!ti.IsAtEnd())
240  {
241  fixedImage->TransformIndexToPhysicalPoint( ti.GetIndex(), inputPoint );
242 
243  m_FixedImagePoints[pos] = inputPoint;
244  m_FixedImageValues[pos] = ti.Get();
245 
246  for (unsigned int i = 0;i < vectorSize;++i)
247  m_FixedMean[i] += m_FixedImageValues[pos][i];
248 
249  ++ti;
250  ++pos;
251  }
252 
253  m_FixedMean /= this->m_NumberOfPixelsCounted;
254  for (unsigned int k = 0;k < this->m_NumberOfPixelsCounted;++k)
255  {
256  for (unsigned int i = 0;i < vectorSize;++i)
257  {
258  for (unsigned int j = i;j < vectorSize;++j)
259  covarianceMatrix(i,j) += (m_FixedImageValues[k][i] - m_FixedMean[i]) * (m_FixedImageValues[k][j] - m_FixedMean[j]);
260  }
261  }
262 
263  covarianceMatrix /= this->m_NumberOfPixelsCounted;
264 
265  for (unsigned int i = 0;i < vectorSize;++i)
266  {
267  for (unsigned int j = i+1;j < vectorSize;++j)
268  covarianceMatrix(j,i) = covarianceMatrix(i,j);
269  }
270 
271  m_leCalculator->GetTensorPower(covarianceMatrix,m_FixedHalfInvCovarianceMatrix,-0.5);
272 }
273 
274 template < class TFixedImagePixelType, class TMovingImagePixelType, unsigned int ImageDimension >
275 void
277 ::PrintSelf(std::ostream& os, itk::Indent indent) const
278 {
279  Superclass::PrintSelf(os, indent);
280  os << indent << m_FixedMean << std::endl;
281  os << indent << m_FixedHalfInvCovarianceMatrix << std::endl;
282 }
283 
284 } // end of namespace anima
double ovlScore(vnl_diag_matrix< T1 > &eigsX, vnl_matrix< T1 > &eigVecsX, vnl_diag_matrix< T1 > &eigsY, vnl_matrix< T1 > &eigVecsY)
void GetVectorRepresentation(const vnl_matrix< T1 > &tensor, itk::VariableLengthVector< T2 > &vector, unsigned int vecDim=0, bool scale=false)
MeasureType GetValue(const TransformParametersType &parameters) const ITK_OVERRIDE
void RotateSymmetricMatrix(T1 &tensor, T2 &rotationMatrix, T3 &rotated_tensor, unsigned int tensorDim)
Rotates a symmetric matrix by performing R^T D R where R is a rotation matrix and D the symmetric mat...
void GetTensorFromVectorRepresentation(const itk::VariableLengthVector< T1 > &vector, vnl_matrix< T2 > &tensor, unsigned int tensDim=0, bool scale=false)
void PrintSelf(std::ostream &os, itk::Indent indent) const ITK_OVERRIDE
void ExtractPPDRotationFromJacobianMatrix(vnl_matrix< RealType > &jacobianMatrix, vnl_matrix< RealType > &rotationMatrix, MatrixType &eigenVectors)