Orfeo Toolbox  3.16
itkRegionBasedLevelSetFunction.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkRegionBasedLevelSetFunction.txx,v $
5  Language: C++
6  Date: $Date: 2010-02-24 19:27:48 $
7  Version: $Revision: 1.29 $
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 
18 #ifndef __itkRegionBasedLevelSetFunction_txx
19 #define __itkRegionBasedLevelSetFunction_txx
20 
23 
24 namespace itk
25 {
26 template < class TInput,
27  class TFeature,
28  class TSharedData >
29 double
30 RegionBasedLevelSetFunction< TInput, TFeature, TSharedData >
31 ::m_WaveDT = 1.0/(2.0 * ImageDimension);
32 
33 template < class TInput,
34  class TFeature,
35  class TSharedData >
36 double
37 RegionBasedLevelSetFunction< TInput, TFeature, TSharedData >
38 ::m_DT = 1.0/(2.0 * ImageDimension);
39 
40 template < class TInput,
41  class TFeature,
42  class TSharedData >
43 RegionBasedLevelSetFunction< TInput,
44  TFeature,
45  TSharedData >
47 {
48  m_Lambda1 = NumericTraits<ScalarValueType>::One;
49  m_Lambda2 = NumericTraits<ScalarValueType>::One;
50 
51  m_OverlapPenaltyWeight = NumericTraits<ScalarValueType>::Zero;
52  m_AreaWeight = NumericTraits<ScalarValueType>::Zero;
53  m_VolumeMatchingWeight = NumericTraits<ScalarValueType>::Zero;
54  m_ReinitializationSmoothingWeight = NumericTraits<ScalarValueType>::Zero;
55  m_CurvatureWeight = m_AdvectionWeight = NumericTraits<ScalarValueType>::Zero;
56  m_Volume = NumericTraits<ScalarValueType>::Zero;
57 
58  m_FunctionId = 0;
59 
60  m_SharedData = 0;
61  m_InitialImage = 0;
62  m_FeatureImage = 0;
63  m_UpdateC = false;
64 
65  for(unsigned int i = 0; i < ImageDimension; i++)
66  {
67  m_InvSpacing[i] = 1;
68  }
69 }
70 
71 template < class TInput, class TFeature, class TSharedData >
75 {
76  VectorType ans;
77  for (unsigned int i = 0; i < ImageDimension; ++i)
78  {
79  ans[i] = NumericTraits<ScalarValueType>::Zero;
80  }
81 
82  return ans;
83 }
84 
85 template < class TInput, class TFeature, class TSharedData >
88 ::m_ZeroVectorConstant =
90 
91 /* Computes the Heaviside function and stores it in m_HeavisideFunctionOfLevelSetImage */
92 template < class TInput,
93  class TFeature,
94  class TSharedData >
97 {
98  // The phi function
99  InputImageConstPointer contourImage = this->m_InitialImage;
100  InputImagePointer hBuffer = this->m_SharedData->m_LevelSetDataPointerVector[this->m_FunctionId]->m_HeavisideFunctionOfLevelSetImage;
101 
102  // Iterator for the phi function
103  typedef ImageRegionConstIteratorWithIndex< InputImageType > ConstImageIteratorType;
104  ConstImageIteratorType constIt( contourImage, contourImage->GetRequestedRegion() );
105 
106  typedef ImageRegionIteratorWithIndex< InputImageType > ImageIteratorType;
107  ImageIteratorType It( hBuffer, hBuffer->GetRequestedRegion() );
108 
109  It.GoToBegin(),
110  constIt.GoToBegin();
111 
112  while( !constIt.IsAtEnd() )
113  {
114  // Convention is inside of level-set function is negative
115  ScalarValueType hVal = m_DomainFunction->Evaluate( - constIt.Get() );
116  It.Set( hVal );
117  ++It;
118  ++constIt;
119  }
120 }
121 
122 template < class TInput,
123  class TFeature,
124  class TSharedData >
125 void
127 ::UpdateSharedData( bool forceUpdate )
128 {
129  if ( forceUpdate )
130  {
131  // Must update all H before updating C
132  this->ComputeHImage();
133  this->m_UpdateC = false;
134  }
135  else
136  {
137  if ( !this->m_UpdateC )
138  {
139  this->ComputeParameters();
140  this->m_UpdateC = true;
141  }
142  this->UpdateSharedDataParameters();
143  }
144 
145  return;
146 }
147 
148 template < class TInput,
149  class TFeature,
150  class TSharedData >
153 ::ComputeGlobalTimeStep(void *GlobalData) const
154 {
155 /* Computing the time-step for stable curve evolution */
156 
157  TimeStepType dt = 0.0;
158 
159  GlobalDataStruct *d = (GlobalDataStruct *)GlobalData;
160 
161  if (vnl_math_abs(d->m_MaxCurvatureChange) > vnl_math::eps)
162  {
163  if (d->m_MaxAdvectionChange > vnl_math::eps)
164  {
165  dt = vnl_math_min( (m_WaveDT / d->m_MaxAdvectionChange),
166  ( this->m_DT / d->m_MaxCurvatureChange ) );
167  }
168  else
169  {
170  dt = this->m_DT / d->m_MaxCurvatureChange;
171  }
172  }
173  else
174  {
175  if (d->m_MaxAdvectionChange > vnl_math::eps)
176  {
177  //NOTE: What's the difference between this->m_WaveDT and this->m_DT?
178  dt = this->m_WaveDT / d->m_MaxAdvectionChange;
179  }
180  }
181 
182  // Reset the values
183  d->m_MaxCurvatureChange = NumericTraits<ScalarValueType>::Zero;
184  d->m_MaxGlobalChange = NumericTraits<ScalarValueType>::Zero;
185  d->m_MaxAdvectionChange = NumericTraits<ScalarValueType>::Zero;
186 
187  return dt;
188 }
189 
190 template < class TInput,
191  class TFeature, class TSharedData >
192 typename RegionBasedLevelSetFunction< TInput,
193  TFeature, TSharedData >::
194 ScalarValueType
196  TFeature, TSharedData >::
197 ComputeCurvature(
198  const NeighborhoodType &itkNotUsed(it),
199  const FloatOffsetType &itkNotUsed(offset), GlobalDataStruct *gd)
200 {
201  // Calculate the mean curvature
202  ScalarValueType curvature = NumericTraits<ScalarValueType>::Zero;
203 
204  unsigned int i, j;
205 
206  for (i = 0; i < ImageDimension; i++)
207  {
208  for(j = 0; j < ImageDimension; j++)
209  {
210  if(j != i)
211  {
212  curvature -= gd->m_dx[i] * gd->m_dx[j] * gd->m_dxy[i][j];
213  curvature += gd->m_dxy[j][j] * gd->m_dx[i] * gd->m_dx[i];
214  }
215  }
216  }
217 
218  if( gd->m_GradMag > vnl_math::eps )
219  {
220  curvature /= gd->m_GradMag * gd->m_GradMag * gd->m_GradMag;
221  }
222  else
223  {
224  curvature /= 1 + gd->m_GradMagSqr;
225  }
226 
227  return curvature;
228 }
229 
230 // Compute the Hessian matrix and various other derivatives. Some of these
231 // derivatives may be used by overloaded virtual functions.
232 template < class TInput,
233  class TFeature,
234  class TSharedData >
235 void
238 {
239  const ScalarValueType inputValue = it.GetCenterPixel();
240 
241  gd->m_GradMagSqr = 0.;
242  gd->m_GradMag = 0.;
243  unsigned int i, j;
244 
245  for (i = 0; i < ImageDimension; i++)
246  {
247  const unsigned int positionA =
248  static_cast< unsigned int >( this->m_Center + this->m_xStride[i] );
249  const unsigned int positionB =
250  static_cast< unsigned int >( this->m_Center - this->m_xStride[i] );
251 
252  gd->m_dx[i] = 0.5 * ( this->m_InvSpacing[i] ) *
253  ( it.GetPixel( positionA ) - it.GetPixel( positionB ) );
254  gd->m_dx_forward[i] = ( this->m_InvSpacing[i] ) *
255  ( it.GetPixel( positionA ) - inputValue );
256  gd->m_dx_backward[i] = ( this->m_InvSpacing[i] ) *
257  ( inputValue - it.GetPixel( positionB ) );
258 
259  gd->m_GradMagSqr += gd->m_dx[i] * gd->m_dx[i];
260 
261  gd->m_dxy[i][i] = ( this->m_InvSpacing[i] ) *
262  ( gd->m_dx_forward[i] - gd->m_dx_backward[i] );
263 
264  for (j = i+1; j < ImageDimension; j++ )
265  {
266  const unsigned int positionAa = static_cast<unsigned int>(
267  this->m_Center - this->m_xStride[i] - this->m_xStride[j] );
268  const unsigned int positionBa = static_cast<unsigned int>(
269  this->m_Center - this->m_xStride[i] + this->m_xStride[j] );
270  const unsigned int positionCa = static_cast<unsigned int>(
271  this->m_Center + this->m_xStride[i] - this->m_xStride[j] );
272  const unsigned int positionDa = static_cast<unsigned int>(
273  this->m_Center + this->m_xStride[i] + this->m_xStride[j] );
274 
275  gd->m_dxy[i][j] = gd->m_dxy[j][i] = 0.25 *
276  ( this->m_InvSpacing[i] ) * ( this->m_InvSpacing[j] ) *
277  ( it.GetPixel( positionAa ) - it.GetPixel( positionBa ) +
278  it.GetPixel( positionDa ) - it.GetPixel( positionCa ) );
279  }
280  }
281  gd->m_GradMag = vcl_sqrt( gd->m_GradMagSqr );
282 }
283 
284 template < class TInput,
285  class TFeature,
286  class TSharedData >
289 ::ComputeUpdate( const NeighborhoodType &it, void *globalData,
290  const FloatOffsetType& offset )
291 {
292  // Access the neighborhood center pixel of phi
293  const ScalarValueType inputValue = it.GetCenterPixel();
294 
295  ScalarValueType laplacian_term = NumericTraits<ScalarValueType>::Zero;
296  ScalarValueType curvature_term = NumericTraits<ScalarValueType>::Zero;
297  ScalarValueType curvature = NumericTraits<ScalarValueType>::Zero;
298  ScalarValueType globalTerm = NumericTraits<ScalarValueType>::Zero;
299  VectorType advection_field;
300  ScalarValueType x_energy, advection_term = NumericTraits<ScalarValueType>::Zero;
301 
302  // Access the global data structure
303  GlobalDataStruct *gd = (GlobalDataStruct *)globalData;
304 
305  ComputeHessian( it, gd );
306 
307  ScalarValueType dh = m_DomainFunction->EvaluateDerivative( - inputValue );
308 
309  // Computing the curvature term
310  // Used to regularized using the length of contour
311  if ( ( dh != 0. ) &&
312  ( this->m_CurvatureWeight != NumericTraits< ScalarValueType >::Zero ) )
313  {
314  curvature = this->ComputeCurvature( it, offset, gd );
315  curvature_term = this->m_CurvatureWeight * curvature *
316  this->CurvatureSpeed(it,offset, gd) * dh;
317 
319  vnl_math_max( gd->m_MaxCurvatureChange, vnl_math_abs( curvature_term ) );
320  }
321 
322  // Computing the laplacian term
323  // Used in maintaining squared distance function
324  if( this->m_ReinitializationSmoothingWeight != NumericTraits<ScalarValueType>::Zero )
325  {
326  laplacian_term = this->ComputeLaplacian( gd ) - curvature;
327 
328  laplacian_term *= this->m_ReinitializationSmoothingWeight *
329  this->LaplacianSmoothingSpeed(it,offset, gd);
330  }
331 
332  if ( ( dh != 0. ) && ( m_AdvectionWeight != NumericTraits<ScalarValueType>::Zero ) )
333  {
334  advection_field = this->AdvectionField(it, offset, gd);
335 
336  for( unsigned int i = 0; i < ImageDimension; i++ )
337  {
338  x_energy = m_AdvectionWeight * advection_field[i];
339 
340  // TODO: Is this condition right ?
341  if (x_energy > NumericTraits<ScalarValueType>::Zero )
342  {
343  advection_term += advection_field[i] * gd->m_dx_backward[i];
344  }
345  else
346  {
347  advection_term += advection_field[i] * gd->m_dx_forward[i];
348  }
349 
351  = vnl_math_max(gd->m_MaxAdvectionChange, vnl_math_abs(x_energy));
352  }
353  advection_term *= m_AdvectionWeight*dh;
354  }
355 
356  /* Compute the globalTerm - rms difference of image with c_0 or c_1*/
357  if ( dh != 0. )
358  {
359  globalTerm = dh * this->ComputeGlobalTerm( inputValue, it.GetIndex() );
360  }
361 
362  /* Final update value is the local terms of curvature lengths and laplacian
363  squared distances - global terms of rms differences of image and piecewise
364  constant regions*/
365  PixelType updateVal =
366  static_cast< PixelType >( curvature_term + laplacian_term + globalTerm + advection_term );
367 
368  /* If MaxGlobalChange recorded is lower than the current globalTerm */
369  if( vnl_math_abs( gd->m_MaxGlobalChange) < vnl_math_abs( globalTerm ) )
370  {
371  gd->m_MaxGlobalChange = globalTerm;
372  }
373 
374  return updateVal;
375 }
376 
377 
378 template < class TInput, class TFeature, class TSharedData >
380 ::ScalarValueType
383 {
384  ScalarValueType laplacian = 0.;
385 
386  // Compute the laplacian using the existing second derivative values
387  for( unsigned int i = 0; i < ImageDimension; i++ )
388  {
389  laplacian += gd->m_dxy[i][i];
390  }
391 
392  return laplacian;
393 }
394 
395 template < class TInput, class TFeature, class TSharedData >
397 ::ScalarValueType
400 {
401  return 2 * ( this->m_SharedData->m_LevelSetDataPointerVector[this->m_FunctionId]->m_WeightedNumberOfPixelsInsideLevelSet - this->m_Volume );
402 }
403 
404 /* Computes the fidelity term (eg: (intensity - mean)2 ).
405 Most of the code is concerned with using the appropriate combination
406 of Heaviside and dirac delta for each part of the fidelity term.
407 - the final dH is the dirac delta term corresponding to the current
408 level set we are updating. */
409 template < class TInput, class TFeature, class TSharedData >
411 ::ScalarValueType
414 const ScalarValueType& itkNotUsed( inputPixel ),
415 const InputIndexType& inputIndex )
416 {
417  // computes if it belongs to background
418  ScalarValueType product = 1;
419 
420  // Assuming only 1 level set function to be present
421  FeatureIndexType featIndex = static_cast< FeatureIndexType >( inputIndex );
422 
423  const FeaturePixelType featureVal =
424  this->m_FeatureImage->GetPixel ( inputIndex );
425 
426  ScalarValueType overlapTerm = 0.;
427 
428  // This conditional statement computes the amount of overlap s
429  // and the presence of background pr
430  if( this->m_SharedData->m_FunctionCount > 1 )
431  {
432  featIndex = this->m_SharedData->m_LevelSetDataPointerVector[this->m_FunctionId]->GetFeatureIndex( inputIndex );
433  overlapTerm = this->m_OverlapPenaltyWeight *
434  ComputeOverlapParameters( featIndex, product );
435  }
436 
437  ScalarValueType inTerm = this->m_Lambda1 * this->ComputeInternalTerm( featureVal, featIndex );
438  ScalarValueType outTerm = this->m_Lambda2 * product * this->ComputeExternalTerm( featureVal, featIndex );
439 
440  ScalarValueType regularizationTerm = this->m_VolumeMatchingWeight *
441  ComputeVolumeRegularizationTerm() - this->m_AreaWeight;
442 
443  ScalarValueType globalTerm = + inTerm - outTerm + overlapTerm + regularizationTerm;
444 
445  return globalTerm;
446 }
447 
448 } // end namespace
449 
450 #endif

Generated at Sun Feb 3 2013 00:02:47 for Orfeo Toolbox with doxygen 1.8.1.1