KWStyle - itkLevelSetFunction.txx
 
Matrix View
Description

1 /*=========================================================================
2
3 Program:   Insight Segmentation & Registration Toolkit
4 Module:    $RCSfile: itkLevelSetFunction.txx.html,v $
5 Language:  C++
6 Date:      $Date: 2006/01/17 19:15:40 $
7 Version:   $Revision: 1.4 $
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 DEF #ifndef __itkLevelSetFunction_txx_
18 DEF #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
27 LEN LevelSetFunction<TImageType>::ComputeCurvatureTerm(const NeighborhoodType &neighborhood,
28 LEN                                                    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>
53 typename LevelSetFunction< TImageType >::ScalarValueType
54 LevelSetFunction< TImageType >
55 ::ComputeMinimalCurvature(
56   const NeighborhoodType &itkNotUsed(neighborhood),
57 IND **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 SEM       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 SEM       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>
125 typename LevelSetFunction< TImageType >::ScalarValueType
126 LevelSetFunction< TImageType >
127 ::Compute3DMinimalCurvature(const NeighborhoodType &neighborhood,
128                             const FloatOffsetType& offset, GlobalDataStruct *gd)
129 {
130 LEN   ScalarValueType mean_curve = this->ComputeMeanCurvature(neighborhood, offset, gd);
131   
132   int i0 = 0, i1 = 1, i2 = 2;
133   ScalarValueType gauss_curve =
134 IND ****(2*(gd->m_dx[i0]*gd->m_dx[i1]*(gd->m_dxy[i2][i0]
135 LEN                                    *gd->m_dxy[i1][i2]-gd->m_dxy[i0][i1]*gd->m_dxy[i2][i2]) +
136 IND ********gd->m_dx[i1]*gd->m_dx[i2]*(gd->m_dxy[i2][i0]
137 LEN                                    *gd->m_dxy[i0][i1]-gd->m_dxy[i1][i2]*gd->m_dxy[i0][i0]) +
138 IND ********gd->m_dx[i0]*gd->m_dx[i2]*(gd->m_dxy[i1][i2]
139 LEN                                    *gd->m_dxy[i0][i1]-gd->m_dxy[i2][i0]*gd->m_dxy[i1][i1])) +
140 IND *****gd->m_dx[i0]*gd->m_dx[i0]*(gd->m_dxy[i1][i1]
141 LEN                                 *gd->m_dxy[i2][i2]-gd->m_dxy[i1][i2]*gd->m_dxy[i1][i2]) +
142 IND *****gd->m_dx[i1]*gd->m_dx[i1]*(gd->m_dxy[i0][i0]
143 LEN                                 *gd->m_dxy[i2][i2]-gd->m_dxy[i2][i0]*gd->m_dxy[i2][i0]) +
144 IND *****gd->m_dx[i2]*gd->m_dx[i2]*(gd->m_dxy[i1][i1]
145 LEN                                 *gd->m_dxy[i0][i0]-gd->m_dxy[i0][i1]*gd->m_dxy[i0][i1]))/
146 LEN,IND ****(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 = sqrt(discriminant);
154   return  (mean_curve - discriminant);
155 }
156
157
158 template <class TImageType>
159 typename LevelSetFunction<TImageType>::ScalarValueType
160 LevelSetFunction<TImageType>::ComputeMeanCurvature(
161   const NeighborhoodType &itkNotUsed(neighborhood),
162 IND **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>
185 typename LevelSetFunction<TImageType>::VectorType
186 LevelSetFunction<TImageType>::InitializeZeroVectorConstant()
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>
198 typename LevelSetFunction<TImageType>::VectorType
199 LevelSetFunction<TImageType>::m_ZeroVectorConstant =
200 LevelSetFunction<TImageType>::InitializeZeroVectorConstant();
201
202 template <class TImageType>
203 void
204 LevelSetFunction<TImageType>::
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 LEN   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 >
225 typename LevelSetFunction< TImageType >::TimeStepType
226 LevelSetFunction<TImageType>
227 ::ComputeGlobalTimeStep(void *GlobalData) const
228 {
229   TimeStepType dt;
230
231   GlobalDataStruct *d = (GlobalDataStruct *)GlobalData;
232
233   d->m_MaxAdvectionChange += d->m_MaxPropagationChange;
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 IND ************************(    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   // reset the values  
260   d->m_MaxAdvectionChange   = NumericTraits<ScalarValueType>::Zero;
261   d->m_MaxPropagationChange = NumericTraits<ScalarValueType>::Zero;
262   d->m_MaxCurvatureChange   = NumericTraits<ScalarValueType>::Zero;
263   
264   return dt;
265 }
266  
267 template< class TImageType >
268 void
269 LevelSetFunction< TImageType>
270 ::Initialize(const RadiusType &r)
271 {
272   this->SetRadius(r);
273   
274   // Dummy neighborhood.
275   NeighborhoodType it;
276   it.SetRadius( r );
277   
278   // Find the center index of the neighborhood.
279   m_Center =  it.Size() / 2;
280
281   // Get the stride length for each axis.
282   for(unsigned int i = 0; i < ImageDimension; i++)
283     {  m_xStride[i] = it.GetStride(i); }
284 }
285   
286 template< class TImageType >
287 typename LevelSetFunction< TImageType >::PixelType
288 LevelSetFunction< TImageType >
289 ::ComputeUpdate(const NeighborhoodType &it, void *globalData,
290                 const FloatOffsetType& offset)
291 {
292   unsigned int i, j;  
293   const ScalarValueType ZERO = NumericTraits<ScalarValueType>::Zero;
294   const ScalarValueType center_value  = it.GetCenterPixel();
295
296   ScalarValueType laplacian, x_energy, laplacian_term, propagation_term,
297 IND ****curvature_term, advection_term, propagation_gradient;
298   VectorType advection_field;
299
300   // Global data structure
301   GlobalDataStruct *gd = (GlobalDataStruct *)globalData;
302
303   // Compute the Hessian matrix and various other derivatives.  Some of these
304   // derivatives may be used by overloaded virtual functions.
305   gd->m_GradMagSqr = 1.0e-6;
306 SEM   for( i = 0 ; i < ImageDimension; i++)
307     {
308     const unsigned int positionA = 
309       static_cast<unsigned int>( m_Center + m_xStride[i]);    
310     const unsigned int positionB = 
311 IND ******static_cast<unsigned int>( m_Center - m_xStride[i]);    
312
313     gd->m_dx[i] = 0.5 * (it.GetPixel( positionA ) - 
314 IND *********************it.GetPixel( positionB )    );
315       
316     gd->m_dxy[i][i] = it.GetPixel( positionA )
317 IND ******+ it.GetPixel( positionB ) - 2.0 * center_value;
318     
319     gd->m_dx_forward[i]  = it.GetPixel( positionA ) - center_value;
320     gd->m_dx_backward[i] = center_value - it.GetPixel( positionB );
321     gd->m_GradMagSqr += gd->m_dx[i] * gd->m_dx[i];
322
323     for( j = i+1; j < ImageDimension; j++ )
324       {
325       const unsigned int positionAa = static_cast<unsigned int>( 
326         m_Center - m_xStride[i] - m_xStride[j] );
327       const unsigned int positionBa = static_cast<unsigned int>( 
328         m_Center - m_xStride[i] + m_xStride[j] );
329       const unsigned int positionCa = static_cast<unsigned int>( 
330         m_Center + m_xStride[i] - m_xStride[j] );
331       const unsigned int positionDa = static_cast<unsigned int>( 
332         m_Center + m_xStride[i] + m_xStride[j] );
333
334       gd->m_dxy[i][j] = gd->m_dxy[j][i] = 0.25 *( it.GetPixel( positionAa )
335 IND ******************************************- it.GetPixel( positionBa )
336 IND ******************************************- it.GetPixel( positionCa )
337 IND ******************************************+ it.GetPixel( positionDa )
338 IND ********);
339       }
340     }
341
342   if ( m_CurvatureWeight != ZERO )
343     {
344 LEN     curvature_term = this->ComputeCurvatureTerm(it, offset, gd) * m_CurvatureWeight
345 IND ******* this->CurvatureSpeed(it, offset);
346
347     gd->m_MaxCurvatureChange = vnl_math_max(gd->m_MaxCurvatureChange,
348                    vnl_math_abs(curvature_term));
349     }
350   else
351     {
352     curvature_term = ZERO;
353     }
354
355   // Calculate the advection term.
356   //  $\alpha \stackrel{\rightharpoonup}{F}(\mathbf{x})\cdot\nabla\phi $
357   //
358   // Here we can use a simple upwinding scheme since we know the
359   // sign of each directional component of the advective force.
360   //
361   if (m_AdvectionWeight != ZERO)
362     {
363     
364     advection_field = this->AdvectionField(it, offset, gd);
365     advection_term = ZERO;
366     
367     for(i = 0; i < ImageDimension; i++)
368       {
369       
370       x_energy = m_AdvectionWeight * advection_field[i];
371       
372       if (x_energy > ZERO)
373         {
374         advection_term += advection_field[i] * gd->m_dx_backward[i];
375         }
376       else
377         {
378         advection_term += advection_field[i] * gd->m_dx_forward[i];
379         }
380         
381       gd->m_MaxAdvectionChange
382 IND ********= vnl_math_max(gd->m_MaxAdvectionChange, vnl_math_abs(x_energy)); 
383       }
384     advection_term *= m_AdvectionWeight;
385     
386     }
387   else
388     {
389     advection_term = ZERO;
390     }
391
392   if (m_PropagationWeight != ZERO)
393     {
394     // Get the propagation speed
395 LEN     propagation_term = m_PropagationWeight * this->PropagationSpeed(it, offset, gd);
396       
397     //
398     // Construct upwind gradient values for use in the propagation speed term:
399     //  $\beta G(\mathbf{x})\mid\nabla\phi\mid$
400     //
401     // The following scheme for ``upwinding'' in the normal direction is taken
402     // from Sethian, Ch. 6 as referenced above.
403     //
404     propagation_gradient = ZERO;
405     
406     if ( propagation_term > ZERO )
407       {
408       for(i = 0; i< ImageDimension; i++)
409         {
410 LEN         propagation_gradient += vnl_math_sqr( vnl_math_max(gd->m_dx_backward[i], ZERO) )
411 IND **********+ vnl_math_sqr( vnl_math_min(gd->m_dx_forward[i],  ZERO) );
412         }
413       }
414     else
415       {
416       for(i = 0; i< ImageDimension; i++)
417         {
418 LEN         propagation_gradient += vnl_math_sqr( vnl_math_min(gd->m_dx_backward[i], ZERO) )
419 IND **********+ vnl_math_sqr( vnl_math_max(gd->m_dx_forward[i],  ZERO) );
420         }        
421       }
422     
423     // Collect energy change from propagation term.  This will be used in
424     // calculating the maximum time step that can be taken for this iteration.
425     gd->m_MaxPropagationChange =
426 IND ******vnl_math_max(gd->m_MaxPropagationChange,
427                    vnl_math_abs(propagation_term));
428     
429     propagation_term *= vcl_sqrt( propagation_gradient );
430     }
431   else propagation_term = ZERO;
432
433   if(m_LaplacianSmoothingWeight != ZERO)
434     {
435     laplacian = ZERO;
436     
437     // Compute the laplacian using the existing second derivative values
438     for(i = 0;i < ImageDimension; i++)
439       {
440       laplacian += gd->m_dxy[i][i];
441       }
442
443     // Scale the laplacian by its speed and weight
444     laplacian_term = 
445 LEN,IND ******laplacian * m_LaplacianSmoothingWeight * LaplacianSmoothingSpeed(it,offset, gd);
446     }
447   else 
448 IND ****laplacian_term = ZERO;
449
450   // Return the combination of all the terms.
451   return ( PixelType ) ( curvature_term - propagation_term 
452                          - advection_term - laplacian_term );
453
454
455 // end namespace itk
456
457 #endif
458

Generated by KWStyle 1.0b on Tuesday January,17 at 02:14:18PM
© Kitware Inc.