Orfeo Toolbox  3.16
itkLevelSetFunction.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: itkLevelSetFunction.txx,v $
5 Language: C++
6 Date: $Date: 2010-03-30 15:20:02 $
7 Version: $Revision: 1.35 $
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 __itkLevelSetFunction_txx
18 #define __itkLevelSetFunction_txx
19 
20 #include "itkLevelSetFunction.h"
21 #include "vnl/algo/vnl_symmetric_eigensystem.h"
22 
23 namespace itk {
24 
25 template <class TImageType>
26 typename LevelSetFunction<TImageType>::ScalarValueType
28  const FloatOffsetType &offset, GlobalDataStruct *gd)
29 {
30  if ( m_UseMinimalCurvature == false )
31  {
32  return this->ComputeMeanCurvature(neighborhood, offset, gd);
33  }
34  else
35  {
36  if (ImageDimension == 3)
37  {
38  return this->ComputeMinimalCurvature(neighborhood, offset, gd);
39  }
40  else if (ImageDimension == 2)
41  {
42  return this->ComputeMeanCurvature(neighborhood, offset, gd);
43  }
44  else
45  {
46  return this->ComputeMinimalCurvature(neighborhood, offset, gd);
47  }
48  }
49 }
50 
51 
52 template< class TImageType>
56  const NeighborhoodType &itkNotUsed(neighborhood),
57  const FloatOffsetType& itkNotUsed(offset), GlobalDataStruct *gd)
58 {
59 
60  unsigned int i, j, n;
61  ScalarValueType gradMag = vcl_sqrt(gd->m_GradMagSqr);
62  ScalarValueType Pgrad[ImageDimension][ImageDimension];
63  ScalarValueType tmp_matrix[ImageDimension][ImageDimension];
64  const ScalarValueType ZERO = NumericTraits<ScalarValueType>::Zero;
65  vnl_matrix_fixed<ScalarValueType, ImageDimension, ImageDimension> Curve;
66  const ScalarValueType MIN_EIG = NumericTraits<ScalarValueType>::min();
67 
68  ScalarValueType mincurve;
69 
70  for (i = 0; i < ImageDimension; i++)
71  {
72  Pgrad[i][i] = 1.0 - gd->m_dx[i] * gd->m_dx[i]/gradMag;
73  for (j = i+1; j < ImageDimension; j++)
74  {
75  Pgrad[i][j]= gd->m_dx[i] * gd->m_dx[j]/gradMag;
76  Pgrad[j][i] = Pgrad[i][j];
77  }
78  }
79 
80  //Compute Pgrad * Hessian * Pgrad
81  for (i = 0; i < ImageDimension; i++)
82  {
83  for (j = i; j < ImageDimension; j++)
84  {
85  tmp_matrix[i][j]= ZERO;
86  for (n = 0; n < ImageDimension; n++)
87  {
88  tmp_matrix[i][j] += Pgrad[i][n] * gd->m_dxy[n][j];
89  }
90  tmp_matrix[j][i]=tmp_matrix[i][j];
91  }
92  }
93 
94  for (i = 0; i < ImageDimension; i++)
95  {
96  for (j = i; j < ImageDimension; j++)
97  {
98  Curve(i,j) = ZERO;
99  for (n = 0; n < ImageDimension; n++)
100  {
101  Curve(i,j) += tmp_matrix[i][n] * Pgrad[n][j];
102  }
103  Curve(j,i) = Curve(i,j);
104  }
105  }
106 
107  //Eigensystem
108  vnl_symmetric_eigensystem<ScalarValueType> eig(Curve);
109 
110  mincurve=vnl_math_abs(eig.get_eigenvalue(ImageDimension-1));
111  for (i = 0; i < ImageDimension; i++)
112  {
113  if(vnl_math_abs(eig.get_eigenvalue(i)) < mincurve &&
114  vnl_math_abs(eig.get_eigenvalue(i)) > MIN_EIG)
115  {
116  mincurve = vnl_math_abs(eig.get_eigenvalue(i));
117  }
118  }
119 
120  return ( mincurve / gradMag );
121 }
122 
123 
124 template< class TImageType>
128  const FloatOffsetType& offset, GlobalDataStruct *gd)
129 {
130  ScalarValueType mean_curve = this->ComputeMeanCurvature(neighborhood, offset, gd);
131 
132  int i0 = 0, i1 = 1, i2 = 2;
133  ScalarValueType gauss_curve =
134  (2*(gd->m_dx[i0]*gd->m_dx[i1]*(gd->m_dxy[i2][i0]
135  *gd->m_dxy[i1][i2]-gd->m_dxy[i0][i1]*gd->m_dxy[i2][i2]) +
136  gd->m_dx[i1]*gd->m_dx[i2]*(gd->m_dxy[i2][i0]
137  *gd->m_dxy[i0][i1]-gd->m_dxy[i1][i2]*gd->m_dxy[i0][i0]) +
138  gd->m_dx[i0]*gd->m_dx[i2]*(gd->m_dxy[i1][i2]
139  *gd->m_dxy[i0][i1]-gd->m_dxy[i2][i0]*gd->m_dxy[i1][i1])) +
140  gd->m_dx[i0]*gd->m_dx[i0]*(gd->m_dxy[i1][i1]
141  *gd->m_dxy[i2][i2]-gd->m_dxy[i1][i2]*gd->m_dxy[i1][i2]) +
142  gd->m_dx[i1]*gd->m_dx[i1]*(gd->m_dxy[i0][i0]
143  *gd->m_dxy[i2][i2]-gd->m_dxy[i2][i0]*gd->m_dxy[i2][i0]) +
144  gd->m_dx[i2]*gd->m_dx[i2]*(gd->m_dxy[i1][i1]
145  *gd->m_dxy[i0][i0]-gd->m_dxy[i0][i1]*gd->m_dxy[i0][i1]))/
146  (gd->m_dx[i0]*gd->m_dx[i0] + gd->m_dx[i1]*gd->m_dx[i1] + gd->m_dx[i2]*gd->m_dx[i2]);
147 
148  ScalarValueType discriminant = mean_curve * mean_curve-gauss_curve;
149  if (discriminant < 0.0)
150  {
151  discriminant = 0.0;
152  }
153  discriminant = vcl_sqrt(discriminant);
154  return (mean_curve - discriminant);
155 }
156 
157 
158 template <class TImageType>
161  const NeighborhoodType &itkNotUsed(neighborhood),
162  const FloatOffsetType &itkNotUsed(offset), GlobalDataStruct *gd)
163 {
164  // Calculate the mean curvature
165  ScalarValueType curvature_term = NumericTraits<ScalarValueType>::Zero;
166  unsigned int i, j;
167 
168 
169  for (i = 0; i < ImageDimension; i++)
170  {
171  for(j = 0; j < ImageDimension; j++)
172  {
173  if(j != i)
174  {
175  curvature_term -= gd->m_dx[i] * gd->m_dx[j] * gd->m_dxy[i][j];
176  curvature_term += gd->m_dxy[j][j] * gd->m_dx[i] * gd->m_dx[i];
177  }
178  }
179  }
180 
181  return (curvature_term / gd->m_GradMagSqr );
182 }
183 
184 template <class TImageType>
187 {
188  VectorType ans;
189  for (unsigned int i = 0; i < ImageDimension; ++i)
190  {
191  ans[i] = NumericTraits<ScalarValueType>::Zero;
192  }
193 
194  return ans;
195 }
196 
197 template <class TImageType>
201 
202 template <class TImageType>
203 void
205 PrintSelf(std::ostream& os, Indent indent) const
206 {
207  Superclass::PrintSelf(os, indent);
208  os << indent << "WaveDT: " << m_WaveDT << std::endl;
209  os << indent << "DT: " << m_DT << std::endl;
210  os << indent << "UseMinimalCurvature " << m_UseMinimalCurvature << std::endl;
211  os << indent << "EpsilonMagnitude: " << m_EpsilonMagnitude << std::endl;
212  os << indent << "AdvectionWeight: " << m_AdvectionWeight << std::endl;
213  os << indent << "PropagationWeight: " << m_PropagationWeight << std::endl;
214  os << indent << "CurvatureWeight: " << m_CurvatureWeight << std::endl;
215  os << indent << "LaplacianSmoothingWeight: " << m_LaplacianSmoothingWeight << std::endl;
216 }
217 
218 template< class TImageType >
219 double LevelSetFunction<TImageType>::m_WaveDT = 1.0/(2.0 * ImageDimension);
220 
221 template < class TImageType >
222 double LevelSetFunction<TImageType>::m_DT = 1.0/(2.0 * ImageDimension);
223 
224 template< class TImageType >
227 ::ComputeGlobalTimeStep(void *GlobalData) const
228 {
229  TimeStepType dt;
230 
231  GlobalDataStruct *d = (GlobalDataStruct *)GlobalData;
232 
234 
235  if (vnl_math_abs(d->m_MaxCurvatureChange) > 0.0)
236  {
237  if (d->m_MaxAdvectionChange > 0.0)
238  {
239  dt = vnl_math_min((m_WaveDT / d->m_MaxAdvectionChange),
240  ( m_DT / d->m_MaxCurvatureChange ));
241  }
242  else
243  {
244  dt = m_DT / d->m_MaxCurvatureChange;
245  }
246  }
247  else
248  {
249  if (d->m_MaxAdvectionChange > 0.0)
250  {
251  dt = m_WaveDT / d->m_MaxAdvectionChange;
252  }
253  else
254  {
255  dt = 0.0;
256  }
257  }
258 
259  double maxScaleCoefficient = 0.0;
260  for (unsigned int i=0; i<ImageDimension; i++)
261  {
262  maxScaleCoefficient = vnl_math_max(this->m_ScaleCoefficients[i],maxScaleCoefficient);
263  }
264  dt /= maxScaleCoefficient;
265 
266  // reset the values
267  d->m_MaxAdvectionChange = NumericTraits<ScalarValueType>::Zero;
268  d->m_MaxPropagationChange = NumericTraits<ScalarValueType>::Zero;
269  d->m_MaxCurvatureChange = NumericTraits<ScalarValueType>::Zero;
270 
271  return dt;
272 }
273 
274 template< class TImageType >
275 void
278 {
279  this->SetRadius(r);
280 
281  // Dummy neighborhood.
282  NeighborhoodType it;
283  it.SetRadius( r );
284 
285  // Find the center index of the neighborhood.
286  m_Center = it.Size() / 2;
287 
288  // Get the stride length for each axis.
289  for(unsigned int i = 0; i < ImageDimension; i++)
290  { m_xStride[i] = it.GetStride(i); }
291 }
292 
293 template< class TImageType >
296 ::ComputeUpdate(const NeighborhoodType &it, void *globalData,
297  const FloatOffsetType& offset)
298 {
299  unsigned int i, j;
300  const ScalarValueType ZERO = NumericTraits<ScalarValueType>::Zero;
301  const ScalarValueType center_value = it.GetCenterPixel();
302 
303  const NeighborhoodScalesType neighborhoodScales = this->ComputeNeighborhoodScales();
304 
305  ScalarValueType laplacian, x_energy, laplacian_term, propagation_term,
306  curvature_term, advection_term, propagation_gradient;
307  VectorType advection_field;
308 
309  // Global data structure
310  GlobalDataStruct *gd = (GlobalDataStruct *)globalData;
311 
312  // Compute the Hessian matrix and various other derivatives. Some of these
313  // derivatives may be used by overloaded virtual functions.
314  gd->m_GradMagSqr = 1.0e-6;
315  for( i = 0; i < ImageDimension; i++)
316  {
317  const unsigned int positionA =
318  static_cast<unsigned int>( m_Center + m_xStride[i]);
319  const unsigned int positionB =
320  static_cast<unsigned int>( m_Center - m_xStride[i]);
321 
322  gd->m_dx[i] = 0.5 * (it.GetPixel( positionA ) -
323  it.GetPixel( positionB ) ) * neighborhoodScales[i];
324  gd->m_dxy[i][i] = ( it.GetPixel( positionA )
325  + it.GetPixel( positionB ) - 2.0 * center_value ) *
326  vnl_math_sqr(neighborhoodScales[i]);
327 
328  gd->m_dx_forward[i] = ( it.GetPixel( positionA ) - center_value ) * neighborhoodScales[i];
329 
330  gd->m_dx_backward[i] = ( center_value - it.GetPixel( positionB ) ) * neighborhoodScales[i];
331 
332  gd->m_GradMagSqr += gd->m_dx[i] * gd->m_dx[i];
333 
334  for( j = i+1; j < ImageDimension; j++ )
335  {
336  const unsigned int positionAa = static_cast<unsigned int>(
337  m_Center - m_xStride[i] - m_xStride[j] );
338  const unsigned int positionBa = static_cast<unsigned int>(
339  m_Center - m_xStride[i] + m_xStride[j] );
340  const unsigned int positionCa = static_cast<unsigned int>(
341  m_Center + m_xStride[i] - m_xStride[j] );
342  const unsigned int positionDa = static_cast<unsigned int>(
343  m_Center + m_xStride[i] + m_xStride[j] );
344 
345  gd->m_dxy[i][j] = gd->m_dxy[j][i] = 0.25 * ( it.GetPixel( positionAa )
346  - it.GetPixel( positionBa )
347  - it.GetPixel( positionCa )
348  + it.GetPixel( positionDa ) )
349  * neighborhoodScales[i] * neighborhoodScales[j];
350  }
351  }
352 
353  if ( m_CurvatureWeight != ZERO )
354  {
355  curvature_term = this->ComputeCurvatureTerm(it, offset, gd) * m_CurvatureWeight
356  * this->CurvatureSpeed(it, offset);
357 
358  gd->m_MaxCurvatureChange = vnl_math_max(gd->m_MaxCurvatureChange,
359  vnl_math_abs(curvature_term));
360  }
361  else
362  {
363  curvature_term = ZERO;
364  }
365 
366  // Calculate the advection term.
367  // $\alpha \stackrel{\rightharpoonup}{F}(\mathbf{x})\cdot\nabla\phi $
368  //
369  // Here we can use a simple upwinding scheme since we know the
370  // sign of each directional component of the advective force.
371  //
372  if (m_AdvectionWeight != ZERO)
373  {
374 
375  advection_field = this->AdvectionField(it, offset, gd);
376  advection_term = ZERO;
377 
378  for(i = 0; i < ImageDimension; i++)
379  {
380 
381  x_energy = m_AdvectionWeight * advection_field[i];
382 
383  if (x_energy > ZERO)
384  {
385  advection_term += advection_field[i] * gd->m_dx_backward[i];
386  }
387  else
388  {
389  advection_term += advection_field[i] * gd->m_dx_forward[i];
390  }
391 
393  = vnl_math_max(gd->m_MaxAdvectionChange, vnl_math_abs(x_energy));
394  }
395  advection_term *= m_AdvectionWeight;
396 
397  }
398  else
399  {
400  advection_term = ZERO;
401  }
402 
403  if (m_PropagationWeight != ZERO)
404  {
405  // Get the propagation speed
406  propagation_term = m_PropagationWeight * this->PropagationSpeed(it, offset, gd);
407 
408  //
409  // Construct upwind gradient values for use in the propagation speed term:
410  // $\beta G(\mathbf{x})\mid\nabla\phi\mid$
411  //
412  // The following scheme for ``upwinding'' in the normal direction is taken
413  // from Sethian, Ch. 6 as referenced above.
414  //
415  propagation_gradient = ZERO;
416 
417  if ( propagation_term > ZERO )
418  {
419  for(i = 0; i< ImageDimension; i++)
420  {
421  propagation_gradient += vnl_math_sqr( vnl_math_max(gd->m_dx_backward[i], ZERO) )
422  + vnl_math_sqr( vnl_math_min(gd->m_dx_forward[i], ZERO) );
423  }
424  }
425  else
426  {
427  for(i = 0; i< ImageDimension; i++)
428  {
429  propagation_gradient += vnl_math_sqr( vnl_math_min(gd->m_dx_backward[i], ZERO) )
430  + vnl_math_sqr( vnl_math_max(gd->m_dx_forward[i], ZERO) );
431  }
432  }
433 
434  // Collect energy change from propagation term. This will be used in
435  // calculating the maximum time step that can be taken for this iteration.
437  vnl_math_max(gd->m_MaxPropagationChange,
438  vnl_math_abs(propagation_term));
439 
440  propagation_term *= vcl_sqrt( propagation_gradient );
441  }
442  else propagation_term = ZERO;
443 
444  if(m_LaplacianSmoothingWeight != ZERO)
445  {
446  laplacian = ZERO;
447 
448  // Compute the laplacian using the existing second derivative values
449  for(i = 0;i < ImageDimension; i++)
450  {
451  laplacian += gd->m_dxy[i][i];
452  }
453 
454  // Scale the laplacian by its speed and weight
455  laplacian_term =
456  laplacian * m_LaplacianSmoothingWeight * LaplacianSmoothingSpeed(it,offset, gd);
457  }
458  else
459  {
460  laplacian_term = ZERO;
461  }
462  // Return the combination of all the terms.
463  return ( PixelType ) ( curvature_term - propagation_term
464  - advection_term - laplacian_term );
465 }
466 
467 } // end namespace itk
468 
469 #endif

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