Orfeo Toolbox  3.16
itkLabelMapMaskImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkLabelMapMaskImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2005/08/23 15:09:03 $
7  Version: $Revision: 1.6 $
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 __itkLabelMapMaskImageFilter_txx
18 #define __itkLabelMapMaskImageFilter_txx
19 
21 #include "itkNumericTraits.h"
22 #include "itkProgressReporter.h"
24 #include "itkImageRegionIterator.h"
25 
26 namespace itk {
27 
28 template <class TInputImage, class TOutputImage>
31 {
32  this->SetNumberOfRequiredInputs(2);
33  m_Label = NumericTraits< InputImagePixelType >::One;
34  m_BackgroundValue = NumericTraits< OutputImagePixelType >::Zero;
35  m_Negated = false;
36  m_Crop = false;
37  m_CropBorder.Fill( 0 );
38 }
39 
40 template <class TInputImage, class TOutputImage>
41 void
44 {
45  // call the superclass' implementation of this method
46  Superclass::GenerateInputRequestedRegion();
47 
48  // We need all the input.
49  InputImagePointer input = const_cast<InputImageType *>(this->GetInput());
50  if ( !input )
51  { return; }
52  input->SetRequestedRegion( input->GetLargestPossibleRegion() );
53 }
54 
55 template <class TInputImage, class TOutputImage>
56 void
59 {
60 
61  if( m_Crop )
62  {
63  const InputImageType * input = this->GetInput();
64 
65  if( !(input->GetMTime() > m_CropTimeStamp) && !(this->GetMTime() > m_CropTimeStamp) )
66  {
67  // early exit, crop sizes already computed
68  // std::cout << "Don't recompute the output size again." << std::endl;
69  // std::cout << "LargestPossibleRegion: " << this->GetOutput()->GetLargestPossibleRegion() << std::endl;
70  // std::cout << "BufferedRegion: " << this->GetOutput()->GetBufferedRegion() << std::endl;
71  // std::cout << "RequestedRegion: " << this->GetOutput()->GetRequestedRegion() << std::endl;
72  return;
73  }
74 
75  // first, call the default implementation, to be sure to forgot nothing
76  Superclass::GenerateOutputInformation();
77 
78  // update the input if needed
79  if( input->GetSource())
80  {
81  ProcessObject * upstream = input->GetSource();
82  if (upstream)
83  {
84  // this->SetInput(NULL);
85  // std::cout << "Update the input (again?)." << std::endl;
86  upstream->Update();
87  // this->SetInput(input);
88  }
89  }
90 
91  // Prefetch image region and size
92  InputImageRegionType cropRegion = input->GetLargestPossibleRegion();
93 
94  // now the output image size can be computed
95  if( m_Negated )
96  {
97  if( input->GetBackgroundValue() != m_Label )
98  {
99  // the "bad" case - the zone outside the object is at least partially
100  // covered by the background, which is not explicitely defined.
101 
102  // simply do nothing for now
103  // TODO: implement that part
104  itkWarningMacro( << "Cropping according to background label is no yet implemented. The full image will be used." );
105 
106  }
107  else
108  {
109  // compute the bounding box of all the objects which don't have that label
110  IndexType mins;
111  mins.Fill( NumericTraits< long >::max() );
112  IndexType maxs;
113  maxs.Fill( NumericTraits< long >::NonpositiveMin() );
114  typename InputImageType::LabelObjectContainerType container = this->GetInput()->GetLabelObjectContainer();
115  for( typename InputImageType::LabelObjectContainerType::const_iterator loit = container.begin();
116  loit != container.end();
117  loit++ )
118  {
119  if( loit->first != m_Label )
120  {
121  typename LabelObjectType::LineContainerType::const_iterator lit;
122  typename LabelObjectType::LineContainerType & lineContainer = loit->second->GetLineContainer();
123  // iterate over all the lines
124  for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ )
125  {
126  const IndexType & idx = lit->GetIndex();
127  unsigned long length = lit->GetLength();
128 
129  // update the mins and maxs
130  for( int i=0; i<ImageDimension; i++)
131  {
132  if( idx[i] < mins[i] )
133  {
134  mins[i] = idx[i];
135  }
136  if( idx[i] > maxs[i] )
137  {
138  maxs[i] = idx[i];
139  }
140  }
141  // must fix the max for the axis 0
142  if( idx[0] + (long)length > maxs[0] )
143  {
144  maxs[0] = idx[0] + length - 1;
145  }
146  }
147  }
148  }
149 
150  // final computation
151  SizeType regionSize;
152  for( int i=0; i<ImageDimension; i++ )
153  {
154  regionSize[i] = maxs[i] - mins[i] + 1;
155  }
156  cropRegion.SetIndex( mins );
157  cropRegion.SetSize( regionSize );
158 
159  }
160  }
161  else
162  {
163  if( input->GetBackgroundValue() == m_Label )
164  {
165  // the other "bad" case - the label we want is not defined as a label object,
166  // but implicitely, in the zones not defined.
167 
168  // simply do nothing for now
169  // TODO: implement that part
170  itkWarningMacro( << "Cropping according to background label is no yet implemented. The full image will be used." );
171 
172  }
173  else
174  {
175  // just find the bounding box of the object with that label
176 
177  const LabelObjectType * labelObject = input->GetLabelObject( m_Label );
178  typename LabelObjectType::LineContainerType::const_iterator lit;
179  const typename LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer();
180  IndexType mins;
181  mins.Fill( NumericTraits< long >::max() );
182  IndexType maxs;
183  maxs.Fill( NumericTraits< long >::NonpositiveMin() );
184  // iterate over all the lines
185  for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ )
186  {
187  const IndexType & idx = lit->GetIndex();
188  unsigned long length = lit->GetLength();
189 
190  // update the mins and maxs
191  for( int i=0; i<ImageDimension; i++)
192  {
193  if( idx[i] < mins[i] )
194  {
195  mins[i] = idx[i];
196  }
197  if( idx[i] > maxs[i] )
198  {
199  maxs[i] = idx[i];
200  }
201  }
202  // must fix the max for the axis 0
203  if( idx[0] + (long)length > maxs[0] )
204  {
205  maxs[0] = idx[0] + length - 1;
206  }
207  }
208  // final computation
209  SizeType regionSize;
210  for( int i=0; i<ImageDimension; i++ )
211  {
212  regionSize[i] = maxs[i] - mins[i] + 1;
213  }
214  cropRegion.SetIndex( mins );
215  cropRegion.SetSize( regionSize );
216 
217  }
218  }
219 
220  // pad by the crop border, but take care to not be larger than the largest
221  // possible region of the input image
222  cropRegion.PadByRadius( m_CropBorder );
223  cropRegion.Crop( input->GetLargestPossibleRegion() );
224 
225  // finally set that region as the largest output region
226  this->GetOutput()->SetLargestPossibleRegion( cropRegion );
227 
228  m_CropTimeStamp.Modified();
229 
230  }
231  else
232  {
233  // no crop -> use the default implementation
234  Superclass::GenerateOutputInformation();
235  }
236 
237  // std::cout << "LargestPossibleRegion: " << this->GetOutput()->GetLargestPossibleRegion() << std::endl;
238  // std::cout << "BufferedRegion: " << this->GetOutput()->GetBufferedRegion() << std::endl;
239  // std::cout << "RequestedRegion: " << this->GetOutput()->GetRequestedRegion() << std::endl;
240 
241 }
242 
243 template <class TInputImage, class TOutputImage>
244 void
247 {
248  this->GetOutput()
249  ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() );
250 }
251 
252 
253 template <class TInputImage, class TOutputImage>
254 void
257 {
258  m_Barrier = Barrier::New();
259  m_Barrier->Initialize( this->GetNumberOfThreads() );
260 
261  Superclass::BeforeThreadedGenerateData();
262 
263 }
264 
265 
266 template <class TInputImage, class TOutputImage>
267 void
269 ::ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread, int threadId )
270 {
271  OutputImageType * output = this->GetOutput();
272  InputImageType * input = const_cast<InputImageType *>(this->GetInput());
273  const OutputImageType * input2 = this->GetFeatureImage();
274 
275  // we will keep the values from the feature image if the same pixel in the label image
276  // equals the label given by the user. The other pixels are set to the background value.
277  if( ( input->GetBackgroundValue() == m_Label ) ^ m_Negated )
278  {
279  // the user want the mask to be the background of the label collection image
280  // copy the feature image to the output image
281  ImageRegionConstIterator< OutputImageType > featureIt( input2, outputRegionForThread );
282  ImageRegionIterator< OutputImageType > outputIt( output, outputRegionForThread );
283 
284  for ( featureIt.GoToBegin(), outputIt.GoToBegin();
285  !featureIt.IsAtEnd();
286  ++featureIt, ++outputIt )
287  {
288  outputIt.Set( featureIt.Get() );
289  }
290  }
291  else
292  {
293  ImageRegionIterator< OutputImageType > outputIt( output, outputRegionForThread );
294 
295  for ( outputIt.GoToBegin(); !outputIt.IsAtEnd(); ++outputIt )
296  {
297  outputIt.Set( m_BackgroundValue );
298  }
299  }
300 
301  // wait for the other threads to complete that part
302  m_Barrier->Wait();
303 
304  if( input->GetBackgroundValue() == m_Label )
305  {
306  // and delegate to the superclass implementation to use the thread support for the label objects
307  Superclass::ThreadedGenerateData( outputRegionForThread, threadId );
308  }
309  else
310  {
311  // need only one thread - take the first one
312  if( threadId == 0 )
313  {
314  const LabelObjectType * labelObject = this->GetLabelMap()->GetLabelObject( m_Label );
315  ProgressReporter progress( this, 0, labelObject->GetLineContainer().size() );
316 
317  if( !m_Negated )
318  {
319  typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit;
320  const typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer();
321 
322  for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ )
323  {
324  IndexType idx = lit->GetIndex();
325  unsigned long length = lit->GetLength();
326  for( unsigned int i=0; i<length; i++)
327  {
328  output->SetPixel( idx, input2->GetPixel( idx ) );
329  idx[0]++;
330  }
331  progress.CompletedPixel();
332  }
333  }
334  else
335  {
336  // and mark the label object as background
337 
338  // should we take care to not write outside the image ?
339  bool testIdxIsInside = m_Crop && ( input->GetBackgroundValue() == m_Label ) ^ m_Negated;
340  RegionType outputRegion = output->GetLargestPossibleRegion();
341 
342  typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit;
343  const typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer();
344 
345  for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ )
346  {
347  IndexType idx = lit->GetIndex();
348  unsigned long length = lit->GetLength();
349  for( unsigned int i=0; i<length; i++)
350  {
351  if( !testIdxIsInside || outputRegion.IsInside( idx ) )
352  {
353  output->SetPixel( idx, m_BackgroundValue );
354  }
355  idx[0]++;
356  }
357  progress.CompletedPixel();
358  }
359  }
360 
361  }
362  }
363 }
364 
365 
366 template<class TInputImage, class TOutputImage>
367 void
370 {
371  OutputImageType * output = this->GetOutput();
372  InputImageType * input = const_cast<InputImageType *>(this->GetInput());
373  const OutputImageType * input2 = this->GetFeatureImage();
374 
375  if( !m_Negated )
376  {
377  // we will keep the values from the feature image if the same pixel in the label image
378  // equals the label given by the user. The other pixels are set to the background value.
379 
380  // should we take care to not write outside the image ?
381  bool testIdxIsInside = m_Crop && ( input->GetBackgroundValue() == m_Label ) ^ m_Negated;
382  RegionType outputRegion = output->GetLargestPossibleRegion();
383 
384  // the user want the mask to be the background of the label collection image
385  typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit;
386  typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer();
387 
388  for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ )
389  {
390  IndexType idx = lit->GetIndex();
391  unsigned long length = lit->GetLength();
392  for( unsigned int i=0; i<length; i++)
393  {
394  if( !testIdxIsInside || outputRegion.IsInside( idx ) )
395  {
396  output->SetPixel( idx, m_BackgroundValue );
397  }
398  idx[0]++;
399  }
400  }
401  }
402  else
403  {
404  // we will keep the pixels from the feature image if the same pixel from the label image
405  // is not equal to the label provided by the user. The pixels with the label provided by the
406  // user are set to the background value
407 
408  // and copy the feature image where the label objects are
409  typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit;
410  typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer();
411 
412  for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ )
413  {
414  IndexType idx = lit->GetIndex();
415  unsigned long length = lit->GetLength();
416  for( unsigned int i=0; i<length; i++)
417  {
418  output->SetPixel( idx, input2->GetPixel( idx ) );
419  idx[0]++;
420  }
421  }
422  }
423 }
424 
425 
426 template<class TInputImage, class TOutputImage>
427 void
429 ::PrintSelf(std::ostream& os, Indent indent) const
430 {
431  Superclass::PrintSelf(os,indent);
432 
433  os << indent << "Label: " << static_cast<typename NumericTraits<LabelType>::PrintType>(m_Label) << std::endl;
434  os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl;
435  os << indent << "Negated: " << m_Negated << std::endl;
436  os << indent << "Crop: " << m_Crop << std::endl;
437  os << indent << "CropBorder: " << m_CropBorder << std::endl;
438 }
439 
440 
441 }// end namespace itk
442 #endif

Generated at Sat Feb 2 2013 23:48:46 for Orfeo Toolbox with doxygen 1.8.1.1