Orfeo Toolbox  3.16
itkMinMaxCurvatureFlowFunction.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkMinMaxCurvatureFlowFunction.txx,v $
5  Language: C++
6  Date: $Date: 2009-10-27 16:06:41 $
7  Version: $Revision: 1.30 $
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 __itkMinMaxCurvatureFlowFunction_txx
18 #define __itkMinMaxCurvatureFlowFunction_txx
20 
21 #include "vnl/vnl_math.h"
23 
24 namespace itk {
25 
29 template<class TImage>
32 {
33  m_StencilRadius = 0;
34  this->SetStencilRadius( 2 );
35 
36 }
37 
38 
42 template<class TImage>
43 void
46 {
47  if ( m_StencilRadius == value ) { return; }
48 
49  m_StencilRadius = (value > 1) ? value: 1;
50  RadiusType radius;
51  unsigned int j;
52 
53  for ( j = 0; j < ImageDimension; j++ )
54  {
55  radius[j] = m_StencilRadius;
56  }
57 
58  this->SetRadius( radius );
59  this->InitializeStencilOperator();
60 
61 }
62 
63 
67 template<class TImage>
68 void
71 {
72  // Fill stencil operator with a sphere of radius m_StencilRadius.
73 
74  m_StencilOperator.SetRadius( m_StencilRadius );
75 
76  RadiusValueType counter[ImageDimension];
77  unsigned int j;
78  RadiusValueType span = 2 * m_StencilRadius + 1;
79  RadiusValueType sqrRadius = m_StencilRadius * m_StencilRadius;
80  for ( j = 0; j < ImageDimension; j++ )
81  {
82  counter[j] = 0;
83  }
84 
85  typedef typename StencilOperatorType::Iterator Iterator;
86  Iterator opIter;
87  Iterator opEnd = m_StencilOperator.End();
88 
89  unsigned long numPixelsInSphere = 0;
90 
91  for ( opIter = m_StencilOperator.Begin(); opIter < opEnd; ++opIter )
92  {
93 
95 
96  RadiusValueType length = 0;
97  for ( j = 0; j < ImageDimension; j++ )
98  {
99  length += static_cast<RadiusValueType>(
100  vnl_math_sqr( static_cast<signed long>(counter[j]) -
101  static_cast<signed long>(m_StencilRadius) ) );
102  }
103  if ( length <= sqrRadius )
104  {
105  *opIter = 1;
106  numPixelsInSphere++;
107  }
108 
109  bool carryOver = true;
110  for ( j = 0; carryOver && j < ImageDimension; j++ )
111  {
112  counter[j] += 1;
113  carryOver = false;
114  if ( counter[j] == span )
115  {
116  counter[j] = 0;
117  carryOver = true;
118  }
119  }
120 
121  }
122 
123  // normalize the operator so that it sums to one
124  for ( opIter = m_StencilOperator.Begin(); opIter < opEnd; ++opIter )
125  {
126  *opIter = static_cast<PixelType>( (double) *opIter /
127  (double) numPixelsInSphere );
128  }
129 
130 }
131 
136 template<class TImage>
140  const NeighborhoodType &it) const
141 {
143 
144  // Compute gradient
145  PixelType gradient[ImageDimension];
146  PixelType gradMagnitude;
147  unsigned long stride;
148  unsigned long center;
149  unsigned int j;
150 
151  center = it.Size()/2;
152 
153  gradMagnitude = NumericTraits<PixelType>::Zero;
154  for ( j = 0; j < ImageDimension; j++ )
155  {
156  stride = it.GetStride( (unsigned long) j );
157  gradient[j] = 0.5 * ( it.GetPixel( center + stride ) -
158  it.GetPixel( center - stride ) );
159  gradient[j] *= this->m_ScaleCoefficients[j];
160 
161  gradMagnitude += vnl_math_sqr( (double)gradient[j] );
162  }
163 
164  if ( gradMagnitude == 0.0 ) { return threshold; }
165 
166  gradMagnitude = vcl_sqrt( (double)gradMagnitude );
167 
168  // Search for all position in the neighborhood perpendicular to
169  // the gradient and at a distance of StencilRadius from center.
170 
171  RadiusValueType counter[ImageDimension];
172  RadiusValueType span = 2 * m_StencilRadius + 1;
173  for ( j = 0; j < ImageDimension; j++ )
174  {
175  counter[j] = 0;
176  }
177 
178  typedef typename NeighborhoodType::ConstIterator Iterator;
179  Iterator neighIter;
180  Iterator neighEnd = it.End();
181 
182  unsigned long i = 0;
183  unsigned long numPixels = 0;
184 
185  for ( neighIter = it.Begin(); neighIter < neighEnd; ++neighIter, ++i )
186  {
187 
189  PixelType vectorMagnitude = NumericTraits<PixelType>::Zero;
190 
191  for ( j = 0; j < ImageDimension; j++ )
192  {
193  signed long diff = static_cast<signed long>( counter[j] ) -
194  static_cast<signed long>( m_StencilRadius );
195 
196  dotProduct += static_cast<PixelType>( diff ) * gradient[j];
197  vectorMagnitude += static_cast<PixelType>( vnl_math_sqr( diff ) );
198 
199  }
200 
201  vectorMagnitude = vcl_sqrt( (double)vectorMagnitude );
202 
203  if ( vectorMagnitude != 0.0 )
204  {
205  dotProduct /= gradMagnitude * vectorMagnitude;
206  }
207 
208  if ( vectorMagnitude >= m_StencilRadius && vnl_math_abs(dotProduct) < 0.262 )
209  {
210  threshold += it.GetPixel( i );
211  numPixels++;
212  }
213 
214  bool carryOver = true;
215  for ( j = 0; carryOver && j < ImageDimension; j++ )
216  {
217  counter[j] += 1;
218  carryOver = false;
219  if ( counter[j] == span )
220  {
221  counter[j] = 0;
222  carryOver = true;
223  }
224  }
225 
226  }
227 
228  if ( numPixels > 0 )
229  {
230  threshold /= static_cast<PixelType>( numPixels );
231  }
232 
233  return threshold;
234 
235 }
236 
237 
242 template<class TImage>
246 {
247  const signed int imageDimension = 2;
248 
249  if ( m_StencilRadius == 0 ) { return it.GetCenterPixel(); }
250 
252 
253  // Compute gradient
254  PixelType gradient[imageDimension];
255  PixelType gradMagnitude;
256  unsigned long stride;
257  unsigned long center;
258  unsigned long position[imageDimension];
259  int j, k;
260 
261  center = it.Size()/2;
262 
263  gradient[0] = 0.5 * ( it.GetPixel( center + 1 ) -
264  it.GetPixel( center - 1) );
265  k = 0;
266  gradient[k] *= this->m_ScaleCoefficients[k];
267  gradMagnitude = vnl_math_sqr( (double)gradient[k] );
268  k++;
269 
270  stride = it.GetStride( 1 );
271  gradient[k] = 0.5 * ( it.GetPixel( center + stride ) -
272  it.GetPixel( center - stride ) );
273  gradient[k] *= this->m_ScaleCoefficients[k];
274  gradMagnitude += vnl_math_sqr( (double)gradient[k] );
275 
276  if ( gradMagnitude == 0.0 ) { return threshold; }
277 
278  gradMagnitude = vcl_sqrt( (double)gradMagnitude ) /
279  static_cast<PixelType>( m_StencilRadius );
280 
281  for ( j = 0; j < imageDimension; j++ )
282  {
283  gradient[j] /= gradMagnitude;
284  }
285 
286 
287  // Compute first perpendicular point
288  position[0] = Math::Round<unsigned long>( (double)(m_StencilRadius - gradient[1]) );
289  position[1] = Math::Round<unsigned long>( (double)(m_StencilRadius + gradient[0]) );
290 
291 
292  threshold = it.GetPixel( position[0] + stride * position[1] );
293 
294  // Compute second perpendicular point
295  position[0] = Math::Round<unsigned long>( (double)(m_StencilRadius + gradient[1]) );
296  position[1] = Math::Round<unsigned long>( (double)(m_StencilRadius - gradient[0]) );
297 
298 
299  threshold += it.GetPixel( position[0] + stride * position[1] );
300  threshold *= 0.5;
301 
302  return threshold;
303 
304 }
305 
306 
307 /*
308  * Compute the threshold by averaging the image intensity in
309  * the direction perpendicular to the image gradient.
310  */
311 template<class TImage>
315 {
316 
317  const signed int imageDimension = 3;
318 
319  if ( m_StencilRadius == 0 ) { return it.GetCenterPixel(); }
320 
322 
323  // Compute gradient
324  PixelType gradient[imageDimension];
325  PixelType gradMagnitude;
326  unsigned long strideY, strideZ;
327  unsigned long center;
328  unsigned long position[imageDimension];
329  int j, k;
330 
331  center = it.Size()/2;
332  strideY = it.GetStride( 1 );
333  strideZ = it.GetStride( 2 );
334 
335  gradient[0] = 0.5 * ( it.GetPixel( center + 1 ) -
336  it.GetPixel( center - 1) );
337  k = 0;
338  gradient[k] *= this->m_ScaleCoefficients[k];
339  gradMagnitude = vnl_math_sqr( (double)gradient[k] );
340  k++;
341 
342  gradient[k] = 0.5 * ( it.GetPixel( center + strideY ) -
343  it.GetPixel( center - strideY ) );
344  gradient[k] *= this->m_ScaleCoefficients[k];
345  gradMagnitude += vnl_math_sqr( (double)gradient[k] );
346  k++;
347 
348  gradient[k] = 0.5 * ( it.GetPixel( center + strideZ ) -
349  it.GetPixel( center - strideZ ) );
350  gradient[k] *= this->m_ScaleCoefficients[k];
351  gradMagnitude += vnl_math_sqr( (double)gradient[k] );
352 
353  if ( gradMagnitude == 0.0 ) { return threshold; }
354 
355  gradMagnitude = vcl_sqrt( (double)gradMagnitude ) /
356  static_cast<PixelType>( m_StencilRadius );
357 
358  for ( j = 0; j < imageDimension; j++ )
359  {
360  gradient[j] /= gradMagnitude;
361  }
362 
363  double theta, phi;
364  if (gradient[2] > 1.0)
365  {
366  gradient[2] = 1.0;
367  }
368  if (gradient[2] < -1.0)
369  {
370  gradient[2] = -1.0;
371  }
372  theta = vcl_acos((double)gradient[2] );
373 
374  if ( gradient[0] == 0 )
375  {
376  phi = vnl_math::pi * 0.5;
377  }
378  else
379  {
380  phi = vcl_atan((double)gradient[1]/ (double)gradient[0] );
381  }
382 
383 
384  double cosTheta = vcl_cos(theta );
385  double sinTheta = vcl_sin(theta );
386  double cosPhi = vcl_cos(phi );
387  double sinPhi = vcl_sin(phi );
388 
389  double rSinTheta = m_StencilRadius * sinTheta;
390  double rCosThetaCosPhi = m_StencilRadius * cosTheta * cosPhi;
391  double rCosThetaSinPhi = m_StencilRadius * cosTheta * sinPhi;
392  double rSinPhi = m_StencilRadius * sinPhi;
393  double rCosPhi = m_StencilRadius * cosPhi;
394 
395  // Point 1: angle = 0;
396  position[0] = Math::Round<unsigned long>( m_StencilRadius + rCosThetaCosPhi );
397  position[1] = Math::Round<unsigned long>( m_StencilRadius + rCosThetaSinPhi );
398  position[2] = Math::Round<unsigned long>( m_StencilRadius - rSinTheta );
399 
400  threshold += it.GetPixel( position[0] +
401  strideY * position[1] + strideZ * position[2] );
402 
403  // Point 2: angle = 90;
404  position[0] = Math::Round<unsigned long>( m_StencilRadius - rSinPhi );
405  position[1] = Math::Round<unsigned long>( m_StencilRadius + rCosPhi );
406  position[2] = m_StencilRadius;
407 
408  threshold += it.GetPixel( position[0] +
409  strideY * position[1] + strideZ * position[2] );
410 
411  // Point 3: angle = 180;
412  position[0] = Math::Round<unsigned long>( m_StencilRadius - rCosThetaCosPhi );
413  position[1] = Math::Round<unsigned long>( m_StencilRadius - rCosThetaSinPhi );
414  position[2] = Math::Round<unsigned long>( m_StencilRadius + rSinTheta );
415 
416  threshold += it.GetPixel( position[0] +
417  strideY * position[1] + strideZ * position[2] );
418 
419  // Point 4: angle = 270;
420  position[0] = Math::Round<unsigned long>( m_StencilRadius + rSinPhi );
421  position[1] = Math::Round<unsigned long>( m_StencilRadius - rCosPhi );
422  position[2] = m_StencilRadius;
423 
424  threshold += it.GetPixel( position[0] +
425  strideY * position[1] + strideZ * position[2] );
426 
427  threshold *= 0.25;
428  return threshold;
429 
430 }
431 
432 
433 /*
434  * Update the solution at pixels which lies on the data boundary.
435  */
436 template<class TImage>
439 ::ComputeUpdate(const NeighborhoodType &it, void * globalData,
440  const FloatOffsetType& offset)
441 {
442  PixelType update = this->Superclass::ComputeUpdate(
443  it, globalData, offset );
444 
445  if ( update == 0.0 )
446  {
447  return update;
448  }
449 
450  PixelType threshold;
451  threshold = this->ComputeThreshold( Dispatch<ImageDimension>(), it);
452 
454  PixelType avgValue = innerProduct( it, m_StencilOperator );
455 
456  if ( avgValue < threshold )
457  {
458  return ( vnl_math_max( update, NumericTraits<PixelType>::Zero ) );
459  }
460  else
461  {
462  return ( vnl_math_min( update, NumericTraits<PixelType>::Zero ) );
463  }
464 
465 }
466 
467 
468 } // end namespace itk
469 
470 #endif

Generated at Sat May 18 2013 23:53:45 for Orfeo Toolbox with doxygen 1.8.3.1