Orfeo Toolbox  3.16
itkFastSymmetricForcesDemonsRegistrationFunction.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkFastSymmetricForcesDemonsRegistrationFunction.txx,v $
5  Language: C++
6  Date: $Date: 2008-12-21 19:13:11 $
7  Version: $Revision: 1.5 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifndef __itkFastSymmetricForcesDemonsRegistrationFunction_txx
18 #define __itkFastSymmetricForcesDemonsRegistrationFunction_txx
19 
21 #include "itkExceptionObject.h"
22 #include "vnl/vnl_math.h"
23 
24 namespace itk {
25 
29 template <class TFixedImage, class TMovingImage, class TDeformationField>
32 {
33 
34  RadiusType r;
35  unsigned int j;
36  for( j = 0; j < ImageDimension; j++ )
37  {
38  r[j] = 0;
39  }
40  this->SetRadius(r);
41 
42  m_TimeStep = 1.0;
43  m_DenominatorThreshold = 1e-9;
44  m_IntensityDifferenceThreshold = 0.001;
45  this->SetMovingImage(NULL);
46  this->SetFixedImage(NULL);
47  m_Normalizer = 0.0;
48  m_FixedImageGradientCalculator = GradientCalculatorType::New();
49 
50  typename DefaultInterpolatorType::Pointer interp =
51  DefaultInterpolatorType::New();
52 
53  m_MovingImageInterpolator = static_cast<InterpolatorType*>(
54  interp.GetPointer() );
55 
56  m_WarpedMovingImageGradientCalculator = MovingGradientCalculatorType::New();
57  m_MovingImageWarper = WarperType::New();
58  m_MovingImageWarper->SetInterpolator( m_MovingImageInterpolator );
59 
60  m_Metric = NumericTraits<double>::max();
61  m_SumOfSquaredDifference = 0.0;
62  m_NumberOfPixelsProcessed = 0L;
63  m_RMSChange = NumericTraits<double>::max();
64  m_SumOfSquaredChange = 0.0;
65 
66 }
67 
68 
72 template <class TFixedImage, class TMovingImage, class TDeformationField>
73 void
75 ::PrintSelf(std::ostream& os, Indent indent) const
76 {
77  Superclass::PrintSelf(os, indent);
78 
79  os << indent << "MovingImageIterpolator: ";
80  os << m_MovingImageInterpolator.GetPointer() << std::endl;
81  os << indent << "FixedImageGradientCalculator: ";
82  os << m_FixedImageGradientCalculator.GetPointer() << std::endl;
83  os << indent << "DenominatorThreshold: ";
84  os << m_DenominatorThreshold << std::endl;
85  os << indent << "IntensityDifferenceThreshold: ";
86  os << m_IntensityDifferenceThreshold << std::endl;
87 
88  os << indent << "Metric: ";
89  os << m_Metric << std::endl;
90  os << indent << "SumOfSquaredDifference: ";
91  os << m_SumOfSquaredDifference << std::endl;
92  os << indent << "NumberOfPixelsProcessed: ";
93  os << m_NumberOfPixelsProcessed << std::endl;
94  os << indent << "RMSChange: ";
95  os << m_RMSChange << std::endl;
96  os << indent << "SumOfSquaredChange: ";
97  os << m_SumOfSquaredChange << std::endl;
98 
99 }
100 
104 template <class TFixedImage, class TMovingImage, class TDeformationField>
105 void
108 {
109  m_IntensityDifferenceThreshold = threshold;
110 }
111 
115 template <class TFixedImage, class TMovingImage, class TDeformationField>
116 double
119 {
120  return m_IntensityDifferenceThreshold;
121 }
122 
126 template <class TFixedImage, class TMovingImage, class TDeformationField>
127 void
130 {
131  if( !this->GetMovingImage() || !this->GetFixedImage() || !m_MovingImageInterpolator )
132  {
133  itkExceptionMacro( << "MovingImage, FixedImage and/or Interpolator not set" );
134  }
135 
136  // cache fixed image information
137  const PixelType fixedImageSpacing = this->GetFixedImage()->GetSpacing();
138 
139  // compute the normalizer
140  m_Normalizer = 0.0;
141  for( unsigned int k = 0; k < ImageDimension; k++ )
142  {
143  m_Normalizer += fixedImageSpacing[k] * fixedImageSpacing[k];
144  }
145  m_Normalizer /= static_cast<double>( ImageDimension );
146 
147 
148  // setup gradient calculator
149  m_FixedImageGradientCalculator->SetInputImage( this->GetFixedImage() );
150 
151  m_MovingImageWarper->SetOutputOrigin( this->GetFixedImage()->GetOrigin() );
152  m_MovingImageWarper->SetOutputSpacing( this->GetFixedImage()->GetSpacing() );
153  m_MovingImageWarper->SetOutputDirection( this->GetFixedImage()->GetDirection() );
154  m_MovingImageWarper->SetInput( this->GetMovingImage() );
155  m_MovingImageWarper->SetDeformationField( this->GetDeformationField() );
156  m_MovingImageWarper->Update();
157  m_WarpedMovingImageGradientCalculator->SetInputImage( this->m_MovingImageWarper->GetOutput() );
158 
159  // setup moving image interpolator for further access
160  m_MovingImageInterpolator->SetInputImage( this->GetMovingImage() );
161 
162  // initialize metric computation variables
163  m_SumOfSquaredDifference = 0.0;
164  m_NumberOfPixelsProcessed = 0L;
165  m_SumOfSquaredChange = 0.0;
166 
167 }
168 
169 
173 template <class TFixedImage, class TMovingImage, class TDeformationField>
175 ::PixelType
177 ::ComputeUpdate(const NeighborhoodType &it, void * gd,
178  const FloatOffsetType& itkNotUsed(offset))
179 {
180  GlobalDataStruct *globalData = (GlobalDataStruct *)gd;
181  const IndexType FirstIndex = this->GetFixedImage()->GetLargestPossibleRegion().GetIndex();
182  const IndexType LastIndex = this->GetFixedImage()->GetLargestPossibleRegion().GetIndex() +
183  this->GetFixedImage()->GetLargestPossibleRegion().GetSize();
184 
185  const IndexType index = it.GetIndex();
186 
187  // Get fixed image related information
188  // Note: no need to check the index is within
189  // fixed image buffer. This is done by the external filter.
190  const double fixedValue = (double) this->GetFixedImage()->GetPixel( index );
191  const CovariantVectorType fixedGradient = m_FixedImageGradientCalculator->EvaluateAtIndex( index );
192 
193  // Get moving image related information
194  // use warped moving image to get moving value and gradient fast(er).
195  const double movingValue = (double) m_MovingImageWarper->GetOutput()->GetPixel( index );
196  const CovariantVectorType movingGradient = m_WarpedMovingImageGradientCalculator->EvaluateAtIndex( index );
197 
198  // unfortunately (since it's a little redundant) we still need the mapped center point coordinates
199  PointType mappedCenterPoint;
200  this->GetFixedImage()->TransformIndexToPhysicalPoint(index, mappedCenterPoint);
201  for( unsigned int dim = 0; dim < ImageDimension; dim++ )
202  {
203  mappedCenterPoint[dim] += it.GetCenterPixel()[dim];
204  }
205 
220  double fixedPlusMovingGradientSquaredMagnitude = 0;
221  for( unsigned int dim = 0; dim < ImageDimension; dim++ )
222  {
223  fixedPlusMovingGradientSquaredMagnitude += vnl_math_sqr( fixedGradient[dim] + movingGradient[dim] );
224  }
225 
226  const double speedValue = fixedValue - movingValue;
227  const double denominator = vnl_math_sqr( speedValue ) / m_Normalizer + fixedPlusMovingGradientSquaredMagnitude;
228 
229  PixelType update;
230  if ( vnl_math_abs(speedValue) < m_IntensityDifferenceThreshold || denominator < m_DenominatorThreshold )
231  {
232  update.Fill(0.0);
233  }
234  else
235  {
236  for( unsigned int j = 0; j < ImageDimension; j++ )
237  {
238  update[j] = 2 * speedValue * (movingGradient[j] + fixedGradient[j]) / denominator;
239  }
240  }
241 
242  // update the squared change value
243  PointType newMappedCenterPoint;
244  bool IsOutsideRegion = 0;
245  for( unsigned int j = 0; j < ImageDimension; j++ )
246  {
247  if ( globalData )
248  {
249  globalData->m_SumOfSquaredChange += vnl_math_sqr( update[j] );
250  newMappedCenterPoint[j] = mappedCenterPoint[j] + update[j];
251  if ( index[j] < (FirstIndex[j] + 2) || index[j] > (LastIndex[j] - 3) )
252  {
253  IsOutsideRegion = 1;
254  }
255  }
256  }
257 
258  // update the metric with the latest deformable field
259  double newMovingValue=0;
260  if ( globalData )
261  {
262  // do not consider voxel on the border (2 voxels) as there are often artefacts
263  // which falsify the metric
264  if( !IsOutsideRegion )
265  {
266  if( m_MovingImageInterpolator->IsInsideBuffer( newMappedCenterPoint ) )
267  {
268  newMovingValue = m_MovingImageInterpolator->Evaluate( newMappedCenterPoint );
269  }
270  else
271  {
272  newMovingValue = 0;
273  }
274  globalData->m_SumOfSquaredDifference += vnl_math_sqr( fixedValue - newMovingValue );
275  globalData->m_NumberOfPixelsProcessed += 1;
276  }
277  }
278  return update;
279 }
280 
281 
285 template <class TFixedImage, class TMovingImage, class TDeformationField>
286 void
288 ::ReleaseGlobalDataPointer( void *gd ) const
289 {
290  GlobalDataStruct * globalData = (GlobalDataStruct *) gd;
291 
292  m_MetricCalculationLock.Lock();
293  m_SumOfSquaredDifference += globalData->m_SumOfSquaredDifference;
294  m_NumberOfPixelsProcessed += globalData->m_NumberOfPixelsProcessed;
295  m_SumOfSquaredChange += globalData->m_SumOfSquaredChange;
296  if ( m_NumberOfPixelsProcessed )
297  {
298  m_Metric = m_SumOfSquaredDifference /
299  static_cast<double>( m_NumberOfPixelsProcessed );
300  m_RMSChange = vcl_sqrt( m_SumOfSquaredChange /
301  static_cast<double>( m_NumberOfPixelsProcessed ) );
302  }
303  m_MetricCalculationLock.Unlock();
304 
305  delete globalData;
306 }
307 
308 } // end namespace itk
309 
310 #endif

Generated at Sat Feb 2 2013 23:36:36 for Orfeo Toolbox with doxygen 1.8.1.1