4 #include <vnl/vnl_matrix_fixed.h> 6 #include <itkImageRegionConstIteratorWithIndex.h> 8 #include <boost/math/special_functions/factorials.hpp> 13 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
17 m_FixedImagePoints.clear();
18 m_FixedImageValues.clear();
26 m_ZeroDiffusionVector = m_ZeroDiffusionModel->GetModelVector();
28 m_OneToOneMapping =
false;
30 m_leCalculator = LECalculatorType::New();
33 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
40 for (
unsigned int i = 0;i < val->GetNumberOfCompartments();++i)
42 if (!val->GetCompartment(i)->GetTensorCompatible())
47 val = movingImage->GetDescriptionModel();
48 for (
unsigned int i = 0;i < val->GetNumberOfCompartments();++i)
50 if (!val->GetCompartment(i)->GetTensorCompatible())
57 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
65 itkExceptionMacro(
"Fixed image has not been assigned");
67 if (this->m_NumberOfPixelsCounted == 0)
70 this->SetTransformParameters( parameters );
78 MCModelPointer currentMovingValue = movingImage->GetDescriptionModel()->Clone();
81 bool tensorCompatibilityCondition = this->CheckTensorCompatibility();
83 for (
unsigned int i = 0;i < this->m_NumberOfPixelsCounted;++i)
85 transformedPoint = this->m_Transform->TransformPoint( m_FixedImagePoints[i] );
86 this->m_Interpolator->GetInputImage()->TransformPhysicalPointToContinuousIndex(transformedPoint,transformedIndex);
88 if( this->m_Interpolator->IsInsideBuffer( transformedIndex ) )
90 movingValue = this->m_Interpolator->EvaluateAtContinuousIndex( transformedIndex );
92 if (!isZero(movingValue))
94 currentMovingValue->SetModelVector(movingValue);
96 if (this->GetModelRotation() != Superclass::NONE)
97 currentMovingValue->Reorient(this->m_OrientationMatrix, (this->GetModelRotation() ==
Superclass::PPD));
100 if (tensorCompatibilityCondition)
101 measure += this->ComputeTensorBasedMetricPart(i,currentMovingValue);
103 measure += this->ComputeNonTensorBasedMetricPart(i,currentMovingValue);
107 if (tensorCompatibilityCondition)
108 measure += this->ComputeTensorBasedMetricPart(i,m_ZeroDiffusionModel);
110 measure += this->ComputeNonTensorBasedMetricPart(i,m_ZeroDiffusionModel);
115 if (tensorCompatibilityCondition)
116 measure += this->ComputeTensorBasedMetricPart(i,m_ZeroDiffusionModel);
118 measure += this->ComputeNonTensorBasedMetricPart(i,m_ZeroDiffusionModel);
126 measure /= this->m_NumberOfPixelsCounted;
130 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
135 unsigned int fixedNumCompartments = m_FixedImageValues[index]->GetNumberOfCompartments();
136 unsigned int movingNumCompartments = movingValue->GetNumberOfCompartments();
138 typedef itk::VariableLengthVector <double> LogVectorType;
139 std::vector <LogVectorType> fixedLogVectors(fixedNumCompartments);
140 std::vector <LogVectorType> movingLogVectors(movingNumCompartments);
141 std::vector <double> fixedWeights(fixedNumCompartments);
142 std::vector <double> movingWeights(movingNumCompartments);
143 vnl_matrix <double> workLogMatrix(3,3);
145 unsigned int pos = 0;
146 for (
unsigned int i = 0;i < fixedNumCompartments;++i)
148 if (m_FixedImageValues[index]->GetCompartmentWeight(i) == 0)
151 m_leCalculator->GetTensorLogarithm(m_FixedImageValues[index]->GetCompartment(i)->GetDiffusionTensor().GetVnlMatrix().as_matrix(),
155 fixedWeights[pos] = m_FixedImageValues[index]->GetCompartmentWeight(i);
159 fixedNumCompartments = pos;
161 if (fixedNumCompartments == 0)
163 fixedLogVectors.resize(fixedNumCompartments);
164 fixedWeights.resize(fixedNumCompartments);
167 for (
unsigned int i = 0;i < movingNumCompartments;++i)
169 if (movingValue->GetCompartmentWeight(i) == 0)
172 m_leCalculator->GetTensorLogarithm(movingValue->GetCompartment(i)->GetDiffusionTensor().GetVnlMatrix().as_matrix(),
176 movingWeights[pos] = movingValue->GetCompartmentWeight(i);
180 movingNumCompartments = pos;
182 if (movingNumCompartments == 0)
184 movingLogVectors.resize(movingNumCompartments);
185 movingWeights.resize(movingNumCompartments);
187 double bestMetricValue = -1;
189 unsigned int minCompartmentsNumber = fixedNumCompartments;
190 int rest = movingNumCompartments - minCompartmentsNumber;
191 bool fixedMin =
true;
195 minCompartmentsNumber = movingNumCompartments;
199 unsigned int maxCompartmentsNumber = minCompartmentsNumber + rest;
200 unsigned int totalNumPairingVectors = 1;
201 if (!m_OneToOneMapping)
202 totalNumPairingVectors = boost::math::factorial<double>(maxCompartmentsNumber-1)
203 / (boost::math::factorial<double>(minCompartmentsNumber-1)
204 * boost::math::factorial<double>(maxCompartmentsNumber - minCompartmentsNumber));
206 std::vector < std::vector <unsigned int> > numPairingsVectors(totalNumPairingVectors);
208 if (!m_OneToOneMapping)
210 std::vector <unsigned int> initialPairingsNumber(maxCompartmentsNumber-1,0);
211 std::vector <unsigned int> pairing(minCompartmentsNumber,1);
212 for (
unsigned int i = minCompartmentsNumber-1;i < maxCompartmentsNumber-1;++i)
213 initialPairingsNumber[i] = 1;
215 unsigned int countVector = 0;
218 unsigned int pos = 0;
219 std::fill(pairing.begin(),pairing.end(),1);
220 for (
unsigned int i = 0;i < maxCompartmentsNumber-1;++i)
222 if (initialPairingsNumber[i] == 0)
231 numPairingsVectors[countVector] = pairing;
233 }
while (std::next_permutation(initialPairingsNumber.begin(),initialPairingsNumber.end()));
237 unsigned int numCompartmentUsed = minCompartmentsNumber;
239 ++numCompartmentUsed;
240 std::vector <unsigned int> initialPairingsNumber(numCompartmentUsed,1);
242 initialPairingsNumber[minCompartmentsNumber] = rest;
243 numPairingsVectors[0] = initialPairingsNumber;
247 std::vector <unsigned int> currentPermutation(maxCompartmentsNumber);
249 for (
unsigned int l = 0;l < totalNumPairingVectors;++l)
251 currentPermutation.resize(maxCompartmentsNumber);
254 for (
unsigned int i = 0;i < numPairingsVectors[l].size();++i)
255 for (
unsigned int j = 0;j < numPairingsVectors[l][i];++j)
257 currentPermutation[pos] = i;
263 double metricValue = 0;
265 for (
unsigned int j = 0;j < maxCompartmentsNumber;++j)
267 unsigned int firstIndex;
268 unsigned int secondIndex;
272 firstIndex = currentPermutation[j];
278 secondIndex = currentPermutation[j];
281 if ((firstIndex >= fixedLogVectors.size())||(secondIndex >= movingLogVectors.size()))
285 for (
unsigned int k = 0;k < fixedLogVectors[firstIndex].GetSize();++k)
286 dist += (fixedLogVectors[firstIndex][k] - movingLogVectors[secondIndex][k]) * (fixedLogVectors[firstIndex][k] - movingLogVectors[secondIndex][k]);
288 if (!m_OneToOneMapping)
289 dist /= numPairingsVectors[l][currentPermutation[j]];
291 metricValue += fixedWeights[firstIndex] * movingWeights[secondIndex] * dist;
294 if ((metricValue < bestMetricValue)||(bestMetricValue < 0))
295 bestMetricValue = metricValue;
296 }
while(std::next_permutation(currentPermutation.begin(),currentPermutation.end()));
299 return bestMetricValue;
302 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
307 itkExceptionMacro(
"DDI basic metric not implemented yet");
311 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
316 unsigned int ndim = vector.GetSize();
318 for (
unsigned int i = 0;i < ndim;++i)
327 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
332 if(!this->m_FixedImage)
333 itkExceptionMacro( <<
"Fixed image has not been assigned" );
337 this->m_NumberOfPixelsCounted = this->GetFixedImageRegion().GetNumberOfPixels();
338 typedef itk::ImageRegionConstIteratorWithIndex<FixedImageType> FixedIteratorType;
339 FixedIteratorType ti(fixedImage, this->GetFixedImageRegion());
340 typename FixedImageType::IndexType index;
342 m_FixedImagePoints.resize(this->m_NumberOfPixelsCounted);
343 m_FixedImageValues.resize(this->m_NumberOfPixelsCounted);
347 unsigned int pos = 0;
351 index = ti.GetIndex();
352 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
354 m_FixedImagePoints[pos] = inputPoint;
355 fixedValue = ti.Get();
357 if (!isZero(fixedValue))
359 m_FixedImageValues[pos] = fixedImage->GetDescriptionModel()->Clone();
360 m_FixedImageValues[pos]->SetModelVector(fixedValue);
364 m_FixedImageValues[pos] = m_ZeroDiffusionModel->Clone();
365 m_FixedImageValues[pos]->SetModelVector(m_ZeroDiffusionVector);
bool isZero(PixelType &vector) const
MCMPointer GetNewMultiCompartmentModel()
Superclass::TransformParametersType TransformParametersType
Superclass::FixedImageConstPointer FixedImageConstPointer
void SetNumberOfCompartments(unsigned int num)
Superclass::MeasureType MeasureType
void SetModelWithStationaryWaterComponent(bool arg)
void GetVectorRepresentation(const vnl_matrix< T1 > &tensor, itk::VariableLengthVector< T2 > &vector, unsigned int vecDim=0, bool scale=false)
Superclass::InputPointType InputPointType
Superclass::FixedImageType FixedImageType
bool CheckTensorCompatibility() const
Superclass::MovingImageType MovingImageType
itk::ContinuousIndex< double, ImageDimension > ContinuousIndexType
TFixedImage::PixelType PixelType
void PreComputeFixedValues()
MCMPairingMeanSquaresImageToImageMetric()
double ComputeNonTensorBasedMetricPart(unsigned int index, const MCModelPointer &movingValue) const
double ComputeTensorBasedMetricPart(unsigned int index, const MCModelPointer &movingValue) const
Superclass::OutputPointType OutputPointType
MCModelType::Pointer MCModelPointer
Really this class is some simplified factory that creates the MCM that it knows.
MeasureType GetValue(const TransformParametersType ¶meters) const ITK_OVERRIDE
void SetModelWithFreeWaterComponent(bool arg)