Orfeo Toolbox  3.16
itkSparseFieldLevelSetImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkSparseFieldLevelSetImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2008-10-18 16:11:13 $
7  Version: $Revision: 1.45 $
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 __itkSparseFieldLevelSetImageFilter_txx
18 #define __itkSparseFieldLevelSetImageFilter_txx
19 
22 #include "itkImageRegionIterator.h"
26 
27 namespace itk {
28 
29 template <class TNeighborhoodType>
32 {
33  typedef typename NeighborhoodType::ImageType ImageType;
34  typename ImageType::Pointer dummy_image = ImageType::New();
35 
36  unsigned int i, nCenter;
37  int d;
38  OffsetType zero_offset;
39 
40  for (i = 0; i < Dimension; ++i)
41  {
42  m_Radius[i] = 1;
43  zero_offset[i] = 0;
44  }
45  NeighborhoodType it(m_Radius, dummy_image, dummy_image->GetRequestedRegion());
46  nCenter = it.Size() / 2;
47 
48  m_Size = 2 * Dimension;
49  m_ArrayIndex.reserve(m_Size);
50  m_NeighborhoodOffset.reserve(m_Size);
51 
52  for (i = 0; i < m_Size; ++i)
53  {
54  m_NeighborhoodOffset.push_back(zero_offset);
55  }
56 
57  for (d = Dimension - 1, i = 0; d >= 0; --d, ++i)
58  {
59  m_ArrayIndex.push_back( nCenter - it.GetStride(d) );
60  m_NeighborhoodOffset[i][d] = -1;
61  }
62  for (d = 0; d < static_cast<int>(Dimension); ++d, ++i)
63  {
64  m_ArrayIndex.push_back( nCenter + it.GetStride(d) );
65  m_NeighborhoodOffset[i][d] = 1;
66  }
67 
68  for (i = 0; i < Dimension; ++i)
69  {
70  m_StrideTable[i] = it.GetStride(i);
71  }
72 }
73 
74 template <class TNeighborhoodType>
75 void
77 ::Print(std::ostream &os) const
78 {
79  os << "SparseFieldCityBlockNeighborList: " << std::endl;
80  for (unsigned i = 0; i < this->GetSize(); ++i)
81  {
82  os << "m_ArrayIndex[" << i << "]: " << m_ArrayIndex[i] << std::endl;
83  os << "m_NeighborhoodOffset[" << i << "]: " << m_NeighborhoodOffset[i]
84  << std::endl;
85  }
86 }
87 
88 //template<class TInputImage, class TOutputImage>
89 //double SparseFieldLevelSetImageFilter<TInputImage, TOutputImage>
90 //::m_ConstantGradientValue = 1.0;
91 
92 template<class TInputImage, class TOutputImage>
95 ::m_ValueOne = NumericTraits<ITK_TYPENAME SparseFieldLevelSetImageFilter<TInputImage,
96  TOutputImage>::ValueType >::One;
97 
98 template<class TInputImage, class TOutputImage>
101 ::m_ValueZero = NumericTraits<ITK_TYPENAME SparseFieldLevelSetImageFilter<TInputImage,
102  TOutputImage>::ValueType >::Zero;
103 
104 template<class TInputImage, class TOutputImage>
107 ::m_StatusNull = NumericTraits<ITK_TYPENAME SparseFieldLevelSetImageFilter<TInputImage,
108  TOutputImage>::StatusType >::NonpositiveMin();
109 
110 template<class TInputImage, class TOutputImage>
113 ::m_StatusChanging = -1;
114 
115 template<class TInputImage, class TOutputImage>
118 ::m_StatusActiveChangingUp = -2;
119 
120 template<class TInputImage, class TOutputImage>
123 ::m_StatusActiveChangingDown = -3;
124 
125 template<class TInputImage, class TOutputImage>
128 ::m_StatusBoundaryPixel = -4;
129 
130 template<class TInputImage, class TOutputImage>
133 {
134  m_IsoSurfaceValue = m_ValueZero;
135  m_NumberOfLayers = ImageDimension;
136  m_LayerNodeStore = LayerNodeStorageType::New();
137  m_LayerNodeStore->SetGrowthStrategyToExponential();
138  this->SetRMSChange(static_cast<double>(m_ValueZero));
139  m_InterpolateSurfaceLocation = true;
140  m_BoundsCheckingActive = false;
141  m_ConstantGradientValue = 1.0;
142 }
143 
144 template<class TInputImage, class TOutputImage>
147 {}
148 
149 template<class TInputImage, class TOutputImage>
150 void
153 {
154  unsigned int i, j, k, t;
155 
156  StatusType up_to, up_search;
157  StatusType down_to, down_search;
158 
159  LayerPointerType UpList[2];
160  LayerPointerType DownList[2];
161  for (i = 0; i < 2; ++i)
162  {
163  UpList[i] = LayerType::New();
164  DownList[i] = LayerType::New();
165  }
166 
167  // Process the active layer. This step will update the values in the active
168  // layer as well as the values at indicies that *will* become part of the
169  // active layer when they are promoted/demoted. Also records promotions,
170  // demotions in the m_StatusLayer for current active layer indicies
171  // (i.e. those indicies which will move inside or outside the active
172  // layers).
173  this->UpdateActiveLayerValues(dt, UpList[0], DownList[0]);
174 
175  // Process the status up/down lists. This is an iterative process which
176  // proceeds outwards from the active layer. Each iteration generates the
177  // list for the next iteration.
178 
179  // First process the status lists generated on the active layer.
180  this->ProcessStatusList(UpList[0], UpList[1], 2, 1);
181  this->ProcessStatusList(DownList[0], DownList[1], 1, 2);
182 
183  down_to = up_to = 0;
184  up_search = 3;
185  down_search = 4;
186  j = 1;
187  k = 0;
188  while( down_search < static_cast<StatusType>( m_Layers.size() ) )
189  {
190  this->ProcessStatusList(UpList[j], UpList[k], up_to, up_search);
191  this->ProcessStatusList(DownList[j], DownList[k], down_to, down_search);
192 
193  if (up_to == 0) up_to += 1;
194  else up_to += 2;
195  down_to += 2;
196 
197  up_search += 2;
198  down_search += 2;
199 
200  // Swap the lists so we can re-use the empty one.
201  t = j;
202  j = k;
203  k = t;
204  }
205 
206  // Process the outermost inside/outside layers in the sparse field.
207  this->ProcessStatusList(UpList[j], UpList[k], up_to, m_StatusNull);
208  this->ProcessStatusList(DownList[j], DownList[k], down_to, m_StatusNull);
209 
210  // Now we are left with the lists of indicies which must be
211  // brought into the outermost layers. Bring UpList into last inside layer
212  // and DownList into last outside layer.
213  this->ProcessOutsideList(UpList[k], static_cast<int>( m_Layers.size()) -2);
214  this->ProcessOutsideList(DownList[k], static_cast<int>( m_Layers.size()) -1);
215 
216  // Finally, we update all of the layer values (excluding the active layer,
217  // which has already been updated).
218  this->PropagateAllLayerValues();
219 }
220 
221 template <class TInputImage, class TOutputImage>
222 void
224 ::ProcessOutsideList(LayerType *OutsideList, StatusType ChangeToStatus)
225 {
226  LayerNodeType *node;
227 
228  // Push each index in the input list into its appropriate status layer
229  // (ChangeToStatus) and update the status image value at that index.
230  while ( ! OutsideList->Empty() )
231  {
232  m_StatusImage->SetPixel(OutsideList->Front()->m_Value, ChangeToStatus);
233  node = OutsideList->Front();
234  OutsideList->PopFront();
235  m_Layers[ChangeToStatus]->PushFront(node);
236  }
237 }
238 
239 template <class TInputImage, class TOutputImage>
240 void
242 ::ProcessStatusList(LayerType *InputList, LayerType *OutputList,
243  StatusType ChangeToStatus, StatusType SearchForStatus)
244 {
245  unsigned int i;
246  bool bounds_status;
247  LayerNodeType *node;
248  StatusType neighbor_status;
250  statusIt(m_NeighborList.GetRadius(), m_StatusImage,
251  this->GetOutput()->GetRequestedRegion());
252 
253  if (m_BoundsCheckingActive == false )
254  {
256  }
257 
258  // Push each index in the input list into its appropriate status layer
259  // (ChangeToStatus) and update the status image value at that index.
260  // Also examine the neighbors of the index to determine which need to go onto
261  // the output list (search for SearchForStatus).
262  while ( ! InputList->Empty() )
263  {
264  statusIt.SetLocation(InputList->Front()->m_Value);
265  statusIt.SetCenterPixel(ChangeToStatus);
266 
267  node = InputList->Front(); // Must unlink from the input list
268  InputList->PopFront(); // _before_ transferring to another list.
269  m_Layers[ChangeToStatus]->PushFront(node);
270 
271  for (i = 0; i < m_NeighborList.GetSize(); ++i)
272  {
273  neighbor_status = statusIt.GetPixel(m_NeighborList.GetArrayIndex(i));
274 
275  // Have we bumped up against the boundary? If so, turn on bounds
276  // checking.
277  if ( neighbor_status == m_StatusBoundaryPixel )
278  {
279  m_BoundsCheckingActive = true;
280  }
281 
282  if (neighbor_status == SearchForStatus)
283  { // mark this pixel so we don't add it twice.
284  statusIt.SetPixel(m_NeighborList.GetArrayIndex(i),
285  m_StatusChanging, bounds_status);
286  if (bounds_status == true)
287  {
288  node = m_LayerNodeStore->Borrow();
289  node->m_Value = statusIt.GetIndex() +
290  m_NeighborList.GetNeighborhoodOffset(i);
291  OutputList->PushFront( node );
292  } // else this index was out of bounds.
293  }
294  }
295  }
296 }
297 
298 template <class TInputImage, class TOutputImage>
299 void
302  LayerType *UpList, LayerType *DownList)
303 {
304  // This method scales the update buffer values by the time step and adds
305  // them to the active layer pixels. New values at an index which fall
306  // outside of the active layer range trigger that index to be placed on the
307  // "up" or "down" status list. The neighbors of any such index are then
308  // assigned new values if they are determined to be part of the active list
309  // for the next iteration (i.e. their values will be raised or lowered into
310  // the active range).
311  const ValueType LOWER_ACTIVE_THRESHOLD = - (m_ConstantGradientValue / 2.0);
312  const ValueType UPPER_ACTIVE_THRESHOLD = m_ConstantGradientValue / 2.0;
313  // const ValueType LOWER_ACTIVE_THRESHOLD = - 0.7;
314  // const ValueType UPPER_ACTIVE_THRESHOLD = 0.7;
315  ValueType new_value, temp_value, rms_change_accumulator;
316  LayerNodeType *node, *release_node;
317  StatusType neighbor_status;
318  unsigned int i, idx, counter;
319  bool bounds_status, flag;
320 
321  typename LayerType::Iterator layerIt;
322  typename UpdateBufferType::const_iterator updateIt;
323 
325  outputIt(m_NeighborList.GetRadius(), this->GetOutput(),
326  this->GetOutput()->GetRequestedRegion());
327 
329  statusIt(m_NeighborList.GetRadius(), m_StatusImage,
330  this->GetOutput()->GetRequestedRegion());
331 
332  if ( m_BoundsCheckingActive == false )
333  {
335  statusIt.NeedToUseBoundaryConditionOff();
336  }
337 
338  counter =0;
339  rms_change_accumulator = m_ValueZero;
340  layerIt = m_Layers[0]->Begin();
341  updateIt = m_UpdateBuffer.begin();
342  while (layerIt != m_Layers[0]->End() )
343  {
344  outputIt.SetLocation(layerIt->m_Value);
345  statusIt.SetLocation(layerIt->m_Value);
346 
347  new_value = this->CalculateUpdateValue(layerIt->m_Value,
348  dt,
349  outputIt.GetCenterPixel(),
350  *updateIt);
351 
352  // If this index needs to be moved to another layer, then search its
353  // neighborhood for indicies that need to be pulled up/down into the
354  // active layer. Set those new active layer values appropriately,
355  // checking first to make sure they have not been set by a more
356  // influential neighbor.
357 
358  // ...But first make sure any neighbors in the active layer are not
359  // moving to a layer in the opposite direction. This step is necessary
360  // to avoid the creation of holes in the active layer. The fix is simply
361  // to not change this value and leave the index in the active set.
362 
363  if (new_value >= UPPER_ACTIVE_THRESHOLD)
364  { // This index will move UP into a positive (outside) layer.
365 
366  // First check for active layer neighbors moving in the opposite
367  // direction.
368  flag = false;
369  for (i = 0; i < m_NeighborList.GetSize(); ++i)
370  {
371  if (statusIt.GetPixel(m_NeighborList.GetArrayIndex(i))
372  == m_StatusActiveChangingDown)
373  {
374  flag = true;
375  break;
376  }
377  }
378  if (flag == true)
379  {
380  ++layerIt;
381  ++updateIt;
382  continue;
383  }
384 
385  rms_change_accumulator += vnl_math_sqr(new_value-outputIt.GetCenterPixel());
386 
387  // Search the neighborhood for inside indicies.
388  temp_value = new_value - m_ConstantGradientValue;
389  for (i = 0; i < m_NeighborList.GetSize(); ++i)
390  {
391  idx = m_NeighborList.GetArrayIndex(i);
392  neighbor_status = statusIt.GetPixel( idx );
393  if (neighbor_status == 1)
394  {
395  // Keep the smallest possible value for the new active node. This
396  // places the new active layer node closest to the zero level-set.
397  if ( outputIt.GetPixel(idx) < LOWER_ACTIVE_THRESHOLD ||
398  ::vnl_math_abs(temp_value) < ::vnl_math_abs(outputIt.GetPixel(idx)) )
399  {
400  outputIt.SetPixel(idx, temp_value, bounds_status);
401  }
402  }
403  }
404  node = m_LayerNodeStore->Borrow();
405  node->m_Value = layerIt->m_Value;
406  UpList->PushFront(node);
407  statusIt.SetCenterPixel(m_StatusActiveChangingUp);
408 
409  // Now remove this index from the active list.
410  release_node = layerIt.GetPointer();
411  ++layerIt;
412  m_Layers[0]->Unlink(release_node);
413  m_LayerNodeStore->Return( release_node );
414  }
415 
416  else if (new_value < LOWER_ACTIVE_THRESHOLD)
417  { // This index will move DOWN into a negative (inside) layer.
418 
419  // First check for active layer neighbors moving in the opposite
420  // direction.
421  flag = false;
422  for (i = 0; i < m_NeighborList.GetSize(); ++i)
423  {
424  if (statusIt.GetPixel(m_NeighborList.GetArrayIndex(i))
425  == m_StatusActiveChangingUp)
426  {
427  flag = true;
428  break;
429  }
430  }
431  if (flag == true)
432  {
433  ++layerIt;
434  ++updateIt;
435  continue;
436  }
437 
438  rms_change_accumulator += vnl_math_sqr(new_value - outputIt.GetCenterPixel());
439 
440  // Search the neighborhood for outside indicies.
441  temp_value = new_value + m_ConstantGradientValue;
442  for (i = 0; i < m_NeighborList.GetSize(); ++i)
443  {
444  idx = m_NeighborList.GetArrayIndex(i);
445  neighbor_status = statusIt.GetPixel( idx );
446  if (neighbor_status == 2)
447  {
448  // Keep the smallest magnitude value for this active set node. This
449  // places the node closest to the active layer.
450  if ( outputIt.GetPixel(idx) >= UPPER_ACTIVE_THRESHOLD ||
451  ::vnl_math_abs(temp_value) < ::vnl_math_abs(outputIt.GetPixel(idx)) )
452  {
453  outputIt.SetPixel(idx, temp_value, bounds_status);
454  }
455  }
456  }
457  node = m_LayerNodeStore->Borrow();
458  node->m_Value = layerIt->m_Value;
459  DownList->PushFront(node);
460  statusIt.SetCenterPixel(m_StatusActiveChangingDown);
461 
462  // Now remove this index from the active list.
463  release_node = layerIt.GetPointer();
464  ++layerIt;
465  m_Layers[0]->Unlink(release_node);
466  m_LayerNodeStore->Return( release_node );
467  }
468  else
469  {
470  rms_change_accumulator += vnl_math_sqr(new_value - outputIt.GetCenterPixel());
471  //rms_change_accumulator += (*updateIt) * (*updateIt);
472  outputIt.SetCenterPixel( new_value );
473  ++layerIt;
474  }
475  ++updateIt;
476  ++counter;
477  }
478 
479  // Determine the average change during this iteration.
480  if (counter == 0)
481  { this->SetRMSChange(static_cast<double>(m_ValueZero)); }
482  else
483  {
484  this->SetRMSChange(static_cast<double>( vcl_sqrt((double)(rms_change_accumulator / static_cast<ValueType>(counter)) )) );
485  }
486 }
487 
488 template<class TInputImage, class TOutputImage>
489 void
492 {
493  // This method is the first step in initializing the level-set image, which
494  // is also the output of the filter. The input is passed through a
495  // zero crossing filter, which produces zero's at pixels closest to the zero
496  // level set and one's elsewhere. The actual zero level set values will be
497  // adjusted in the Initialize() step to more accurately represent the
498  // position of the zero level set.
499 
500  // First need to subtract the iso-surface value from the input image.
501  typedef ShiftScaleImageFilter<InputImageType, OutputImageType> ShiftScaleFilterType;
502  typename ShiftScaleFilterType::Pointer shiftScaleFilter = ShiftScaleFilterType::New();
503  shiftScaleFilter->SetInput( this->GetInput() );
504  shiftScaleFilter->SetShift( - m_IsoSurfaceValue );
505  // keep a handle to the shifted output
506  m_ShiftedImage = shiftScaleFilter->GetOutput();
507 
509  zeroCrossingFilter = ZeroCrossingImageFilter<OutputImageType,
510  OutputImageType>::New();
511  zeroCrossingFilter->SetInput(m_ShiftedImage);
512  zeroCrossingFilter->GraftOutput(this->GetOutput());
513  zeroCrossingFilter->SetBackgroundValue(m_ValueOne);
514  zeroCrossingFilter->SetForegroundValue(m_ValueZero);
515 
516  zeroCrossingFilter->Update();
517 
518  this->GraftOutput(zeroCrossingFilter->GetOutput());
519 }
520 
521 template<class TInputImage, class TOutputImage>
522 void
525 {
526  unsigned int i;
527 
528  if (this->GetUseImageSpacing())
529  {
530  double minSpacing = NumericTraits<double>::max();
531  for (i=0; i<ImageDimension; i++)
532  {
533  minSpacing = vnl_math_min(minSpacing,this->GetInput()->GetSpacing()[i]);
534  }
535  m_ConstantGradientValue = minSpacing;
536  }
537  else
538  {
539  m_ConstantGradientValue = 1.0;
540  }
541 
542  // Allocate the status image.
543  m_StatusImage = StatusImageType::New();
544  m_StatusImage->SetRegions(this->GetOutput()->GetRequestedRegion());
545  m_StatusImage->Allocate();
546 
547  // Initialize the status image to contain all m_StatusNull values.
549  statusIt(m_StatusImage, m_StatusImage->GetRequestedRegion());
550  for (statusIt.GoToBegin(); ! statusIt.IsAtEnd(); ++statusIt)
551  {
552  statusIt.Set( m_StatusNull );
553  }
554 
555  // Initialize the boundary pixels in the status image to
556  // m_StatusBoundaryPixel values. Uses the face calculator to find all of the
557  // region faces.
559  BFCType;
560 
561  BFCType faceCalculator;
562  typename BFCType::FaceListType faceList;
563  typename BFCType::SizeType sz;
564  typename BFCType::FaceListType::iterator fit;
565 
566  sz.Fill(1);
567  faceList = faceCalculator(m_StatusImage, m_StatusImage->GetRequestedRegion(), sz);
568  fit = faceList.begin();
569 
570  for (++fit; fit != faceList.end(); ++fit) // skip the first (nonboundary) region
571  {
572  statusIt = ImageRegionIterator<StatusImageType>(m_StatusImage, *fit);
573  for (statusIt.GoToBegin(); ! statusIt.IsAtEnd(); ++statusIt)
574  {
575  statusIt.Set( m_StatusBoundaryPixel );
576  }
577  }
578 
579  // Erase all existing layer lists.
580  for (i = 0; i < m_Layers.size(); ++i)
581  {
582  while (! m_Layers[i]->Empty() )
583  {
584  m_LayerNodeStore->Return(m_Layers[i]->Front());
585  m_Layers[i]->PopFront();
586  }
587  }
588 
589  // Allocate the layers for the sparse field.
590  m_Layers.clear();
591  m_Layers.reserve(2*m_NumberOfLayers + 1);
592 
593  while ( m_Layers.size() < (2*m_NumberOfLayers+1) )
594  {
595  m_Layers.push_back( LayerType::New() );
596  }
597 
598  // Throw an exception if we don't have enough layers.
599  if (m_Layers.size() < 3)
600  {
601  itkExceptionMacro( << "Not enough layers have been allocated for the sparse field. Requires at least one layer.");
602  }
603 
604  // Construct the active layer and initialize the first layers inside and
605  // outside of the active layer.
606  this->ConstructActiveLayer();
607 
608  // Construct the rest of the non-active set layers using the first two
609  // layers. Inside layers are odd numbers, outside layers are even numbers.
610  for (i = 1; i < m_Layers.size() - 2; ++i)
611  {
612  this->ConstructLayer(i, i+2);
613  }
614 
615  // Set the values in the output image for the active layer.
616  this->InitializeActiveLayerValues();
617 
618  // Initialize layer values using the active layer as seeds.
619  this->PropagateAllLayerValues();
620 
621  // Initialize pixels inside and outside the sparse field layers to positive
622  // and negative values, respectively. This is not necessary for the
623  // calculations, but is useful for presenting a more intuitive output to the
624  // filter. See PostProcessOutput method for more information.
625  this->InitializeBackgroundPixels();
626 }
627 
628 template <class TInputImage, class TOutputImage>
629 void
632 {
633  // Assign background pixels OUTSIDE the sparse field layers to a new level set
634  // with value greater than the outermost layer. Assign background pixels
635  // INSIDE the sparse field layers to a new level set with value less than
636  // the innermost layer.
637  const ValueType max_layer = static_cast<ValueType>(m_NumberOfLayers);
638 
639  const ValueType outside_value = (max_layer+1) * m_ConstantGradientValue;
640  const ValueType inside_value = -(max_layer+1) * m_ConstantGradientValue;
641 
642  ImageRegionConstIterator<StatusImageType> statusIt(m_StatusImage,
643  this->GetOutput()->GetRequestedRegion());
644 
645  ImageRegionIterator<OutputImageType> outputIt(this->GetOutput(),
646  this->GetOutput()->GetRequestedRegion());
647 
648  ImageRegionConstIterator<OutputImageType> shiftedIt(m_ShiftedImage,
649  this->GetOutput()->GetRequestedRegion());
650 
651  for (outputIt = outputIt.Begin(), statusIt = statusIt.Begin(),
652  shiftedIt = shiftedIt.Begin();
653  ! outputIt.IsAtEnd(); ++outputIt, ++statusIt, ++shiftedIt)
654  {
655  if (statusIt.Get() == m_StatusNull || statusIt.Get() == m_StatusBoundaryPixel)
656  {
657  if (shiftedIt.Get() > m_ValueZero)
658  {
659  outputIt.Set(outside_value);
660  }
661  else
662  {
663  outputIt.Set(inside_value);
664  }
665  }
666  }
667 
668 };
669 
670 template <class TInputImage, class TOutputImage>
671 void
674 {
675  //
676  // We find the active layer by searching for 0's in the zero crossing image
677  // (output image). The first inside and outside layers are also constructed
678  // by searching the neighbors of the active layer in the (shifted) input image.
679  // Negative neighbors not in the active set are assigned to the inside,
680  // positive neighbors are assigned to the outside.
681  //
682  // During construction we also check whether any of the layers of the active
683  // set (or the active set itself) is sitting on a boundary pixel location. If
684  // this is the case, then we need to do active bounds checking in the solver.
685  //
686 
687  unsigned int i;
689  shiftedIt(m_NeighborList.GetRadius(), m_ShiftedImage,
690  this->GetOutput()->GetRequestedRegion());
692  outputIt(m_NeighborList.GetRadius(), this->GetOutput(),
693  this->GetOutput()->GetRequestedRegion());
695  statusIt(m_NeighborList.GetRadius(), m_StatusImage,
696  this->GetOutput()->GetRequestedRegion());
697  IndexType center_index, offset_index;
698  LayerNodeType *node;
699  bool bounds_status;
700  ValueType value;
701  StatusType layer_number;
702 
703  typename OutputImageType::IndexType upperBounds, lowerBounds;
704  lowerBounds = this->GetOutput()->GetRequestedRegion().GetIndex();
705  upperBounds = this->GetOutput()->GetRequestedRegion().GetIndex()
706  + this->GetOutput()->GetRequestedRegion().GetSize();
707 
708  for (outputIt.GoToBegin(); !outputIt.IsAtEnd(); ++outputIt)
709  {
710  if ( outputIt.GetCenterPixel() == m_ValueZero )
711  {
712  // Grab the neighborhood in the status image.
713  center_index = outputIt.GetIndex();
714  statusIt.SetLocation( center_index );
715 
716  // Check to see if any of the sparse field touches a boundary. If so,
717  // then activate bounds checking.
718  for (i = 0; i < ImageDimension; i++)
719  {
720  if (center_index[i] + static_cast<long>(m_NumberOfLayers) >= (upperBounds[i] - 1)
721  || center_index[i] - static_cast<long>(m_NumberOfLayers) <= lowerBounds[i])
722  {
723  m_BoundsCheckingActive = true;
724  }
725  }
726 
727  // Borrow a node from the store and set its value.
728  node = m_LayerNodeStore->Borrow();
729  node->m_Value = center_index;
730 
731  // Add the node to the active list and set the status in the status
732  // image.
733  m_Layers[0]->PushFront( node );
734  statusIt.SetCenterPixel( 0 );
735 
736  // Grab the neighborhood in the image of shifted input values.
737  shiftedIt.SetLocation( center_index );
738 
739  // Search the neighborhood pixels for first inside & outside layer
740  // members. Construct these lists and set status list values.
741  for (i = 0; i < m_NeighborList.GetSize(); ++i)
742  {
743  offset_index = center_index
744  + m_NeighborList.GetNeighborhoodOffset(i);
745 
746  if ( outputIt.GetPixel(m_NeighborList.GetArrayIndex(i)) != m_ValueZero)
747  {
748  value = shiftedIt.GetPixel(m_NeighborList.GetArrayIndex(i));
749 
750  if ( value < m_ValueZero ) // Assign to first inside layer.
751  {
752  layer_number = 1;
753  }
754  else // Assign to first outside layer
755  {
756  layer_number = 2;
757  }
758 
759  statusIt.SetPixel( m_NeighborList.GetArrayIndex(i),
760  layer_number, bounds_status );
761  if ( bounds_status == true ) // In bounds.
762  {
763  node = m_LayerNodeStore->Borrow();
764  node->m_Value = offset_index;
765  m_Layers[layer_number]->PushFront( node );
766  } // else do nothing.
767  }
768  }
769  }
770  }
771 }
772 
773 template<class TInputImage, class TOutputImage>
774 void
777 {
778  unsigned int i;
779  LayerNodeType *node;
780  bool boundary_status;
781  typename LayerType::ConstIterator fromIt;
783  statusIt(m_NeighborList.GetRadius(), m_StatusImage,
784  this->GetOutput()->GetRequestedRegion() );
785 
786  // For all indicies in the "from" layer...
787  for (fromIt = m_Layers[from]->Begin();
788  fromIt != m_Layers[from]->End(); ++fromIt)
789  {
790  // Search the neighborhood of this index in the status image for
791  // unassigned indicies. Push those indicies onto the "to" layer and
792  // assign them values in the status image. Status pixels outside the
793  // boundary will be ignored.
794  statusIt.SetLocation( fromIt->m_Value );
795  for (i = 0; i < m_NeighborList.GetSize(); ++i)
796  {
797  if ( statusIt.GetPixel( m_NeighborList.GetArrayIndex(i) )
798  == m_StatusNull )
799  {
800  statusIt.SetPixel(m_NeighborList.GetArrayIndex(i), to,
801  boundary_status);
802  if (boundary_status == true) // in bounds
803  {
804  node = m_LayerNodeStore->Borrow();
805  node->m_Value = statusIt.GetIndex()
806  + m_NeighborList.GetNeighborhoodOffset(i);
807  m_Layers[to]->PushFront( node );
808  }
809  }
810  }
811  }
812 }
813 
814 template <class TInputImage, class TOutputImage>
815 void
818 {
819  const ValueType CHANGE_FACTOR = m_ConstantGradientValue / 2.0;
820  ValueType MIN_NORM = 1.0e-6;
821  if (this->GetUseImageSpacing())
822  {
823  double minSpacing = NumericTraits<double>::max();
824  for (unsigned int i=0; i<ImageDimension; i++)
825  {
826  minSpacing = vnl_math_min(minSpacing,this->GetInput()->GetSpacing()[i]);
827  }
828  MIN_NORM *= minSpacing;
829  }
830 
831  unsigned int i, center;
832 
833  typename LayerType::ConstIterator activeIt;
835  shiftedIt( m_NeighborList.GetRadius(), m_ShiftedImage,
836  this->GetOutput()->GetRequestedRegion() );
837 
838  center = shiftedIt.Size() /2;
839  typename OutputImageType::Pointer output = this->GetOutput();
840 
841  const NeighborhoodScalesType neighborhoodScales = this->GetDifferenceFunction()->ComputeNeighborhoodScales();
842 
843  ValueType dx_forward, dx_backward, length, distance;
844 
845  // For all indicies in the active layer...
846  for (activeIt = m_Layers[0]->Begin();
847  activeIt != m_Layers[0]->End(); ++activeIt)
848  {
849  // Interpolate on the (shifted) input image values at this index to
850  // assign an active layer value in the output image.
851  shiftedIt.SetLocation( activeIt->m_Value );
852 
853  length = m_ValueZero;
854  for (i = 0; i < ImageDimension; ++i)
855  {
856  dx_forward = ( shiftedIt.GetPixel(center + m_NeighborList.GetStride(i))
857  - shiftedIt.GetCenterPixel() ) * neighborhoodScales[i];
858  dx_backward = ( shiftedIt.GetCenterPixel()
859  - shiftedIt.GetPixel(center - m_NeighborList.GetStride(i)) ) * neighborhoodScales[i];
860 
861  if ( vnl_math_abs(dx_forward) > vnl_math_abs(dx_backward) )
862  {
863  length += dx_forward * dx_forward;
864  }
865  else
866  {
867  length += dx_backward * dx_backward;
868  }
869  }
870  length = vcl_sqrt((double)length) + MIN_NORM;
871  distance = shiftedIt.GetCenterPixel() / length;
872 
873  output->SetPixel( activeIt->m_Value ,
874  vnl_math_min(vnl_math_max(-CHANGE_FACTOR, distance), CHANGE_FACTOR) );
875  }
876 
877 }
878 
879 template <class TInputImage, class TOutputImage>
880 void
883 {
884  // Preallocate the update buffer. NOTE: There is currently no way to
885  // downsize a std::vector. This means that the update buffer will grow
886  // dynamically but not shrink. In newer implementations there may be a
887  // squeeze method which can do this. Alternately, we can implement our own
888  // strategy for downsizing.
889  m_UpdateBuffer.clear();
890  m_UpdateBuffer.reserve(m_Layers[0]->Size());
891 }
892 
893 
894 template <class TInputImage, class TOutputImage>
895 typename
899 {
901  = this->GetDifferenceFunction();
902  typename Superclass::FiniteDifferenceFunctionType::FloatOffsetType offset;
903  ValueType norm_grad_phi_squared, dx_forward, dx_backward, forwardValue,
904  backwardValue, centerValue;
905  unsigned i;
906  ValueType MIN_NORM = 1.0e-6;
907  if (this->GetUseImageSpacing())
908  {
909  double minSpacing = NumericTraits<double>::max();
910  for (i=0; i<ImageDimension; i++)
911  {
912  minSpacing = vnl_math_min(minSpacing,this->GetInput()->GetSpacing()[i]);
913  }
914  MIN_NORM *= minSpacing;
915  }
916 
917  void *globalData = df->GetGlobalDataPointer();
918 
919  typename LayerType::ConstIterator layerIt;
920  NeighborhoodIterator<OutputImageType> outputIt(df->GetRadius(),
921  this->GetOutput(), this->GetOutput()->GetRequestedRegion());
922  TimeStepType timeStep;
923 
924  const NeighborhoodScalesType neighborhoodScales = this->GetDifferenceFunction()->ComputeNeighborhoodScales();
925 
926  if ( m_BoundsCheckingActive == false )
927  {
928  outputIt.NeedToUseBoundaryConditionOff();
929  }
930 
931  m_UpdateBuffer.clear();
932  m_UpdateBuffer.reserve(m_Layers[0]->Size());
933 
934  // Calculates the update values for the active layer indicies in this
935  // iteration. Iterates through the active layer index list, applying
936  // the level set function to the output image (level set image) at each
937  // index. Update values are stored in the update buffer.
938  for (layerIt = m_Layers[0]->Begin(); layerIt != m_Layers[0]->End(); ++layerIt)
939  {
940  outputIt.SetLocation(layerIt->m_Value);
941 
942  // Calculate the offset to the surface from the center of this
943  // neighborhood. This is used by some level set functions in sampling a
944  // speed, advection, or curvature term.
945  if (this->GetInterpolateSurfaceLocation()
946  && (centerValue = outputIt.GetCenterPixel()) != 0.0 )
947  {
948  // Surface is at the zero crossing, so distance to surface is:
949  // phi(x) / norm(grad(phi)), where phi(x) is the center of the
950  // neighborhood. The location is therefore
951  // (i,j,k) - ( phi(x) * grad(phi(x)) ) / norm(grad(phi))^2
952  norm_grad_phi_squared = 0.0;
953  for (i = 0; i < ImageDimension; ++i)
954  {
955  forwardValue = outputIt.GetNext(i);
956  backwardValue = outputIt.GetPrevious(i);
957 
958  if (forwardValue * backwardValue >= 0)
959  { // Neighbors are same sign OR at least one neighbor is zero.
960  dx_forward = forwardValue - centerValue;
961  dx_backward = centerValue - backwardValue;
962 
963  // Pick the larger magnitude derivative.
964  if (::vnl_math_abs(dx_forward) > ::vnl_math_abs(dx_backward) )
965  {
966  offset[i] = dx_forward;
967  }
968  else
969  {
970  offset[i] = dx_backward;
971  }
972  }
973  else //Neighbors are opposite sign, pick the direction of the 0 surface.
974  {
975  if (forwardValue * centerValue < 0)
976  {
977  offset[i] = forwardValue - centerValue;
978  }
979  else
980  {
981  offset[i] = centerValue - backwardValue;
982  }
983  }
984 
985  norm_grad_phi_squared += offset[i] * offset[i];
986  }
987 
988  for (i = 0; i < ImageDimension; ++i)
989  {
990 #if defined(ITK_USE_DEPRECATED_LEVELSET_INTERPOLATION)
991  offset[i] = (offset[i] * centerValue) * vcl_sqrt(ImageDimension +0.5)
992  / (norm_grad_phi_squared + MIN_NORM);
993 #else
994  offset[i] = (offset[i] * centerValue) / (norm_grad_phi_squared + MIN_NORM);
995 #endif
996  }
997 
998  m_UpdateBuffer.push_back( df->ComputeUpdate(outputIt, globalData, offset) );
999  }
1000  else // Don't do interpolation
1001  {
1002  m_UpdateBuffer.push_back( df->ComputeUpdate(outputIt, globalData) );
1003  }
1004  }
1005 
1006  // Ask the finite difference function to compute the time step for
1007  // this iteration. We give it the global data pointer to use, then
1008  // ask it to free the global data memory.
1009  timeStep = df->ComputeGlobalTimeStep(globalData);
1010 
1011  df->ReleaseGlobalDataPointer(globalData);
1012 
1013  return timeStep;
1014 }
1015 
1016 
1017 template <class TInputImage, class TOutputImage>
1018 void
1021 {
1022  unsigned int i;
1023 
1024  // Update values in the first inside and first outside layers using the
1025  // active layer as a seed. Inside layers are odd numbers, outside layers are
1026  // even numbers.
1027  this->PropagateLayerValues(0, 1, 3, 1); // first inside
1028  this->PropagateLayerValues(0, 2, 4, 2); // first outside
1029 
1030  // Update the rest of the layers.
1031  for (i = 1; i < m_Layers.size() - 2; ++i)
1032  {
1033  this->PropagateLayerValues(i, i+2, i+4, (i+2)%2);
1034  }
1035 }
1036 
1037 template <class TInputImage, class TOutputImage>
1038 void
1041  StatusType promote, int InOrOut)
1042 {
1043  unsigned int i;
1044  ValueType value, value_temp, delta;
1045  value = NumericTraits<ValueType>::Zero; // warnings
1046  bool found_neighbor_flag;
1047  typename LayerType::Iterator toIt;
1048  LayerNodeType *node;
1049  StatusType past_end = static_cast<StatusType>( m_Layers.size() ) - 1;
1050 
1051  // Are we propagating values inward (more negative) or outward (more
1052  // positive)?
1053  if (InOrOut == 1) delta = - m_ConstantGradientValue;
1054  else delta = m_ConstantGradientValue;
1055 
1057  outputIt(m_NeighborList.GetRadius(), this->GetOutput(),
1058  this->GetOutput()->GetRequestedRegion() );
1060  statusIt(m_NeighborList.GetRadius(), m_StatusImage,
1061  this->GetOutput()->GetRequestedRegion() );
1062 
1063  if ( m_BoundsCheckingActive == false )
1064  {
1065  outputIt.NeedToUseBoundaryConditionOff();
1066  statusIt.NeedToUseBoundaryConditionOff();
1067  }
1068 
1069  toIt = m_Layers[to]->Begin();
1070  while ( toIt != m_Layers[to]->End() )
1071  {
1072  statusIt.SetLocation( toIt->m_Value );
1073 
1074  // Is this index marked for deletion? If the status image has
1075  // been marked with another layer's value, we need to delete this node
1076  // from the current list then skip to the next iteration.
1077  if (statusIt.GetCenterPixel() != to)
1078  {
1079  node = toIt.GetPointer();
1080  ++toIt;
1081  m_Layers[to]->Unlink( node );
1082  m_LayerNodeStore->Return( node );
1083  continue;
1084  }
1085 
1086  outputIt.SetLocation( toIt->m_Value );
1087 
1088  found_neighbor_flag = false;
1089  for (i = 0; i < m_NeighborList.GetSize(); ++i)
1090  {
1091  // If this neighbor is in the "from" list, compare its absolute value
1092  // to to any previous values found in the "from" list. Keep the value
1093  // that will cause the next layer to be closest to the zero level set.
1094  if ( statusIt.GetPixel( m_NeighborList.GetArrayIndex(i) ) == from )
1095  {
1096  value_temp = outputIt.GetPixel( m_NeighborList.GetArrayIndex(i) );
1097 
1098  if (found_neighbor_flag == false)
1099  {
1100  value = value_temp;
1101  }
1102  else
1103  {
1104  if (InOrOut == 1)
1105  {
1106  // Find the largest (least negative) neighbor
1107  if ( value_temp > value )
1108  {
1109  value = value_temp;
1110  }
1111  }
1112  else
1113  {
1114  // Find the smallest (least positive) neighbor
1115  if (value_temp < value)
1116  {
1117  value = value_temp;
1118  }
1119  }
1120  }
1121  found_neighbor_flag = true;
1122  }
1123  }
1124  if (found_neighbor_flag == true)
1125  {
1126  // Set the new value using the smallest distance
1127  // found in our "from" neighbors.
1128  outputIt.SetCenterPixel( value + delta );
1129  ++toIt;
1130  }
1131  else
1132  {
1133  // Did not find any neighbors on the "from" list, then promote this
1134  // node. A "promote" value past the end of my sparse field size
1135  // means delete the node instead. Change the status value in the
1136  // status image accordingly.
1137  node = toIt.GetPointer();
1138  ++toIt;
1139  m_Layers[to]->Unlink( node );
1140  if ( promote > past_end )
1141  {
1142  m_LayerNodeStore->Return( node );
1143  statusIt.SetCenterPixel(m_StatusNull);
1144  }
1145  else
1146  {
1147  m_Layers[promote]->PushFront( node );
1148  statusIt.SetCenterPixel(promote);
1149  }
1150  }
1151  }
1152 }
1153 
1154 
1155 template<class TInputImage, class TOutputImage>
1156 void
1159 {
1160  // Assign background pixels INSIDE the sparse field layers to a new level set
1161  // with value less than the innermost layer. Assign background pixels
1162  // OUTSIDE the sparse field layers to a new level set with value greater than
1163  // the outermost layer.
1164  const ValueType max_layer = static_cast<ValueType>(m_NumberOfLayers);
1165 
1166  const ValueType inside_value = (max_layer+1) * m_ConstantGradientValue;
1167  const ValueType outside_value = -(max_layer+1) * m_ConstantGradientValue;
1168 
1169  ImageRegionConstIterator<StatusImageType> statusIt(m_StatusImage,
1170  this->GetOutput()->GetRequestedRegion());
1171 
1172  ImageRegionIterator<OutputImageType> outputIt(this->GetOutput(),
1173  this->GetOutput()->GetRequestedRegion());
1174 
1175  for (outputIt = outputIt.Begin(), statusIt = statusIt.Begin();
1176  ! outputIt.IsAtEnd(); ++outputIt, ++statusIt)
1177  {
1178  if (statusIt.Get() == m_StatusNull)
1179  {
1180  if (outputIt.Get() > m_ValueZero)
1181  {
1182  outputIt.Set(inside_value);
1183  }
1184  else
1185  {
1186  outputIt.Set(outside_value);
1187  }
1188  }
1189  }
1190 }
1191 
1192 template<class TInputImage, class TOutputImage>
1193 void
1195 ::PrintSelf(std::ostream& os, Indent indent) const
1196 {
1197  Superclass::PrintSelf(os, indent);
1198 
1199  unsigned int i;
1200  os << indent << "m_IsoSurfaceValue: " << m_IsoSurfaceValue << std::endl;
1201  os << indent << "m_LayerNodeStore: " << std::endl;
1202  m_LayerNodeStore->Print(os,indent.GetNextIndent());
1203  os << indent << "m_BoundsCheckingActive: " << m_BoundsCheckingActive;
1204  for (i=0; i < m_Layers.size(); i++)
1205  {
1206  os << indent << "m_Layers[" << i << "]: size="
1207  << m_Layers[i]->Size() << std::endl;
1208  os << indent << m_Layers[i];
1209  }
1210  os << indent << "m_UpdateBuffer: size=" << static_cast<unsigned long>(m_UpdateBuffer.size())
1211  << " capacity=" << static_cast<unsigned long>( m_UpdateBuffer.capacity()) << std::endl;
1212 }
1213 
1214 } // end namespace itk
1215 
1216 #endif

Generated at Sun Feb 3 2013 00:08:06 for Orfeo Toolbox with doxygen 1.8.1.1