11 #include <itkLinearInterpolateImageFunction.h> 13 #include <itkImageRegionConstIterator.h> 18 template <
typename TInputImageType>
26 m_SkewMax = M_PI / 4.0;
29 m_SearchSkewRadius = 5;
30 m_SearchScaleRadius = 0.1;
32 m_TransformDirection = 1;
35 template <
typename TInputImageType>
46 template <
typename TInputImageType>
51 return AgregatorType::AFFINE;
54 template <
typename TInputImageType>
61 switch(m_SimilarityType)
68 typename LocalMetricType::Pointer tmpMetric = LocalMetricType::New();
70 tmpMetric->SetScaleIntensities(
true);
81 typename LocalMetricType::Pointer tmpMetric = LocalMetricType::New();
82 tmpMetric->SetScaleIntensities(
true);
89 typedef itk::ImageToImageMetric <InputImageType,InputImageType> BaseMetricType;
90 BaseMetricType *baseMetric = dynamic_cast <BaseMetricType *> (metric.GetPointer());
92 typedef itk::LinearInterpolateImageFunction<InputImageType,double> LocalInterpolatorType;
93 typename LocalInterpolatorType::Pointer interpolator = LocalInterpolatorType::New();
95 baseMetric->SetInterpolator(interpolator);
96 baseMetric->ComputeGradientOff();
98 baseMetric->SetFixedImage(this->GetReferenceImage());
99 baseMetric->SetMovingImage(this->GetMovingImage());
100 interpolator->SetInputImage(this->GetMovingImage());
105 template <
typename TInputImageType>
113 typename BaseTransformType::Pointer tmpTr;
115 switch(m_BlockTransformType)
132 tmpTr = BaseTransformType::New();
137 typename BaseTransformType::HomogeneousMatrixType geometry;
139 geometry.SetIdentity();
140 for (
unsigned int i = 0;i < 3;++i)
141 for (
unsigned int j = 0;j < 3;++j)
142 geometry(i,j) = this->GetReferenceImage()->GetDirection()(i,j) * this->GetReferenceImage()->GetSpacing()[j];
144 tmpTr->SetIdentity();
145 for (
unsigned int j = 0;j < 3;++j)
146 geometry(j,InputImageType::ImageDimension) = blockCenter[j];
148 tmpTr->SetUniqueDirection(m_TransformDirection);
149 tmpTr->SetGeometry(geometry,
false);
156 template <
typename TInputImageType>
161 double similarityWeight = 0;
163 switch (m_SimilarityType)
166 similarityWeight = 1;
169 similarityWeight = (val + 1) / 2.0;
173 similarityWeight = val;
177 std::vector <double> localGradient(InputImageType::ImageDimension,0);
178 itk::ImageRegionConstIterator <InputImageType> fixedItr(this->GetReferenceImage(),this->GetBlockRegion(block));
180 typename ImageRegionType::IndexType currentIndex, modifiedIndex;
182 typename InputImageType::DirectionType orientationMatrix = this->GetReferenceImage()->GetDirection();
183 typename InputImageType::SpacingType imageSpacing = this->GetReferenceImage()->GetSpacing();
184 typename InputImageType::SizeType imageSize = this->GetReferenceImage()->GetLargestPossibleRegion().GetSize();
186 std::vector <double> correctionDirection(InputImageType::ImageDimension);
187 for (
unsigned int i = 0;i < InputImageType::ImageDimension;++i)
188 correctionDirection[i] = this->GetReferenceImage()->GetDirection()(i,m_TransformDirection);
190 vnl_matrix <double> meanStructureTensor(InputImageType::ImageDimension,InputImageType::ImageDimension);
191 meanStructureTensor.fill(0);
193 while (!fixedItr.IsAtEnd())
195 currentIndex = fixedItr.GetIndex();
196 std::fill(localGradient.begin(),localGradient.end(),0);
198 for (
unsigned int i = 0;i < InputImageType::ImageDimension;++i)
200 modifiedIndex = currentIndex;
201 modifiedIndex[i] = std::max(0,(
int)(currentIndex[i] - 1));
202 double previousValue = this->GetReferenceImage()->GetPixel(modifiedIndex);
203 modifiedIndex[i] = std::min((
int)(imageSize[i] - 1),(
int)(currentIndex[i] + 1));
204 double postValue = this->GetReferenceImage()->GetPixel(modifiedIndex);
206 for (
unsigned int j = 0;j < InputImageType::ImageDimension;++j)
207 localGradient[j] += (postValue - previousValue) * orientationMatrix(j,i) / (2.0 * imageSpacing[i]);
210 for (
unsigned int i = 0;i < InputImageType::ImageDimension;++i)
211 for (
unsigned int j = i;j < InputImageType::ImageDimension;++j)
213 meanStructureTensor(i,j) += localGradient[i] * localGradient[j];
215 meanStructureTensor(j,i) = meanStructureTensor(i,j);
221 meanStructureTensor /= this->GetBlockRegion(block).GetNumberOfPixels();
223 itk::SymmetricEigenAnalysis < vnl_matrix <double>, vnl_diag_matrix<double>, vnl_matrix <double> > eigenComputer(InputImageType::ImageDimension);
224 vnl_matrix <double> eVec(InputImageType::ImageDimension,InputImageType::ImageDimension);
225 vnl_diag_matrix <double> eVals(InputImageType::ImageDimension);
227 eigenComputer.ComputeEigenValuesAndVectors(meanStructureTensor, eVals, eVec);
228 double linearCoef = (eVals[InputImageType::ImageDimension - 1] - eVals[InputImageType::ImageDimension - 2]) / eVals[InputImageType::ImageDimension - 1];
230 double scalarProduct = 0;
231 for (
unsigned int i = 0;i < InputImageType::ImageDimension;++i)
232 scalarProduct += eVec[InputImageType::ImageDimension - 1][i] * correctionDirection[i];
234 double structureWeight = linearCoef * std::abs(scalarProduct);
236 return std::sqrt(structureWeight * similarityWeight);
239 template <
typename TInputImageType>
245 BaseTransformType *tr = dynamic_cast <BaseTransformType *> (this->GetBlockTransformPointer(block).GetPointer());
249 typedef itk::ImageToImageMetric <InputImageType, InputImageType> InternalMetricType;
250 InternalMetricType *tmpMetric = dynamic_cast <InternalMetricType *> (metric.GetPointer());
251 tmpMetric->SetFixedImageRegion(this->GetBlockRegion(block));
252 tmpMetric->SetTransform(this->GetBlockTransformPointer(block));
253 tmpMetric->Initialize();
261 template <
typename TInputImageType>
267 throw itk::ExceptionObject(__FILE__, __LINE__,
"Exhaustive optimizer not supported in distortion correction",ITK_LOCATION);
270 LocalOptimizerType::ScalesType tmpScales(this->GetBlockTransformPointer(0)->GetNumberOfParameters());
271 LocalOptimizerType::ScalesType lowerBounds(this->GetBlockTransformPointer(0)->GetNumberOfParameters());
272 LocalOptimizerType::ScalesType upperBounds(this->GetBlockTransformPointer(0)->GetNumberOfParameters());
273 typename InputImageType::SpacingType fixedSpacing = this->GetReferenceImage()->GetSpacing();
278 double scaleFactor = 1.0;
279 if ((m_BlockTransformType !=
Direction)&&(m_ScaleMax > 0))
280 scaleFactor = - m_ScaleMax / (std::exp(- m_ScaleMax) - 1.0);
282 switch (m_BlockTransformType)
286 tmpScales[0] = this->GetSearchRadius() / m_SearchScaleRadius;
287 tmpScales[1] = this->GetSearchRadius() / m_SearchSkewRadius;
288 tmpScales[2] = this->GetSearchRadius() / m_SearchSkewRadius;
291 lowerBounds[0] = - m_ScaleMax;
292 upperBounds[0] = m_ScaleMax;
293 lowerBounds[1] = - m_SkewMax * scaleFactor;
294 upperBounds[1] = m_SkewMax * scaleFactor;
295 lowerBounds[2] = - m_SkewMax * scaleFactor;
296 upperBounds[2] = m_SkewMax * scaleFactor;
297 lowerBounds[3] = - m_TranslateMax * scaleFactor;
298 upperBounds[3] = m_TranslateMax * scaleFactor;
305 tmpScales[0] = this->GetSearchRadius() / m_SearchScaleRadius;
308 lowerBounds[0] = - m_ScaleMax;
309 upperBounds[0] = m_ScaleMax;
310 lowerBounds[1] = - m_TranslateMax * scaleFactor;
311 upperBounds[1] = m_TranslateMax * scaleFactor;
321 lowerBounds[0] = - m_TranslateMax;
322 upperBounds[0] = m_TranslateMax;
328 LocalOptimizerType * tmpOpt = dynamic_cast <LocalOptimizerType *> (optimizer.GetPointer());
329 tmpOpt->SetScales(tmpScales);
330 tmpOpt->SetLowerBounds(lowerBounds);
331 tmpOpt->SetUpperBounds(upperBounds);
MetricType::Pointer MetricPointer
Superclass::BaseInputTransformPointer BaseInputTransformPointer
virtual void BlockMatchingSetup(MetricPointer &metric, unsigned int block)
bool GetMaximizedMetric()
virtual MetricPointer SetupMetric()
BaseInputTransformType::Pointer BaseInputTransformPointer
virtual void TransformDependantOptimizerSetup(OptimizerPointer &optimizer)
InputImageType::PointType PointType
DistortionCorrectionBlockMatcher()
OptimizerType::Pointer OptimizerPointer
InputImageType::RegionType ImageRegionType
Superclass::MetricPointer MetricPointer
virtual BaseInputTransformPointer GetNewBlockTransform(PointType &blockCenter)
virtual double ComputeBlockWeight(double val, unsigned int block)
AgregatorType::TRANSFORM_TYPE GetAgregatorInputTransformType()