Orfeo Toolbox  3.16
itkMultiphaseSparseFiniteDifferenceImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkMultiphaseSparseFiniteDifferenceImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2010-02-24 19:27:48 $
7  Version: $Revision: 1.19 $
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 __itkMultiphaseSparseFiniteDifferenceImageFilter_txx
19 #define __itkMultiphaseSparseFiniteDifferenceImageFilter_txx
20 
22 
23 namespace itk
24 {
25 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
26 double MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >
27 ::m_ConstantGradientValue = 1.0;
28 
29 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
30 const ITK_TYPENAME MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
31 TOutputImage, TFunction, TIdCell >::ValueType
32 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >
33 ::m_ValueOne = NumericTraits<ITK_TYPENAME
34 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >
35 ::ValueType >::One;
36 
37 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
38 const ITK_TYPENAME MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
39 TOutputImage, TFunction, TIdCell >::ValueType
40 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >
41 ::m_ValueZero = NumericTraits<ITK_TYPENAME
42 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >::
43 ValueType>::Zero;
44 
45 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
46 const ITK_TYPENAME MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
47 TOutputImage, TFunction, TIdCell >::StatusType
48 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >
49 ::m_StatusNull = NumericTraits< ITK_TYPENAME
50 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >::
51 StatusType >::NonpositiveMin();
52 
53 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
54 const ITK_TYPENAME MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
55 TOutputImage, TFunction, TIdCell >::StatusType
56 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >
57 ::m_StatusChanging = -1;
58 
59 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
60 const ITK_TYPENAME MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
61 TOutputImage, TFunction, TIdCell >::StatusType
62 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >
63 ::m_StatusActiveChangingUp = -2;
64 
65 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
66 const ITK_TYPENAME MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
67 TOutputImage, TFunction, TIdCell >::StatusType
68 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >
69 ::m_StatusActiveChangingDown = -3;
70 
71 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
72 const ITK_TYPENAME MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
73 TOutputImage, TFunction, TIdCell >::StatusType
74 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage, TOutputImage, TFunction, TIdCell >
75 ::m_StatusBoundaryPixel = -4;
76 
77 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
80 {
81  this->m_CurrentFunctionIndex = 0;
82  this->m_IsoSurfaceValue = m_ValueZero;
83  this->m_BackgroundValue = NumericTraits<ValueType>::max();
84  this->m_NumberOfLayers = ImageDimension;
85  this->m_InterpolateSurfaceLocation = true;
86  this->m_BoundsCheckingActive = false;
87 }
88 
89 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
90 void
93 {
94  for( IdCellType i = 0; i < this->m_FunctionCount; i++ )
95  {
96  InputImagePointer input = this->m_LevelSet[i];
97 
98  // This is used as a temporary buffer
99  InputImagePointer tempImage = InputImageType::New();
100  tempImage->SetRegions( input->GetRequestedRegion() );
101  tempImage->CopyInformation( input );
102  tempImage->Allocate();
103 
104  // Compute Heaviside of input image
105  // Copy input to temp
106  InputRegionType region = input->GetRequestedRegion();
107  ImageRegionIterator< InputImageType > lIt( input, region );
108  ImageRegionIterator< InputImageType > tIt( tempImage, region );
109 
110  lIt.GoToBegin();
111  tIt.GoToBegin();
112 
113  while( !lIt.IsAtEnd() )
114  {
115  tIt.Set( lIt.Get() );
116  ++tIt;
117  ++lIt;
118  }
119 
120  // TODO: Can the zeroCrossingFilter have the same input and output?
121  ZeroCrossingFilterPointer zeroCrossingFilter = ZeroCrossingFilterType::New();
122  zeroCrossingFilter->SetInput( tempImage );
123  zeroCrossingFilter->SetBackgroundValue( m_ValueOne );
124  zeroCrossingFilter->SetForegroundValue( m_ValueZero );
125  zeroCrossingFilter->Update();
126 
127  // The levelset image has a 0 where the zero contour exists and + outside and - inside
128  ImageRegionIterator< InputImageType > zIt( zeroCrossingFilter->GetOutput(), region );
129 
130  lIt.GoToBegin();
131  zIt.GoToBegin();
132 
133  while( !lIt.IsAtEnd() )
134  {
135  if ( zIt.Get() == 0 )
136  {
137  lIt.Set( 0 );
138  }
139  ++zIt;
140  ++lIt;
141  }
142  }
143 }
144 
145 template < class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
146 typename MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
147 TOutputImage, TFunction, TIdCell >::TimeStepType
150 {
151  // Initialize to the maximum possible value
152  TimeStepType minTimeStep = NumericTraits< TimeStepType >::max();
153  TimeStepType timeStep;
154  InputSpacingType spacing = this->m_LevelSet[0]->GetSpacing();
155 
156  // Calculate change across all the level-set functions
157  for ( IdCellType fId = 0; fId < this->m_FunctionCount; ++fId )
158  {
159  this->m_CurrentFunctionIndex = fId;
160 
161  const FiniteDifferenceFunctionPointer df = this->m_DifferenceFunctions[fId];
162 
163  SparseDataStruct *sparsePtr = this->m_SparseData[fId];
164 
166  ValueType gradientMagnitudeSqr,
167  forward, backward, current;
168  const ValueType MIN_NORM = 1.0e-6;
169 
170  void *globalData = df->GetGlobalDataPointer();
171 
172  NeighborhoodIterator< InputImageType > outputIt ( df->GetRadius(),
173  this->m_LevelSet[fId], this->m_LevelSet[fId]->GetRequestedRegion() );
174 
175  if( m_BoundsCheckingActive == false )
176  {
178  }
179 
180  sparsePtr->m_UpdateBuffer.clear();
181  sparsePtr->m_UpdateBuffer.reserve ( sparsePtr->m_Layers[0]->Size() );
182 
183  // Calculates the update values for the active layer indices in this
184  // iteration. Iterates through the active layer index list by evaluating
185  // the update to the output image (level set image) at each
186  // index. Update values are stored in the update buffer.
187  LayerConstIterator layerIt = sparsePtr->m_Layers[0]->Begin();
188 
189  unsigned int j;
190 
191  while( layerIt != sparsePtr->m_Layers[0]->End() )
192  {
193  outputIt.SetLocation ( layerIt->m_Value );
194 
195  current = outputIt.GetCenterPixel();
196 
197  // Calculate the offset to the surface from the current of this
198  // neighborhood. This is used by some level set functions in sampling a
199  // speed, advection, or curvature term.
200  if ( this->GetInterpolateSurfaceLocation() && current != 0.0 )
201  {
202  // Surface is at the zero crossing, so distance to surface is:
203  // phi(x) / norm(grad(phi)), where phi(x) is the current of the
204  // neighborhood. The location is therefore
205  // (i,j,k) - ( phi(x)/ norm(grad(phi))) * (grad(phi(x)) / norm(grad(phi)) )
206  gradientMagnitudeSqr = 0.0;
207 
208  for ( j = 0; j < ImageDimension; ++j )
209  {
210  forward = outputIt.GetNext ( j );
211  backward = outputIt.GetPrevious ( j );
212 
213  if ( forward * backward >= 0 )
214  {
215  // Neighbors are same sign OR at least one neighbor is zero.
216  // Pick the larger magnitude derivative.
217  if ( vnl_math_abs ( forward - current ) > vnl_math_abs( current - backward ) )
218  {
219  offset[j] = ( forward - current ) / spacing[j];
220  }
221  else
222  {
223  offset[j] = ( current - backward ) / spacing[j];
224  }
225  }
226  else //Neighbors are opposite sign, pick the direction of 0 surface.
227  {
228  if ( forward * current < 0 )
229  {
230  offset[j] = ( forward - current ) / spacing[j];
231  }
232  else
233  {
234  offset[j] = ( current - backward ) / spacing[j];
235  }
236  }
237 
238  gradientMagnitudeSqr += offset[j] * offset[j];
239  }
240 
241  // Adding sqrt imagedimension "extends the reach" of the
242  // interpolation
243  // to surfaces that pass close to the current of cells. This is a
244  // heuristic fudge factor that improves interpolation and reduces
245  // "wiggling" at convergence.
246  ValueType coeff = current * vcl_sqrt( ImageDimension
247  + 0.5 ) / ( gradientMagnitudeSqr + MIN_NORM );
248 
249  for ( j = 0; j < ImageDimension; ++j )
250  {
251  offset[j] *= coeff;
252  }
253 
254  sparsePtr->m_UpdateBuffer.push_back ( df->ComputeUpdate ( outputIt, globalData, offset ) );
255  }
256  else // Don't do interpolation
257  {
258  sparsePtr->m_UpdateBuffer.push_back ( df->ComputeUpdate ( outputIt, globalData ) );
259  }
260 
261  ++layerIt;
262  }
263 
264  // Ask the finite difference function to compute the time step for
265  // this iteration. We give it the global data pointer to use, then
266  // ask it to free the global data memory.
267  timeStep = df->ComputeGlobalTimeStep ( globalData );
268  df->ReleaseGlobalDataPointer ( globalData );
269 
270  if ( timeStep < minTimeStep )
271  {
272  minTimeStep = timeStep;
273  }
274  }
275 
276  minTimeStep = 0.2; //FIXME finally assigned to a constant
277 
278  return minTimeStep;
279 }
280 
281 
282 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
283 void
284 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
285  TOutputImage,
286  TFunction, TIdCell >
287 ::ApplyUpdate ( TimeStepType dt )
288 {
289  unsigned int j, k;
290 
291  for ( IdCellType fId = 0; fId < this->m_FunctionCount; ++fId )
292  {
293  this->m_CurrentFunctionIndex = fId;
294 
295  SparseDataStruct *sparsePtr = this->m_SparseData[fId];
296  unsigned int t;
297 
298  StatusType up_to, up_search;
299  StatusType down_to, down_search;
300 
301  LayerPointerType UpList[2];
302  LayerPointerType DownList[2];
303 
304  for ( j = 0; j < 2; ++j )
305  {
306  UpList[j] = LayerType::New();
307  DownList[j] = LayerType::New();
308  }
309 
310  // Process the active layer. This step will update the values in the
311  // active layer as well as the values at indices that *will* become part
312  // of the active layer when they are promoted/demoted. Also records
313  // promotions, demotions in the UpList[0] and DownList[0] for current
314  // active layer indices (i.e. those indices which will move inside or outside
315  // the active layers).
316  this->UpdateActiveLayerValues( dt, UpList[0], DownList[0] );
317 
318  // Process the up/down lists. This is an iterative process which
319  // proceeds outwards from the active layer. Each iteration generates the
320  // list for the next iteration.
321 
322  // First process the status lists generated on the active layer.
323  this->ProcessStatusList ( UpList[0], UpList[1], 2, 1 );
324  this->ProcessStatusList ( DownList[0], DownList[1], 1, 2 );
325 
326  down_to = up_to = 0;
327  up_search = 3;
328  down_search = 4;
329  j = 1;
330  k = 0;
331  while ( down_search < static_cast<StatusType>(sparsePtr->m_Layers.size()))
332  {
333  this->ProcessStatusList(UpList[j], UpList[k], up_to, up_search );
334  this->ProcessStatusList(DownList[j], DownList[k], down_to, down_search);
335 
336  if( up_to == 0 )
337  {
338  up_to += 1;
339  }
340  else
341  {
342  up_to += 2;
343  }
344 
345  down_to += 2;
346 
347  up_search += 2;
348  down_search += 2;
349 
350  // Swap the lists so we can re-use the empty one.
351  t = j;
352  j = k;
353  k = t;
354  }
355 
356  // Process the outermost inside/outside layers in the sparse field.
357  this->ProcessStatusList(UpList[j], UpList[k], up_to, m_StatusNull );
358  this->ProcessStatusList(DownList[j], DownList[k], down_to, m_StatusNull);
359 
360  // Now we are left with the lists of indicies which must be
361  // brought into the outermost layers. Bring UpList into last inside layer
362  // and DownList into last outside layer.
363  this->ProcessOutsideList ( UpList[k], static_cast<signed char> (
364  sparsePtr->m_Layers.size() ) -2 );
365  this->ProcessOutsideList ( DownList[k], static_cast<signed char> (
366  sparsePtr->m_Layers.size() ) -1 );
367 
368  // Finally, we update all of the layer values (excluding the active layer,
369  // which has already been updated).
370  this->PropagateAllLayerValues();
371  }
372 
373  this->m_CurrentFunctionIndex = 0;
374 }
375 
376 template < class TInputImage, class TFeatureImage, class TOutputImage,
377  class TFunction, typename TIdCell >
378 void
379 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
380  TOutputImage,
381  TFunction, TIdCell >
382 ::ProcessOutsideList ( LayerType *OutsideList, StatusType ChangeToStatus )
383 {
384  SparseDataStruct *sparsePtr = this->m_SparseData[this->m_CurrentFunctionIndex];
385  LayerNodeType *node;
386 
387  // Push each index in the input list into its appropriate status layer
388  // (ChangeToStatus) and update the status image value at that index.
389  while ( ! OutsideList->Empty() )
390  {
391  sparsePtr->m_StatusImage->SetPixel ( OutsideList->Front()->m_Value, ChangeToStatus );
392  node = OutsideList->Front();
393  OutsideList->PopFront();
394  sparsePtr->m_Layers[ChangeToStatus]->PushFront ( node );
395  }
396 }
397 
398 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
399 void
400 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
401  TOutputImage,
402  TFunction, TIdCell >
403 ::ProcessStatusList ( LayerType *InputList, LayerType *OutputList,
404  StatusType ChangeToStatus, StatusType SearchForStatus )
405 {
406  SparseDataStruct *sparsePtr = this->m_SparseData[this->m_CurrentFunctionIndex];
407 
408  unsigned int i;
409  bool bounds_status;
410  LayerNodeType *node;
411  StatusType neighbor_status;
413  m_NeighborList.GetRadius(), sparsePtr->m_StatusImage,
414  this->m_LevelSet[this->m_CurrentFunctionIndex]->GetRequestedRegion() );
415 
416  if ( !m_BoundsCheckingActive )
417  {
419  }
420 
421  // Push each index in the input list into its appropriate status layer
422  // (ChangeToStatus) and update the status image value at that index.
423  // Also examine the neighbors of the index to determine which need to go
424  // onto the output list (search for SearchForStatus).
425  while ( ! InputList->Empty() )
426  {
427  statusIt.SetLocation ( InputList->Front()->m_Value );
428  statusIt.SetCenterPixel ( ChangeToStatus );
429 
430  node = InputList->Front(); // Must unlink from the input list
431  InputList->PopFront(); // before transferring to another list.
432  sparsePtr->m_Layers[ChangeToStatus]->PushFront ( node );
433 
434  // Iterate through the neighbors of this status-changed node
435  for ( i = 0; i < m_NeighborList.GetSize(); ++i )
436  {
437  neighbor_status = statusIt.GetPixel (
438  m_NeighborList.GetArrayIndex ( i ) );
439 
440  // Have we bumped up against the boundary? If so, turn on bounds
441  // checking.
442  if ( neighbor_status == m_StatusBoundaryPixel )
443  {
444  m_BoundsCheckingActive = true;
445  }
446 
447  // Find neighbors that move into the list prior to the ChangeToStatus
448  if ( neighbor_status == SearchForStatus )
449  {
450  // mark this pixel so we don't add it twice.
451  statusIt.SetPixel ( m_NeighborList.GetArrayIndex ( i ),
452  m_StatusChanging, bounds_status );
453  if ( bounds_status == true )
454  {
455  node = sparsePtr->m_LayerNodeStore->Borrow();
456  node->m_Value = statusIt.GetIndex() +
457  m_NeighborList.GetNeighborhoodOffset ( i );
458  OutputList->PushFront ( node );
459  } // else this index was out of bounds.
460  }
461  }
462  }
463 }
464 
465 
466 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
467 void
468 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
469  TOutputImage,
470  TFunction, TIdCell >
471 ::UpdateActiveLayerValues ( TimeStepType dt, LayerType *UpList, LayerType
472 *DownList )
473 {
474  SparseDataStruct *sparsePtr = this->m_SparseData[this->m_CurrentFunctionIndex];
475 
476  // This method scales the update buffer values by the time step and adds
477  // them to the active layer pixels. New values at an index which fall
478  // outside of the active layer range trigger that index to be placed on the
479  // "up" or "down" status list. The neighbors of any such index are then
480  // assigned new values if they are determined to be part of the active list
481  // for the next iteration (i.e. their values will be raised or lowered into
482  // the active range).
483 
484  // These need to take into account the spacing ??
485  const ValueType LOWER_ACTIVE_THRESHOLD = -( m_ConstantGradientValue/2.0 );
486  const ValueType UPPER_ACTIVE_THRESHOLD = m_ConstantGradientValue / 2.0;
487 
488  ValueType new_value, temp_value;
489  LayerNodeType *node, *release_node;
490  StatusType neighbor_status;
491  unsigned int i, idx;
492  bool bounds_status, flag;
493 
494  LayerIterator layerIt;
495  UpdateBufferConstIterator updateIt;
496 
498  outputIt ( m_NeighborList.GetRadius(),
499  this->m_LevelSet[this->m_CurrentFunctionIndex],
500  this->m_LevelSet[this->m_CurrentFunctionIndex]->GetRequestedRegion() );
501 
503  statusIt ( m_NeighborList.GetRadius(),
504  sparsePtr->m_StatusImage,
505  this->m_LevelSet[this->m_CurrentFunctionIndex]->GetRequestedRegion() );
506 
507  // If bounds checking is turned on
508  if ( !m_BoundsCheckingActive )
509  {
511  statusIt.NeedToUseBoundaryConditionOff();
512  }
513 
514  // Iterate over the update buffer and active layer
515  // Both are the same size
516  layerIt = sparsePtr->m_Layers[0]->Begin();
517  updateIt = sparsePtr->m_UpdateBuffer.begin();
518 
519  while( layerIt != sparsePtr->m_Layers[0]->End() )
520  {
521  outputIt.SetLocation ( layerIt->m_Value );
522  statusIt.SetLocation ( layerIt->m_Value );
523 
524  new_value = this->CalculateUpdateValue ( layerIt->m_Value,
525  dt, outputIt.GetCenterPixel(), *updateIt );
526 
527  // If this index needs to be moved to another layer, then search its
528  // neighborhood for indicies that need to be pulled up/down into the
529  // active layer. Set those new active layer values appropriately,
530  // checking first to make sure they have not been set by a more
531  // influential neighbor.
532 
533  // ...But first make sure any neighbors in the active layer are not
534  // moving to a layer in the opposite direction. This step is necessary
535  // to avoid the creation of holes in the active layer. The fix is simply
536  // to not change this value and leave the index in the active set.
537 
538  if ( new_value >= UPPER_ACTIVE_THRESHOLD )
539  {
540  // This index will move UP into a positive (outside) layer. Contour is shrinking
541  // into the negative layers.
542 
543  // First check for neighbors that belong to the active layer and moving
544  // in the opposite direction.
545  flag = false;
546  for ( i = 0; i < m_NeighborList.GetSize(); ++i )
547  {
548  if ( statusIt.GetPixel( m_NeighborList.GetArrayIndex( i ) )
549  == m_StatusActiveChangingDown )
550  {
551  flag = true;
552  break;
553  }
554  }
555 
556  if ( flag == true )
557  {
558  ++layerIt;
559  ++updateIt;
560  continue;
561  }
562 
563  // Search the neighborhood for inside indicies.
564  for ( i = 0; i < m_NeighborList.GetSize(); ++i )
565  {
566  temp_value = new_value - m_ConstantGradientValue * m_PixelDistance[i];
567  idx = m_NeighborList.GetArrayIndex ( i );
568  neighbor_status = statusIt.GetPixel ( idx );
569  // 1 is first negative layer that will come into the active layer
570  if ( neighbor_status == 1 )
571  {
572  // Keep the smallest possible value for the new active node. This
573  // places the new active layer node closest to the zero level-set.
574  if ( outputIt.GetPixel ( idx ) < LOWER_ACTIVE_THRESHOLD ||
575  vnl_math_abs ( temp_value ) < vnl_math_abs (
576  outputIt.GetPixel ( idx ) ) )
577  {
578  UpdatePixel ( this->m_CurrentFunctionIndex, idx, outputIt, temp_value, bounds_status );
579  }
580  }
581  }
582  // Push current active layer pixel into the uplist
583  node = sparsePtr->m_LayerNodeStore->Borrow();
584  node->m_Value = layerIt->m_Value;
585  UpList->PushFront ( node );
586  statusIt.SetCenterPixel ( m_StatusActiveChangingUp );
587 
588  // Now remove this pixel from the active list.
589  release_node = layerIt.GetPointer();
590  sparsePtr->m_Layers[0]->Unlink ( release_node );
591  sparsePtr->m_LayerNodeStore->Return ( release_node );
592  }
593 
594  else if ( new_value < LOWER_ACTIVE_THRESHOLD )
595  {
596  // This index will move DOWN into a negative (inside) layer. 2 in the
597  // positive sparse field will come in
598 
599  // First check for active layer neighbors moving in the opposite
600  // direction.
601  flag = false;
602  for ( i = 0; i < m_NeighborList.GetSize(); ++i )
603  {
604 
605  if ( statusIt.GetPixel( m_NeighborList.GetArrayIndex( i ) )
606  == m_StatusActiveChangingUp )
607  {
608  flag = true;
609  break;
610  }
611  }
612 
613  if ( flag == true )
614  {
615  ++layerIt;
616  ++updateIt;
617  continue;
618  }
619 
620  // Search the neighborhood for outside indicies.
621  for ( i = 0; i < m_NeighborList.GetSize(); ++i )
622  {
623  temp_value = new_value + m_ConstantGradientValue * m_PixelDistance[i];
624  idx = m_NeighborList.GetArrayIndex ( i );
625  neighbor_status = statusIt.GetPixel ( idx );
626  if ( neighbor_status == 2 )
627  {
628  // Keep the smallest magnitude value for this active set node. This
629  // places the node closest to the active layer.
630  if ( outputIt.GetPixel ( idx ) >= UPPER_ACTIVE_THRESHOLD ||
631  vnl_math_abs ( temp_value ) < vnl_math_abs (
632  outputIt.GetPixel ( idx ) ) )
633  {
634  UpdatePixel ( this->m_CurrentFunctionIndex, idx, outputIt, temp_value, bounds_status );
635  }
636  }
637  }
638  // Push current active layer pixel into the downlist
639  node = sparsePtr->m_LayerNodeStore->Borrow();
640  node->m_Value = layerIt->m_Value;
641  DownList->PushFront ( node );
642  statusIt.SetCenterPixel ( m_StatusActiveChangingDown );
643 
644  // Now remove this index from the active list.
645  release_node = layerIt.GetPointer();
646  sparsePtr->m_Layers[0]->Unlink ( release_node );
647  sparsePtr->m_LayerNodeStore->Return ( release_node );
648  }
649  else
650  {
651  UpdatePixel( this->m_CurrentFunctionIndex, outputIt.Size()/2, outputIt, new_value, bounds_status );
652  }
653 
654  // Move to the next active layer pixel
655  ++layerIt;
656  ++updateIt;
657  }
658 }
659 
660 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
661 void
662 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
663  TOutputImage,
664  TFunction, TIdCell >
665 ::InitializeActiveLayerValues()
666 {
667  // Initialize all active layer pixels to values computed as distance
668  // to the 0 contour. Similar to the fast marching initial seeds.
669 
670  const ValueType MIN_NORM = 1.0e-6;
671  InputSpacingType spacing = this->m_LevelSet[0]->GetSpacing();
672 
673  double temp;
674  for ( IdCellType i = 0; i < this->m_FunctionCount; i++ )
675  {
676  SparseDataStruct *sparsePtr = this->m_SparseData[i];
677 
678  InputImagePointer levelset = this->m_LevelSet[i];
679 
680  typename LayerType::ConstIterator activeIt;
682  m_NeighborList.GetRadius(),
683  levelset, levelset->GetRequestedRegion() );
684 
685  sparsePtr->m_UpdateBuffer.clear();
686  sparsePtr->m_UpdateBuffer.reserve ( sparsePtr->m_Layers[0]->Size() );
687 
688  unsigned int center; // index to active layer pixel
689  center = outputIt.Size()/2;
690  ValueType dx, gradientMagnitude, gradientMagnitudeSqr,
691  distance, forward, current, backward;
692 
693  // For all indicies in the active layer...
694  activeIt = sparsePtr->m_Layers[0]->Begin();
695  while( activeIt != sparsePtr->m_Layers[0]->End() )
696  {
697  // Interpolate on the (shifted) input image values at this index to
698  // assign an active layer value in the output image.
699  outputIt.SetLocation ( activeIt->m_Value );
700 
701  gradientMagnitudeSqr = m_ValueZero;
702 
703  for ( unsigned int j = 0; j < ImageDimension; ++j )
704  {
705  // Compute forward and backward pixel values
706  forward = outputIt.GetPixel ( center + m_NeighborList.GetStride( j ) );
707  current = outputIt.GetCenterPixel();
708  backward = outputIt.GetPixel ( center - m_NeighborList.GetStride ( j ) );
709 
710  if ( forward * backward >= 0 )
711  {
712  // Neighbors are same sign OR at least one neighbor is zero.
713  // Pick the larger magnitude derivative.
714  if ( ::vnl_math_abs ( forward - center ) >::vnl_math_abs( center - backward ) )
715  {
716  dx = ( forward - current ) / spacing[j];
717  }
718  else
719  {
720  dx = ( current - backward ) / spacing[j];
721  }
722  }
723  else
724  {
725  // Choose the derivative closest to the 0 contour
726  if ( vnl_math_sgn( current*forward ) == -1 )
727  {
728  dx = ( forward - current ) / spacing[j];
729  }
730  else
731  {
732  dx = ( current - backward ) / spacing[j];
733  }
734  }
735  gradientMagnitudeSqr += dx * dx;
736  }
737  gradientMagnitude = vcl_sqrt ( gradientMagnitudeSqr ) + MIN_NORM;
738 
739  // Compute the correct distance as phi(x)/gradientMagnitude
740  distance = outputIt.GetCenterPixel() / gradientMagnitude;
741 
742  // Insert in the update buffer
743  sparsePtr->m_UpdateBuffer.push_back(
744  vnl_math_min ( vnl_math_max ( -MIN_NORM, distance ),
745  MIN_NORM ) );
746  ++activeIt;
747  }
748 
749  // Update the level-set image using the update buffer
750  activeIt = sparsePtr->m_Layers[0]->Begin();
751  while( activeIt != sparsePtr->m_Layers[0]->End() )
752  {
753  // Update the accumulator value using the update buffer
754  temp = static_cast< double > ( sparsePtr->m_UpdateBuffer.front()
755  - levelset->GetPixel ( activeIt->m_Value ) );
756  m_RMSSum += temp * temp;
757  m_RMSCounter++;
758 
759  levelset->SetPixel ( activeIt->m_Value, sparsePtr->m_UpdateBuffer.front() );
760  ++activeIt;
761  }
762  }
763 }
764 
765 
766 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
767 void
768 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
769  TOutputImage,
770  TFunction, TIdCell >
771 ::PropagateAllLayerValues()
772 {
773  for ( IdCellType i = 0; i < this->m_FunctionCount; i++ )
774  {
775  // Calls the UpdatePixel(...) function inside
776  PropagateFunctionLayerValues ( i );
777  }
778 }
779 
780 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
781 void
782 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
783  TOutputImage,
784  TFunction, TIdCell >
785 ::PropagateFunctionLayerValues ( unsigned int fId )
786 {
787  SparseDataStruct *sparsePtr = this->m_SparseData[fId];
788 
789  // Update values in the first inside and first outside layers using the
790  // active layer as a seed. Inside layers are odd numbers, outside layers are
791  // even numbers.
792 
793  this->PropagateLayerValues ( sparsePtr, 0, 1, 3, 1 ); // first inside
794  this->PropagateLayerValues ( sparsePtr, 0, 2, 4, 2 ); // first outside
795 
796  // Update the rest of the layers.
797  for ( unsigned int i = 1; i < sparsePtr->m_Layers.size() - 2; ++i )
798  {
799  this->PropagateLayerValues ( sparsePtr, i, i+2, i+4, ( i+2 ) %2 );
800  }
801 }
802 
803 template<class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
804 void
805 MultiphaseSparseFiniteDifferenceImageFilter< TInputImage, TFeatureImage,
806  TOutputImage,
807  TFunction, TIdCell >
808 ::PropagateLayerValues ( SparseDataStruct *sparsePtr, StatusType from,
809  StatusType to, StatusType promote, int InOrOut )
810 {
811  // InOrOut indicates whether we are propagating in the negative/positive region
812  // of the level-set function
813 
814  unsigned int i;
815  ValueType value_temp, delta;
816  ValueType value = NumericTraits<ValueType>::Zero; // warnings
817  bool found_neighbor_flag;
818  LayerIterator toIt;
819  LayerNodeType *node;
820 
821  StatusType past_end = static_cast<StatusType>( sparsePtr->m_Layers.size() )-1;
822 
823  // Are we propagating values inward (-1, more negative) or outward (1, more
824  // positive)?
825  delta = ( InOrOut == 1 ) ? -1: 1;
826 
828  outputIt ( m_NeighborList.GetRadius(),
829  this->m_LevelSet[sparsePtr->m_Index],
830  this->m_LevelSet[sparsePtr->m_Index]->GetRequestedRegion() );
832  statusIt ( m_NeighborList.GetRadius(), sparsePtr->m_StatusImage,
833  this->m_LevelSet[sparsePtr->m_Index]->GetRequestedRegion() );
834 
835  if ( !m_BoundsCheckingActive )
836  {
838  statusIt.NeedToUseBoundaryConditionOff();
839  }
840 
841  // Iterate over the to-layer to fill the values in the output image
842  toIt = sparsePtr->m_Layers[to]->Begin();
843  while ( toIt != sparsePtr->m_Layers[to]->End() )
844  {
845  // Set the iterator location in the status image
846  OutputIndexType indexCurrent = toIt->m_Value;
847  statusIt.SetLocation ( indexCurrent );
848 
849  // Is this index marked for deletion? If the status image has
850  // been marked with another layer's value, we need to delete this node
851  // from the current list then skip to the next iteration.
852  if ( statusIt.GetCenterPixel() != to )
853  {
854  node = toIt.GetPointer();
855  ++toIt;
856  sparsePtr->m_Layers[to]->Unlink ( node );
857  sparsePtr->m_LayerNodeStore->Return ( node );
858  continue;
859  }
860 
861  // Set the iterator location in the level-set image
862  outputIt.SetLocation ( toIt->m_Value );
863 
864  // We explore all neighbors to identify the closest from-layer node
865  found_neighbor_flag = false;
866  unsigned int indexNeighbor;
867  for ( i = 0; i < m_NeighborList.GetSize(); ++i )
868  {
869  // If this neighbor is in the "from" list, compare its absolute value
870  // to any previous values found in the "from" list. Keep the value
871  // that will cause the to-layer to be closest to the zero level set.
872  indexNeighbor = m_NeighborList.GetArrayIndex ( i ); // Get index
873  if ( statusIt.GetPixel ( indexNeighbor ) == from ) // if belongs to from-layer
874  {
875  // This value should be a distance in terms of spacing with neighbors
876  // plus its current value
877 
878  InputPointType p1, p2;
879  ValueType dist = 0; // compute the distance between neighbors
880  this->m_LevelSet[sparsePtr->m_Index]->TransformIndexToPhysicalPoint(
881  statusIt.GetIndex( indexNeighbor ), p1 );
882  this->m_LevelSet[sparsePtr->m_Index]->TransformIndexToPhysicalPoint(
883  indexCurrent, p2);
884  for( unsigned int j = 0; j < ImageDimension; j++ )
885  dist += (p1[j] - p2[j]) * (p1[j] - p2[j]);
886  dist = delta * vcl_sqrt( dist );
887 
888  value_temp = dist + outputIt.GetPixel ( indexNeighbor ); // grab its value
889 
890  if ( !found_neighbor_flag )
891  {
892  value = value_temp;
893  }
894  else
895  {
896  // Irrespective of negative/positive region, select the lowest absolute minimum
897  //value = delta * vnl_math_min( vnl_math_abs( value_temp ), vnl_math_abs( value ) );
898  if ( InOrOut == 1 ) // inward
899  {
900  // Find the largest (least negative) neighbor
901  if ( value_temp > value )
902  {
903  value = value_temp;
904  }
905  }
906  else
907  {
908  // Find the smallest (least positive) neighbor
909  if ( value_temp < value )
910  {
911  value = value_temp;
912  }
913  }
914 
915  }
916  found_neighbor_flag = true;
917  }
918  }
919 
920  if ( found_neighbor_flag )
921  {
922  // Set the new value using the smallest distance
923  // found in our "from" neighbors.
924  bool bounds_status;
925  unsigned int center = outputIt.Size()/2;
926 
927  UpdatePixel(sparsePtr->m_Index, center, outputIt, value, bounds_status);
928 
929  // Update the rms change
930  m_RMSSum += ( value - outputIt.GetCenterPixel() ) * ( value - outputIt.GetCenterPixel() );
931  m_RMSCounter++;
932 
933  ++toIt;
934  }
935  else
936  {
937  // Did not find any neighbors on the "from" list, then promote this
938  // node. A "promote" value past the end of my sparse field size
939  // means delete the node instead. Change the status value in the
940  // status image accordingly.
941  node = toIt.GetPointer();
942  ++toIt;
943  sparsePtr->m_Layers[to]->Unlink ( node );
944  if ( promote > past_end )
945  {
946  sparsePtr->m_LayerNodeStore->Return ( node );
947  // Reset the pixel status to null -- does not belong to sparse layer
948  statusIt.SetCenterPixel ( m_StatusNull );
949  // Set the pixel to its default background value
950  this->m_LevelSet[sparsePtr->m_Index]->SetPixel( indexCurrent ,
951  delta * this->m_BackgroundValue );
952  }
953  else
954  {
955  sparsePtr->m_Layers[promote]->PushFront ( node );
956  statusIt.SetCenterPixel ( promote );
957  }
958  }
959  }
960 }
961 
962 template< class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
963 void
966 {
967  Superclass::InitializeIteration();
968 
969  m_RMSSum = 0.;
970  m_RMSCounter = 0; // counter
971 
972  // Set the values in the output image for the active layer.
973  this->InitializeActiveLayerValues();
974 
975  // Initialize layer values using the active layer as seeds
976  this->PropagateAllLayerValues();
977 
978  // Determine the average RMS of change during this iteration
979  if ( m_RMSCounter == 0 )
980  {
981  this->SetRMSChange ( static_cast<double> ( 0. ) );
982  }
983  else
984  {
985  this->SetRMSChange ( vcl_sqrt ( m_RMSSum / m_RMSCounter ) );
986  }
987 }
988 
989 
990 template< class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
991 void
994 {
995  // Initialize m_PixelDistance values for the corresponding neighborhood list
996  // This stores the distance between neighbors. Usually same as 1 except when
997  // the image spacing is different.
998  InputSpacingType spacing = this->m_LevelSet[0]->GetSpacing();
999  OffsetType offset;
1000  this->m_PixelDistance.clear();
1001  this->m_PixelDistance.resize ( m_NeighborList.GetSize() );
1002  for ( unsigned int i = 0; i < m_NeighborList.GetSize(); ++i )
1003  {
1004  offset = m_NeighborList.GetNeighborhoodOffset ( i );
1005  m_PixelDistance[i] = 0;
1006  for( unsigned int j = 0; j < ImageDimension; j++ )
1007  {
1008  m_PixelDistance[i] += offset[j]*spacing[j]*offset[j]*spacing[j];
1009  }
1010  m_PixelDistance[i] = vcl_sqrt( m_PixelDistance[i] );
1011  }
1012 
1013 
1014  for ( IdCellType fId = 0; fId < this->m_FunctionCount; ++fId )
1015  {
1016  SparseDataStruct *sparsePtr = this->m_SparseData[fId];
1017 
1018  // Allocate the status image.
1019  sparsePtr->m_StatusImage = StatusImageType::New();
1020  sparsePtr->m_StatusImage->SetRegions (
1021  this->m_LevelSet[fId]->GetRequestedRegion() );
1022  sparsePtr->m_StatusImage->CopyInformation( this->m_LevelSet[fId] );
1023  sparsePtr->m_StatusImage->Allocate();
1024  sparsePtr->m_StatusImage->FillBuffer( m_StatusNull );//NonpositiveMin
1025 
1026  // Initialize the boundary pixels in the status image to
1027  // m_StatusBoundaryPixel values. Uses the face calculator to find all of
1028  // the region faces.
1029  BFCType faceCalculator;
1030  typename BFCType::FaceListType faceList;
1031 
1032  // Set the difference function radius here
1033  typename BFCType::SizeType sz = this->m_DifferenceFunctions[fId]->GetRadius();
1034  typename BFCType::FaceListType::iterator fit;
1035 
1036  // Compute the boundary pixel regions set in a container
1037  faceList = faceCalculator ( sparsePtr->m_StatusImage,
1038  sparsePtr->m_StatusImage->GetRequestedRegion(), sz );
1039 
1040  // Iterate over the boundary region sets
1041  fit = faceList.begin();
1042  for( ++fit; fit != faceList.end(); ++fit )
1043  {
1044  // For each region, set the pixel in m_StatusImage to m_StatusBoundaryPixel
1045  ImageRegionIterator<StatusImageType> statusIt( sparsePtr->m_StatusImage, *fit );
1046 
1047  statusIt.GoToBegin();
1048  while( ! statusIt.IsAtEnd() )
1049  {
1050  statusIt.Set ( m_StatusBoundaryPixel );
1051  ++statusIt;
1052  }
1053  }
1054 
1055  // Erase all existing layer lists -- element by element
1056  for ( unsigned int i = 0; i < sparsePtr->m_Layers.size(); ++i )
1057  {
1058  while ( ! sparsePtr->m_Layers[i]->Empty() )
1059  {
1060  sparsePtr->m_LayerNodeStore->Return( sparsePtr->m_Layers[i]->Front());
1061  sparsePtr->m_Layers[i]->PopFront();
1062  }
1063  }
1064 
1065  // Allocate the layers for the sparse field.
1066  sparsePtr->m_Layers.clear();
1067  sparsePtr->m_Layers.reserve( 2 * this->m_NumberOfLayers + 1 );
1068 
1069  while( sparsePtr->m_Layers.size() < ( 2 * this->m_NumberOfLayers+1 ) )
1070  {
1071  sparsePtr->m_Layers.push_back( LayerType::New() );
1072  }
1073 
1074  // Throw an exception if we don't have enough layers.
1075  if ( sparsePtr->m_Layers.size() < 3 )
1076  {
1077  itkExceptionMacro ( << "Not enough layers have been allocated for the"
1078  "sparse field. Requires at least one layer." );
1079  }
1080  }
1081 
1082  // Set the background constants required to be set outside the sparse layer
1083  this->InitializeBackgroundConstants();
1084 
1085  // Construct the active layer and initialize the first layers inside and
1086  // outside of the active layer for all level-set functions.
1087  this->ConstructActiveLayer();
1088 
1089  for ( IdCellType fId = 0; fId < this->m_FunctionCount; ++fId )
1090  {
1091  SparseDataStruct *sparsePtr = this->m_SparseData[fId];
1092 
1093  // Construct the rest of the non-active set layers using the first two
1094  // layers. Inside layers are odd numbers, outside layers are even numbers.
1095  // We need to loop from i = 1 to m_Layers.size()-2 since the last two layers
1096  // are constructed in the previous iteration
1097  for ( unsigned int i = 1; i < sparsePtr->m_Layers.size() - 2; ++i )
1098  {
1099  // Construct layer i+2 from layer i. Note that layer i+1 is on the other side
1100  this->ConstructLayer( sparsePtr, i, i+2 );
1101  }
1102  }
1103 
1104  // Set the values in the output image for the active layer.
1105  this->InitializeActiveLayerValues();
1106 
1107  // Initialize layer values using the active layer as seeds
1108  this->PropagateAllLayerValues();
1109 
1110  // Initialize pixels outside the sparse field layers to positive
1111  // and negative values, respectively. This is not necessary for the
1112  // calculations, but is useful for presenting a more intuitive output to the
1113  // filter. See PostProcessOutput method for more information.
1114  this->InitializeBackgroundPixels();
1115 }
1116 
1117 
1118 template< class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
1119 void
1122 {
1123  // Determine the maximum spacing to set the background pixel values
1124  // outside the sparse field
1125  float maxSpacing = NumericTraits<float>::min();
1126  InputSpacingType spacing = this->m_LevelSet[0]->GetSpacing();
1127  for( unsigned int i = 0; i < ImageDimension; i++ )
1128  maxSpacing = vnl_math_max( maxSpacing, static_cast<float>( spacing[i] ) );
1129 
1130  // Assign background pixels OUTSIDE the sparse field layers to a new level
1131  // set with value greater than the outermost layer. Assign background pixels
1132  // INSIDE the sparse field layers to a new level set with value less than
1133  // the innermost layer.
1134  const ValueType max_layer = static_cast<ValueType> ( this->m_NumberOfLayers );
1135 
1136  this->m_BackgroundValue = ( max_layer + 1 ) * maxSpacing;
1137 }
1138 
1139 
1140 template< class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
1141 void
1144 {
1145  for ( IdCellType fId = 0; fId < this->m_FunctionCount; fId++ )
1146  {
1147  SparseDataStruct *sparsePtr = this->m_SparseData[fId];
1148 
1150  sparsePtr->m_StatusImage,
1151  this->m_LevelSet[fId]->GetRequestedRegion() );
1152 
1154  this->m_LevelSet[fId],
1155  this->m_LevelSet[fId]->GetRequestedRegion() );
1156 
1157  outputIt.GoToBegin();
1158  statusIt.GoToBegin();
1159 
1160  while( !outputIt.IsAtEnd() )
1161  {
1162  if( statusIt.Get() == m_StatusNull || statusIt.Get() ==
1163  m_StatusBoundaryPixel )
1164  {
1165  if( outputIt.Get() > 0 )
1166  {
1167  outputIt.Set ( this->m_BackgroundValue );
1168  }
1169  if( outputIt.Get() < 0 )
1170  {
1171  outputIt.Set ( - this->m_BackgroundValue );
1172  }
1173  }
1174  ++outputIt;
1175  ++statusIt;
1176  }
1177  }
1178 }
1179 
1180 
1181 template< class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
1182 void
1185 {
1186  // We construct active layers for all level-set functions
1187  for ( IdCellType fId = 0; fId < this->m_FunctionCount; fId++ )
1188  {
1189  SparseDataStruct *sparsePtr = this->m_SparseData[fId];
1190 
1191  // We find the active layer by searching for 0's in the zero crossing
1192  // image (output image). The first inside and outside layers are also
1193  // constructed by searching the neighbors of the active layer in the
1194  // (shifted) input image. Negative neighbors not in the active set are
1195  // assigned to the inside, positive neighbors are assigned to the outside.
1196  //
1197  // During construction we also check whether any of the layers of the
1198  // active set (or the active set itself) is sitting on a boundary pixel
1199  // location. If this is the case, then we need to do active bounds
1200  // checking in the solver.
1201 
1203  outputIt ( m_NeighborList.GetRadius(),
1204  this->m_LevelSet[fId],
1205  this->m_LevelSet[fId]->GetRequestedRegion() );
1206 
1208  statusIt ( m_NeighborList.GetRadius(),
1209  sparsePtr->m_StatusImage,
1210  this->m_LevelSet[fId]->GetRequestedRegion() );
1211 
1212  InputIndexType center_index, offset_index;
1213  LayerNodeType *node;
1214  bool bounds_status;
1215  StatusType layer_number;
1216 
1217  // Determine image bounds for checking if sparse layers touch boundaries
1218  InputIndexType lowerBounds;
1219  InputSizeType upperBounds;
1220  lowerBounds = this->m_LevelSet[fId]->GetRequestedRegion().GetIndex();
1221  upperBounds = this->m_LevelSet[fId]->GetRequestedRegion().GetSize();
1222 
1223  // Iterate over the output image
1224  outputIt.GoToBegin();
1225  while( !outputIt.IsAtEnd() )
1226  {
1227  // Check if the center pixel has a value 0. The zeroCrossingFilter has
1228  // already placed 0s on the active layer pixels and 1 everywhere else.
1229  if ( outputIt.GetCenterPixel() == m_ValueZero )
1230  {
1231  // Grab the neighborhood in the status image.
1232  center_index = outputIt.GetIndex();
1233 
1234  statusIt.SetLocation ( center_index );
1235 
1236  // Check to see if any of the sparse field touches a boundary. If so,
1237  // then activate bounds checking.
1238  for ( unsigned int i = 0; i < ImageDimension; i++ )
1239  {
1240  if ( ( center_index[i] + static_cast< long > (
1241  this->m_NumberOfLayers ) >= static_cast< long>( upperBounds[i] - 1 ) )
1242  || center_index[i] - static_cast< long >(
1243  this->m_NumberOfLayers ) <= static_cast< long >(lowerBounds[i]) )
1244  {
1245  m_BoundsCheckingActive = true;
1246  }
1247  }
1248 
1249  // Borrow a node from the store and set its value.
1250  node = sparsePtr->m_LayerNodeStore->Borrow();
1251  node->m_Value = center_index;
1252 
1253  // Add the node to the active list and set the status in the status
1254  // image.
1255  sparsePtr->m_Layers[0]->PushFront ( node );
1256  statusIt.SetCenterPixel ( 0 );
1257 
1258  // Search the neighborhood pixels for first inside & outside layer
1259  // members. Construct these lists and set status list values.
1260  for ( unsigned int i = 0; i < m_NeighborList.GetSize(); ++i )
1261  {
1262  // If the neighborhood pixel is not on the active layer
1263  // determine its sign to assign to outside or inside layers
1264  unsigned int neighborIndex = m_NeighborList.GetArrayIndex( i );
1265  if ( outputIt.GetPixel( neighborIndex ) != m_ValueZero )
1266  {
1267  // Determine if the neighbor belongs to layer 1 (inside) or 2 (outside)
1268  layer_number = ( outputIt.GetPixel ( neighborIndex ) > 0 ) ? 2 : 1;
1269 
1270  // This check is to prevent the same pixel from being included more than once
1271  // in the list
1272  if ( statusIt.GetPixel( neighborIndex ) == m_StatusNull )
1273  {
1274  statusIt.SetPixel ( neighborIndex, layer_number, bounds_status );
1275 
1276  if ( bounds_status ) // In bounds.
1277  {
1278  offset_index = center_index + m_NeighborList.GetNeighborhoodOffset ( i );
1279  node = sparsePtr->m_LayerNodeStore->Borrow();
1280  node->m_Value = offset_index;
1281  sparsePtr->m_Layers[layer_number]->PushFront ( node );
1282  } // else do nothing.
1283  }
1284  }
1285  }
1286  }
1287  ++outputIt;
1288  }
1289  }
1290 }
1291 
1292 template< class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
1293 void
1296 {
1297  LayerNodeType *node;
1298  bool boundary_status;
1299 
1301  m_NeighborList.GetRadius(), sparsePtr->m_StatusImage,
1302  this->m_LevelSet[sparsePtr->m_Index]->GetRequestedRegion() );
1303 
1304 
1305  typename LayerType::ConstIterator fromIt;
1306  fromIt = sparsePtr->m_Layers[from]->Begin();
1307 
1308  // For all indices in the "from" layer...
1309  while( fromIt != sparsePtr->m_Layers[from]->End() )
1310  {
1311  // Search the neighborhood of this index in the status image for
1312  // unassigned indicies. Push those indicies onto the "to" layer and
1313  // assign them values in the status image. Status pixels outside the
1314  // boundary will be ignored.
1315  statusIt.SetLocation ( fromIt->m_Value );
1316  for ( unsigned int i = 0; i < m_NeighborList.GetSize(); ++i )
1317  {
1318  // If the pixel is not a boundary pixel or belongs to another layer
1319  unsigned int neighborIndex = m_NeighborList.GetArrayIndex ( i );
1320  if ( statusIt.GetPixel ( neighborIndex ) == m_StatusNull )
1321  {
1322  statusIt.SetPixel ( neighborIndex, to, boundary_status );
1323  if ( boundary_status == true ) // in bounds
1324  {
1325  node = sparsePtr->m_LayerNodeStore->Borrow();
1326  node->m_Value = statusIt.GetIndex() + m_NeighborList.GetNeighborhoodOffset ( i );
1327  sparsePtr->m_Layers[to]->PushFront ( node );
1328  }
1329  }
1330  }
1331  ++fromIt;
1332  }
1333 }
1334 
1335 template< class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
1336 void
1339 {
1340  // Get the output pointer and clear its contents
1341  OutputImagePointer output = this->GetOutput();
1342  output->FillBuffer( NumericTraits<OutputPixelType>::Zero );
1343 
1344  // Set the values in the levelset image for the active layer.
1345  this->InitializeActiveLayerValues();
1346  // Initialize layer values using the active layer as seeds.
1347  this->PropagateAllLayerValues();
1348 
1349  // Initialize pixels outside the sparse field layers to positive
1350  // and negative values, respectively. This is not necessary for the
1351  // calculations, but is useful for presenting a more intuitive output to the
1352  // filter.
1353  this->InitializeBackgroundPixels();
1354 
1355  for ( IdCellType fId = 0; fId < this->m_FunctionCount; fId++ )
1356  {
1357  InputImagePointer input = this->m_LevelSet[fId];
1358  InputPointType origin = input->GetOrigin();
1359  InputSpacingType spacing = input->GetSpacing();
1360 
1361  // Local iterator
1362  ImageRegionIterator< InputImageType > inIt ( this->m_LevelSet[fId],
1363  this->m_LevelSet[fId]->GetRequestedRegion() );
1364 
1365  // In the context of the global coordinates
1366  OutputIndexType start;
1367  output->TransformPhysicalPointToIndex( origin, start );
1368 
1369  // Defining sub-region in the global coordinates
1370  OutputRegionType region;
1371  region.SetSize( input->GetRequestedRegion().GetSize() );
1372  region.SetIndex( start );
1373 
1374  if ( !input || !output )
1375  {
1376  itkExceptionMacro ( << "Either input and/or output is NULL." );
1377  }
1378 
1379  ImageRegionIterator< OutputImageType > outIt ( output, region );
1380 
1381  OutputPixelType p = static_cast< OutputPixelType > ( this->m_Lookup[fId] );
1382 
1383  inIt.GoToBegin();
1384  outIt.GoToBegin();
1385 
1386  while( !outIt.IsAtEnd() )
1387  {
1388  if ( inIt.Get() < 0 )
1389  {
1390  outIt.Value() = p;
1391  }
1392  ++inIt;
1393  ++outIt;
1394  }
1395  }
1396 }
1397 
1398 template< class TInputImage, class TFeatureImage, class TOutputImage, class TFunction, typename TIdCell >
1399 void
1401 ::PrintSelf ( std::ostream& os, Indent indent ) const
1402 {
1403  Superclass::PrintSelf(os,indent);
1404 
1405  os << indent << "m_IsoSurfaceValue: " << this->m_IsoSurfaceValue << std::endl;
1406  os << indent << "m_BoundsCheckingActive: " << m_BoundsCheckingActive;
1407 
1408  for( IdCellType i = 0; i < this->m_FunctionCount; i++ )
1409  {
1410  SparseDataStruct *sparsePtr = this->m_SparseData[i];
1411  os << indent << "m_LayerNodeStore: " << std::endl;
1412  sparsePtr->m_LayerNodeStore->Print ( os,indent.GetNextIndent() );
1413  for ( i = 0; i < sparsePtr->m_Layers.size(); i++ )
1414  {
1415  os << indent << "m_Layers[" << i << "]: size="
1416  << sparsePtr->m_Layers[i]->Size() << std::endl;
1417  os << indent << sparsePtr->m_Layers[i];
1418  }
1419 
1420  os << indent << "m_UpdateBuffer: size=" <<
1421  static_cast< unsigned long > ( sparsePtr->m_UpdateBuffer.size() )
1422  << " capacity = " <<
1423  static_cast<unsigned long> ( sparsePtr->m_UpdateBuffer.capacity() ) <<
1424  std::endl;
1425  }
1426 
1427  os << indent << "Interpolate Surface Location " << m_InterpolateSurfaceLocation << std::endl;
1428  os << indent << "Number of Layers " << m_NumberOfLayers << std::endl;
1429  os << indent << "Value Zero " <<
1430  static_cast< typename NumericTraits<ValueType>::PrintType >( m_ValueZero ) << std::endl;
1431  os << indent << "Value One " <<
1432  static_cast< typename NumericTraits<ValueType>::PrintType >( m_ValueOne ) << std::endl;
1433 }
1434 
1435 } // end namespace itk
1436 
1437 #endif

Generated at Sat Feb 2 2013 23:54:36 for Orfeo Toolbox with doxygen 1.8.1.1