Orfeo ToolBox  4.2
Orfeo ToolBox is not a black box
otbStreamingMinMaxImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
11 
12 Some parts of this code are derived from ITK. See ITKCopyright.txt
13 for details.
14 
15 
16  This software is distributed WITHOUT ANY WARRANTY; without even
17  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
18  PURPOSE. See the above copyright notices for more information.
19 
20 =========================================================================*/
21 #ifndef __otbStreamingMinMaxImageFilter_txx
22 #define __otbStreamingMinMaxImageFilter_txx
24 
25 #include <algorithm>
26 #include "itkImageRegionIterator.h"
27 #include "itkProgressReporter.h"
28 #include "otbMacro.h"
29 
30 namespace otb
31 {
32 
33 template<class TInputImage>
36 {
37  // TODO : SetNumberOfRequiredOutputs
38 
39  // first output is a copy of the image, DataObject created by
40  // superclass
41  //
42  // allocate the data objects for the outputs which are
43  // just decorators around pixel & index types
44  for (int i = 1; i < 5; ++i)
45  {
46  this->itk::ProcessObject::SetNthOutput(i, this->MakeOutput(i));
47  }
48 
49  this->GetMinimumOutput()->Set(itk::NumericTraits<PixelType>::max());
50  this->GetMaximumOutput()->Set(itk::NumericTraits<PixelType>::NonpositiveMin());
51 
52  this->Reset();
53 }
54 
55 template<class TInputImage>
56 typename itk::DataObject::Pointer
58 ::MakeOutput(unsigned int output)
59 {
60  itk::DataObject::Pointer ret;
61  switch (output)
62  {
63  case 0:
64  ret = static_cast<itk::DataObject*>(TInputImage::New().GetPointer());
65  break;
66  case 1:
67  case 2:
68  ret = static_cast<itk::DataObject*>(PixelObjectType::New().GetPointer());
69  break;
70  case 3:
71  case 4:
72  ret = static_cast<itk::DataObject*>(IndexObjectType::New().GetPointer());
73  break;
74  }
75  return ret;
76 }
77 
78 template<class TInputImage>
82 {
83  return static_cast<PixelObjectType*>(this->itk::ProcessObject::GetOutput(1));
84 }
85 
86 template<class TInputImage>
90 {
91  return static_cast<const PixelObjectType*>(this->itk::ProcessObject::GetOutput(1));
92 }
93 
94 template<class TInputImage>
98 {
99  return static_cast<PixelObjectType*>(this->itk::ProcessObject::GetOutput(2));
100 }
101 
102 template<class TInputImage>
106 {
107  return static_cast<const PixelObjectType*>(this->itk::ProcessObject::GetOutput(2));
108 }
109 
110 
111 template<class TInputImage>
115 {
116  return static_cast<IndexObjectType*>(this->itk::ProcessObject::GetOutput(3));
117 }
118 
119 template<class TInputImage>
123 {
124  return static_cast<const IndexObjectType*>(this->itk::ProcessObject::GetOutput(3));
125 }
126 
127 template<class TInputImage>
131 {
132  return static_cast<IndexObjectType*>(this->itk::ProcessObject::GetOutput(4));
133 }
134 
135 template<class TInputImage>
139 {
140  return static_cast<const IndexObjectType*>(this->itk::ProcessObject::GetOutput(4));
141 }
142 
143 template<class TInputImage>
144 void
147 {
148  Superclass::GenerateOutputInformation();
149  if (this->GetInput())
150  {
151  this->GetOutput()->CopyInformation(this->GetInput());
152  this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion());
153 
154  if (this->GetOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
155  {
156  this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion());
157  }
158  }
159 }
160 template<class TInputImage>
161 void
164 {
165  // This is commented to prevent the streaming of the whole image for the first stream strip
166  // It shall not cause any problem because the output image of this filter is not intended to be used.
167  //InputImagePointer image = const_cast< TInputImage * >( this->GetInput() );
168  //this->GraftOutput( image );
169  // Nothing that needs to be allocated for the remaining outputs
170 }
171 
172 template<class TInputImage>
173 void
176 {
177  int i;
178  int numberOfThreads = this->GetNumberOfThreads();
179 
182  IndexType minimumIdx;
183  IndexType maximumIdx;
184 
185  for (i = 0; i < numberOfThreads; ++i)
186  {
187  if (m_ThreadMin[i] < minimum)
188  {
189  minimum = m_ThreadMin[i];
190  minimumIdx = m_ThreadMinIndex[i];
191  }
192  if (m_ThreadMax[i] > maximum)
193  {
194  maximum = m_ThreadMax[i];
195  maximumIdx = m_ThreadMaxIndex[i];
196  }
197  }
198 
199  // Set the outputs
200  this->GetMinimumOutput()->Set(minimum);
201  this->GetMaximumOutput()->Set(maximum);
202  this->GetMinimumIndexOutput()->Set(minimumIdx);
203  this->GetMaximumIndexOutput()->Set(maximumIdx);
204 }
205 
206 template<class TInputImage>
207 void
210 {
211  int numberOfThreads = this->GetNumberOfThreads();
212 
213  m_ThreadMin.resize(numberOfThreads);
214  m_ThreadMax.resize(numberOfThreads);
215  std::fill(m_ThreadMin.begin(), m_ThreadMin.end(), itk::NumericTraits<PixelType>::max());
216  std::fill(m_ThreadMax.begin(), m_ThreadMax.end(), itk::NumericTraits<PixelType>::NonpositiveMin());
217 
218  IndexType zeroIdx;
219  zeroIdx.Fill(0);
220  m_ThreadMinIndex.resize(numberOfThreads);
221  m_ThreadMaxIndex.resize(numberOfThreads);
222  std::fill(m_ThreadMinIndex.begin(), m_ThreadMinIndex.end(), zeroIdx);
223  std::fill(m_ThreadMaxIndex.begin(), m_ThreadMaxIndex.end(), zeroIdx);
224 }
225 
226 template<class TInputImage>
227 void
229 ::ThreadedGenerateData(const RegionType& outputRegionForThread,
230  itk::ThreadIdType threadId)
231 {
232  // support progress methods/callbacks
233  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
234 
235  InputImagePointer inputPtr = const_cast<TInputImage *>(this->GetInput(0));
236  itk::ImageRegionConstIterator<TInputImage> it(inputPtr, outputRegionForThread);
237  it.GoToBegin();
238  // do the work
239  while (!it.IsAtEnd())
240  {
241  PixelType value = it.Get();
242  if (value < m_ThreadMin[threadId])
243  {
244  m_ThreadMin[threadId] = value;
245  m_ThreadMinIndex[threadId] = it.GetIndex();
246  }
247  if (value > m_ThreadMax[threadId])
248  {
249  m_ThreadMax[threadId] = value;
250  m_ThreadMaxIndex[threadId] = it.GetIndex();
251  }
252  ++it;
253  progress.CompletedPixel();
254  }
255 }
256 
257 template <class TImage>
258 void
260 ::PrintSelf(std::ostream& os, itk::Indent indent) const
261 {
262  Superclass::PrintSelf(os, indent);
263 
264  os << indent << "Minimum: "
265  << static_cast<typename itk::NumericTraits<PixelType>::PrintType>(this->GetMinimum()) << std::endl;
266  os << indent << "Maximum: "
267  << static_cast<typename itk::NumericTraits<PixelType>::PrintType>(this->GetMaximum()) << std::endl;
268  os << indent << "Minimum Index: " << this->GetMinimumIndex() << std::endl;
269  os << indent << "Maximum Index: " << this->GetMaximumIndex() << std::endl;
270 }
271 
272 } // end namespace otb
273 #endif
const IndexType GetIndex() const
void ThreadedGenerateData(const RegionType &outputRegionForThread, itk::ThreadIdType threadId)
virtual DataObjectPointer MakeOutput(unsigned int idx)
void PrintSelf(std::ostream &os, itk::Indent indent) const
static T max(const T &)
static T NonpositiveMin()
bool IsAtEnd(void) const
PixelType Get(void) const
unsigned int ThreadIdType