Orfeo Toolbox  3.16
itkKappaStatisticImageToImageMetric.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkKappaStatisticImageToImageMetric.txx,v $
5  Language: C++
6  Date: $Date: 2009-01-24 20:02:57 $
7  Version: $Revision: 1.12 $
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 __itkKappaStatisticImageToImageMetric_txx
18 #define __itkKappaStatisticImageToImageMetric_txx
19 
23 
24 namespace itk
25 {
26 
30 template <class TFixedImage, class TMovingImage>
33 {
34  itkDebugMacro("Constructor");
35 
36  this->SetComputeGradient( true );
37  m_ForegroundValue = 255;
38  m_Complement = false;
39 }
40 
41 
45 template <class TFixedImage, class TMovingImage>
48 ::GetValue( const TransformParametersType & parameters ) const
49 {
50  itkDebugMacro("GetValue( " << parameters << " ) ");
51 
52  this->SetTransformParameters( parameters );
53 
54  //Get the fixed image
55  //
56  //
57  FixedImageConstPointer fixedImage = this->m_FixedImage;
58  if( !fixedImage )
59  {
60  itkExceptionMacro( << "Fixed image has not been assigned" );
61  }
62 
63  //Get an iterator over the fixed image
64  //
65  //
66  typedef ImageRegionConstIteratorWithIndex<FixedImageType> FixedIteratorType;
67  typename FixedImageType::IndexType fixedIndex;
68  FixedIteratorType fi( fixedImage, fixedImage->GetBufferedRegion() );
69 
70  //Get the moving image
71  //
72  //
73  MovingImageConstPointer movingImage = this->m_MovingImage;
74  if( !movingImage )
75  {
76  itkExceptionMacro( << "Moving image has not been assigned" );
77  }
78 
79  //Following are used in the metric computation. 'measure' is the
80  //value of the metric. 'fixedForegroundArea' is the total area
81  //of the foreground region in the fixed image.
82  //'movingForegroundArea' is the foreground area in the moving image
83  //in the area of overlap under the current transformation.
84  //'intersection' is the area of foreground intersection between the
85  //fixed and moving image.
86  //
87  //
88  MeasureType measure;
89  MeasureType intersection = NumericTraits< MeasureType >::Zero;
90  MeasureType movingForegroundArea = NumericTraits< MeasureType >::Zero;
91  MeasureType fixedForegroundArea = NumericTraits< MeasureType >::Zero;
92 
93  //Compute fixedForegroundArea, movingForegroundArea, and
94  //intersection. Loop over the fixed image.
95  //
96  //
97  while(!fi.IsAtEnd())
98  {
99  fixedIndex = fi.GetIndex();
100 
101  InputPointType fixedInputPoint;
102  fixedImage->TransformIndexToPhysicalPoint( fixedIndex, fixedInputPoint );
103 
104  if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( fixedInputPoint ) )
105  {
106  ++fi;
107  continue;
108  }
109 
110  const RealType fixedValue = fi.Get();
111 
112  //Increment 'fixedForegroundArea'
113  //
114  //
115  if (fixedValue==m_ForegroundValue)
116  {
117  fixedForegroundArea++;
118  }
119 
120  //Get the point in the transformed moving image corresponding to
121  //the point in the fixed image (physical coordinates)
122  //
123  //
125  transformedPoint = this->m_Transform->TransformPoint( fixedInputPoint );
126 
127  if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) )
128  {
129  ++fi;
130  continue;
131  }
132 
133  //Compute movingForegroundArea and intersection
134  //
135  //
136  if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) )
137  {
138  const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
139  if (movingValue==m_ForegroundValue)
140  {
141  movingForegroundArea++;
142  }
143  if ((movingValue==m_ForegroundValue)&&(fixedValue==m_ForegroundValue))
144  {
145  intersection++;
146  }
147  }
148  ++fi;
149  }
150 
151  //Compute the final metric value
152  //
153  //
154  if (!m_Complement)
155  {
156  measure = 2.0*(intersection)/(fixedForegroundArea+movingForegroundArea);
157  }
158  else
159  {
160  measure = 1.0-2.0*(intersection)/(fixedForegroundArea+movingForegroundArea);
161  }
162 
163  return measure;
164 }
165 
166 
170 template < class TFixedImage, class TMovingImage>
171 void
174  DerivativeType & derivative ) const
175 {
176  itkDebugMacro("GetDerivative( " << parameters << " ) ");
177 
178  if( !this->GetGradientImage() )
179  {
180  itkExceptionMacro(<<"The gradient image is null, maybe you forgot to call Initialize()");
181  }
182 
183  FixedImageConstPointer fixedImage = this->m_FixedImage;
184  if( !fixedImage )
185  {
186  itkExceptionMacro( << "Fixed image has not been assigned" );
187  }
188 
189  const unsigned int ImageDimension = FixedImageType::ImageDimension;
190 
191  typedef ImageRegionConstIteratorWithIndex< FixedImageType > FixedIteratorType;
192 
193  FixedIteratorType ti( fixedImage, this->GetFixedImageRegion() );
194 
195  typename FixedImageType::IndexType index;
196 
197  this->m_NumberOfPixelsCounted = 0;
198 
199  this->SetTransformParameters( parameters );
200 
201  const unsigned int ParametersDimension = this->GetNumberOfParameters();
202  derivative = DerivativeType( ParametersDimension );
203  derivative.Fill( NumericTraits<ITK_TYPENAME DerivativeType::ValueType>::Zero );
204 
205  typedef Array<double> ArrayType;
206 
207  ArrayType sum1 = ArrayType( ParametersDimension );
208  sum1.Fill( NumericTraits<ITK_TYPENAME ArrayType::ValueType>::Zero );
209 
210  ArrayType sum2 = ArrayType( ParametersDimension );
211  sum2.Fill( NumericTraits<ITK_TYPENAME ArrayType::ValueType>::Zero );
212 
213  int fixedArea = 0;
214  int movingArea = 0;
215  int intersection = 0;
216 
217  ti.GoToBegin();
218  while(!ti.IsAtEnd())
219  {
220  index = ti.GetIndex();
221 
222  InputPointType inputPoint;
223  fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
224 
225  if( this->m_FixedImageMask && !this->m_FixedImageMask->IsInside( inputPoint ) )
226  {
227  ++ti;
228  continue;
229  }
230 
231  const RealType fixedValue = ti.Value();
232  if ( fixedValue == m_ForegroundValue )
233  {
234  fixedArea++;
235  }
236 
237  OutputPointType transformedPoint = this->m_Transform->TransformPoint( inputPoint );
238 
239  if( this->m_MovingImageMask && !this->m_MovingImageMask->IsInside( transformedPoint ) )
240  {
241  ++ti;
242  continue;
243  }
244 
245  if( this->m_Interpolator->IsInsideBuffer( transformedPoint ) )
246  {
247  const RealType movingValue = this->m_Interpolator->Evaluate( transformedPoint );
248 
249  if ( movingValue == m_ForegroundValue )
250  {
251  movingArea++;
252  }
253 
254  if (( movingValue == m_ForegroundValue )&&( fixedValue == m_ForegroundValue ))
255  {
256  intersection++;
257  }
258 
259  const TransformJacobianType & jacobian =
260  this->m_Transform->GetJacobian( inputPoint );
261 
262  this->m_NumberOfPixelsCounted++;
263 
264  // Get the gradient by NearestNeighboorInterpolation:
265  // which is equivalent to round up the point components.
266  typedef typename OutputPointType::CoordRepType CoordRepType;
268  MovingImageContinuousIndexType;
269 
270  MovingImageContinuousIndexType tempIndex;
271  this->m_MovingImage->TransformPhysicalPointToContinuousIndex( transformedPoint, tempIndex );
272 
273  typename MovingImageType::IndexType mappedIndex;
274  mappedIndex.CopyWithRound( tempIndex );
275 
276  const GradientPixelType gradient = this->m_GradientImage->GetPixel( mappedIndex );
277 
278  for(unsigned int par=0; par<ParametersDimension; par++)
279  {
280  for(unsigned int dim=0; dim<ImageDimension; dim++)
281  {
282  sum2[par] += jacobian( dim, par )*gradient[dim];
283  if ( fixedValue == m_ForegroundValue )
284  {
285  sum1[par] += 2.0*jacobian( dim, par )*gradient[dim];
286  }
287  }
288  }
289  }
290  ++ti;
291  }
292 
293  if( !this->m_NumberOfPixelsCounted )
294  {
295  itkExceptionMacro(<<"All the points mapped to outside of the moving image");
296  }
297  else
298  {
299  double areaSum = double(fixedArea)+double(movingArea);
300  for(unsigned int par=0; par<ParametersDimension; par++)
301  {
302  derivative[par] = -(areaSum*sum1[par]-2.0*intersection*sum2[par])/(areaSum*areaSum);
303  }
304  }
305 }
306 
307 
308 /*
309  * Compute the image gradient and assign to m_GradientImage.
310  */
311 template <class TFixedImage, class TMovingImage>
312 void
315 {
316  const unsigned int dim = MovingImageType::ImageDimension;
317 
318  typename GradientImageType::Pointer tempGradientImage = GradientImageType::New();
319  tempGradientImage->SetRegions( this->m_MovingImage->GetBufferedRegion().GetSize() );
320  tempGradientImage->Allocate();
321  tempGradientImage->Update();
322 
323  typedef ImageRegionIteratorWithIndex< GradientImageType > GradientIteratorType;
324  typedef ImageRegionConstIteratorWithIndex< MovingImageType > MovingIteratorType;
325 
326  GradientIteratorType git( tempGradientImage, tempGradientImage->GetBufferedRegion() );
327  MovingIteratorType mit( this->m_MovingImage, this->m_MovingImage->GetBufferedRegion() );
328 
329  git.GoToBegin();
330  mit.GoToBegin();
331 
332  typename MovingImageType::IndexType minusIndex;
333  typename MovingImageType::IndexType plusIndex;
334  typename MovingImageType::IndexType currIndex;
335  typename GradientImageType::PixelType tempGradPixel;
336  typename MovingImageType::SizeType movingSize = this->m_MovingImage->GetBufferedRegion().GetSize();
337  while(!mit.IsAtEnd())
338  {
339  currIndex = mit.GetIndex();
340  minusIndex = mit.GetIndex();
341  plusIndex = mit.GetIndex();
342  for ( unsigned int i=0; i<dim; i++ )
343  {
344  if ((currIndex[i] == 0) ||
345  (static_cast<typename MovingImageType::SizeType::SizeValueType>(currIndex[i]) == (movingSize[i]-1)))
346  {
347  tempGradPixel[i] = 0;
348  }
349  else
350  {
351  minusIndex[i] = currIndex[i]-1;
352  plusIndex[i] = currIndex[i]+1;
353  double minusVal = double(this->m_MovingImage->GetPixel(minusIndex));
354  double plusVal = double(this->m_MovingImage->GetPixel(plusIndex));
355  if ((minusVal != m_ForegroundValue)&&(plusVal == m_ForegroundValue))
356  {
357  tempGradPixel[i] = 1;
358  }
359  else if ((minusVal == m_ForegroundValue)&&(plusVal != m_ForegroundValue))
360  {
361  tempGradPixel[i] = -1;
362  }
363  else
364  {
365  tempGradPixel[i] = 0;
366  }
367  }
368  minusIndex = currIndex;
369  plusIndex = currIndex;
370  }
371  git.Set( tempGradPixel );
372  ++git;
373  ++mit;
374  }
375 
376  this->m_GradientImage = tempGradientImage;
377 }
378 
382 template <class TFixedImage, class TMovingImage>
383 void
386  MeasureType & Value, DerivativeType & Derivative) const
387 {
388  Value = this->GetValue( parameters );
389  this->GetDerivative( parameters, Derivative );
390 }
391 
392 
396 template <class TFixedImage, class TMovingImage>
397 void
399 ::PrintSelf(std::ostream& os, Indent indent) const
400 {
401  Superclass::PrintSelf( os, indent );
402  os << indent << "Complement: " << (m_Complement ? "On" : "Off") << std::endl;
403  os << indent << "ForegroundValue: " << m_ForegroundValue << std::endl;
404 }
405 
406 } // end namespace itk
407 
408 
409 #endif

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