Orfeo Toolbox  3.16
itkValuedRegionalExtremaImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkValuedRegionalExtremaImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2007-01-30 14:03:55 $
7  Version: $Revision: 1.5 $
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 __itkValuedRegionalExtremaImageFilter_txx
19 #define __itkValuedRegionalExtremaImageFilter_txx
20 
22 #include "itkImageRegionIterator.h"
23 #include "itkNumericTraits.h"
25 #include "itkProgressReporter.h"
26 #include "itkConnectedComponentAlgorithm.h"
27 
28 namespace itk {
29 
30 template <class TInputImage, class TOutputImage, class TFunction1,
31  class TFunction2>
32 ValuedRegionalExtremaImageFilter<TInputImage, TOutputImage, TFunction1,
33  TFunction2>
35 {
36  m_FullyConnected = false;
37 
38  // not really useful, just to always have the same value before
39  //the filter has run
40  m_Flat = false;
41 
42 }
43 
44 template <class TInputImage, class TOutputImage, class TFunction1,
45  class TFunction2>
46 void
47 ValuedRegionalExtremaImageFilter<TInputImage, TOutputImage, TFunction1,
48  TFunction2>
49 ::GenerateInputRequestedRegion()
50 {
51  // call the superclass' implementation of this method
52  Superclass::GenerateInputRequestedRegion();
53 
54  // We need all the input.
55  InputImagePointer input = const_cast<InputImageType *>(this->GetInput());
56  if( !input )
57  {
58  return;
59  }
60 
61  input->SetRequestedRegion( input->GetLargestPossibleRegion() );
62 }
63 
64 
65 template <class TInputImage, class TOutputImage, class TFunction1,
66  class TFunction2>
67 void
68 ValuedRegionalExtremaImageFilter<TInputImage, TOutputImage, TFunction1,
69  TFunction2>
70 ::EnlargeOutputRequestedRegion(DataObject *)
71 {
72  this->GetOutput()
73  ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() );
74 }
75 
76 
77 template<class TInputImage, class TOutputImage, class TFunction1,
78  class TFunction2>
79 void
80 ValuedRegionalExtremaImageFilter<TInputImage, TOutputImage, TFunction1,
81  TFunction2>
82 ::GenerateData()
83 {
84  // Allocate the output
85  this->AllocateOutputs();
86 
87  // 2 phases
88  ProgressReporter progress(this, 0,
89  this->GetOutput()->GetRequestedRegion().GetNumberOfPixels()*2);
90 
91  // copy input to output - isn't there a better way?
92  typedef ImageRegionConstIterator<TInputImage> InputIterator;
93  typedef ImageRegionIterator<TOutputImage> OutputIterator;
94 
95  InputIterator inIt( this->GetInput(),
96  this->GetOutput()->GetRequestedRegion() );
97  OutputIterator outIt( this->GetOutput(),
98  this->GetOutput()->GetRequestedRegion() );
99  inIt = inIt.Begin();
100  outIt = outIt.Begin();
101 
102  InputImagePixelType firstValue = inIt.Get();
103  this->m_Flat = true;
104 
105  while ( !outIt.IsAtEnd() )
106  {
107  InputImagePixelType currentValue = inIt.Get();
108  outIt.Set( static_cast<OutputImagePixelType>( currentValue ) );
109  if( currentValue != firstValue )
110  {
111  this->m_Flat = false;
112  }
113  ++inIt;
114  ++outIt;
115  progress.CompletedPixel();
116  }
117 
118  // if the image is flat, there is no need to do the work:
119  // the image will be unchanged
120  if( !this->m_Flat )
121  {
122  // Now for the real work!
123  // More iterators - use shaped ones so that we can set connectivity
124  // Note : all comments refer to finding regional minima, because
125  // it is briefer and clearer than trying to describe both regional
126  // maxima and minima processes at the same time
127  ISizeType kernelRadius;
128  kernelRadius.Fill(1);
129  NOutputIterator outNIt(kernelRadius,
130  this->GetOutput(),
131  this->GetOutput()->GetRequestedRegion() );
132  setConnectivity( &outNIt, m_FullyConnected );
133 
134  ConstInputIterator inNIt(kernelRadius,
135  this->GetInput(),
136  this->GetOutput()->GetRequestedRegion() );
137  setConnectivity( &inNIt, m_FullyConnected );
138 
140  iBC.SetConstant(m_MarkerValue);
141  inNIt.OverrideBoundaryCondition(&iBC);
142 
144  oBC.SetConstant(m_MarkerValue);
145  outNIt.OverrideBoundaryCondition(&oBC);
146 
147  TFunction1 compareIn;
148  TFunction2 compareOut;
149 
150  outIt = outIt.Begin();
151  // set up the stack and neighbor list
152  IndexStack IS;
153  typename NOutputIterator::IndexListType IndexList;
154  IndexList = outNIt.GetActiveIndexList();
155 
156  while ( !outIt.IsAtEnd() )
157  {
158  OutputImagePixelType V = outIt.Get();
159  // if the output pixel value = the marker value then we have
160  // already visited this pixel and don't need to do so again
161  if (compareOut(V, m_MarkerValue))
162  {
163  // reposition the input iterator
164  inNIt += outIt.GetIndex() - inNIt.GetIndex();
165 
166  InputImagePixelType Cent = static_cast<InputImagePixelType>(V);
167 
168  // check each neighbor of the input pixel
170  for (sIt = inNIt.Begin(); !sIt.IsAtEnd(); ++sIt)
171  {
172  InputImagePixelType Adjacent = sIt.Get();
173  if (compareIn(Adjacent, Cent))
174  {
175  // The centre pixel cannot be part of a regional minima
176  // because one of its neighbors is smaller.
177  // Set all pixels in the output image that are connected to
178  // the centre pixel and have the same value to
179  // m_MarkerValue
180  // This is the flood filling step. It is a simple, stack
181  // based, procedure. The original value (V) of the pixel is
182  // recorded and the pixel index in the output image
183  // is set to the marker value. The stack is initialized
184  // with the pixel index. The flooding procedure pops the
185  // stack, sets that index to the marker value and places the
186  // indexes of all neighbors with value V on the stack. The
187  // process terminates when the stack is empty.
188 
189  outNIt += outIt.GetIndex() - outNIt.GetIndex();
190 
192  OutIndexType idx;
193  // Initialize the stack
194  IS.push(outNIt.GetIndex());
195  outNIt.SetCenterPixel(m_MarkerValue);
196 
197  typename NOutputIterator::IndexListType::const_iterator LIt;
198 
199  while (!IS.empty())
200  {
201  // Pop the stack
202  idx = IS.top();
203  IS.pop();
204  // position the iterator
205  outNIt += idx - outNIt.GetIndex();
206  // check neighbors
207  for (LIt = IndexList.begin(); LIt != IndexList.end(); ++LIt)
208  {
209  NVal = outNIt.GetPixel(*LIt);
210  if (NVal == V)
211  {
212  // still in a flat zone
213  IS.push(outNIt.GetIndex(*LIt));
214 
215  // set the output as the marker value
216  outNIt.SetPixel(*LIt, m_MarkerValue);
217  }
218  }
219  }
220  // end flooding
221  break;
222  }
223  }
224  }
225  ++outIt;
226  progress.CompletedPixel();
227  }
228  }
229 
230 }
231 
232 template<class TInputImage, class TOutputImage, class TFunction1,
233  class TFunction2>
234 void
235 ValuedRegionalExtremaImageFilter<TInputImage, TOutputImage, TFunction1,
236  TFunction2>
237 ::PrintSelf(std::ostream &os, Indent indent) const
238 {
239  Superclass::PrintSelf(os, indent);
240 
241  os << indent << "FullyConnected: " << m_FullyConnected << std::endl;
242  os << indent << "Flat: " << m_Flat << std::endl;
243  os << indent << "MarkerValue: " << m_MarkerValue << std::endl;
244 }
245 
246 } // end namespace itk
247 
248 #endif

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