OTB  10.0.0
Orfeo Toolbox
otbStreamingMinMaxVectorImageFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1999-2011 Insight Software Consortium
3  * Copyright (C) 2005-2024 Centre National d'Etudes Spatiales (CNES)
4  *
5  * This file is part of Orfeo Toolbox
6  *
7  * https://www.orfeo-toolbox.org/
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 #ifndef otbStreamingMinMaxVectorImageFilter_hxx
23 #define otbStreamingMinMaxVectorImageFilter_hxx
25 
26 #include "itkImageRegionIterator.h"
27 #include "itkImageRegionConstIteratorWithIndex.h"
28 #include "itkNumericTraits.h"
29 #include "itkProgressReporter.h"
30 #include "otbMacro.h"
31 
32 namespace otb
33 {
34 
35 template <class TInputImage>
37  : m_NoDataFlag(false), m_NoDataValue(itk::NumericTraits<InternalPixelType>::Zero)
38 {
39 
40  // first output is a copy of the image, DataObject created by
41  // superclass
42  //
43  // allocate the data objects for the outputs which are
44  // just decorators around pixel types
45  this->DynamicMultiThreadingOff();
46  for (int i = 1; i < 3; ++i)
47  {
48  typename PixelObjectType::Pointer output = static_cast<PixelObjectType*>(this->MakeOutput(i).GetPointer());
49  this->itk::ProcessObject::SetNthOutput(i, output.GetPointer());
50  }
51 }
52 
53 template <class TInputImage>
55 {
56  itk::DataObject::Pointer ret;
57  switch (output)
58  {
59  case 0:
60  ret = static_cast<itk::DataObject*>(TInputImage::New().GetPointer());
61  break;
62  case 1:
63  case 2:
64  ret = static_cast<itk::DataObject*>(PixelObjectType::New().GetPointer());
65  break;
66  }
67  return ret;
68 }
69 
70 template <class TInputImage>
72 {
73  return static_cast<PixelObjectType*>(this->itk::ProcessObject::GetOutput(1));
74 }
75 
76 template <class TInputImage>
78 {
79  return static_cast<const PixelObjectType*>(this->itk::ProcessObject::GetOutput(1));
80 }
81 
82 template <class TInputImage>
84 {
85  return static_cast<PixelObjectType*>(this->itk::ProcessObject::GetOutput(2));
86 }
87 
88 template <class TInputImage>
90 {
91  return static_cast<const PixelObjectType*>(this->itk::ProcessObject::GetOutput(2));
92 }
93 
94 template <class TInputImage>
96 {
97  Superclass::GenerateOutputInformation();
98  if (this->GetInput())
99  {
100  this->GetOutput()->CopyInformation(this->GetInput());
101  this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion());
102 
103  if (this->GetOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
104  {
105  this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion());
106  }
107  }
108 }
109 
110 template <class TInputImage>
112 {
113  // This is commented to prevent the streaming of the whole image for the first stream strip
114  // It shall not cause any problem because the output image of this filter is not intended to be used.
115  // InputImagePointer image = const_cast< TInputImage * >( this->GetInput() );
116  // this->GraftOutput( image );
117  // Nothing that needs to be allocated for the remaining outputs
118 }
119 
120 template <class TInputImage>
122 {
123  TInputImage* inputPtr = const_cast<TInputImage*>(this->GetInput());
124  inputPtr->UpdateOutputInformation();
125 
126  unsigned int numberOfThreads = this->GetNumberOfWorkUnits();
127  unsigned int numberOfComponent = inputPtr->GetNumberOfComponentsPerPixel();
128 
129  // Variable Initialization
130  PixelType tempPixel;
131  tempPixel.SetSize(numberOfComponent);
132  tempPixel.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
133  this->GetMaximumOutput()->Set(tempPixel);
134 
135  tempPixel.Fill(itk::NumericTraits<InternalPixelType>::max());
136  this->GetMinimumOutput()->Set(tempPixel);
137 
138  PixelType tempTemporariesPixel;
139  tempTemporariesPixel.SetSize(numberOfComponent);
140  tempTemporariesPixel.Fill(itk::NumericTraits<InternalPixelType>::max());
141  m_ThreadMin = ArrayPixelType(numberOfThreads, tempTemporariesPixel);
142 
143  tempTemporariesPixel.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
144  m_ThreadMax = ArrayPixelType(numberOfThreads, tempTemporariesPixel);
145 }
146 
147 template <class TInputImage>
149 {
150  int i;
151 
152  int numberOfThreads = this->GetNumberOfWorkUnits();
153  unsigned int numberOfComponent = this->GetInput()->GetNumberOfComponentsPerPixel();
154 
155  PixelType minimumVector;
156  minimumVector.SetSize(numberOfComponent);
157  minimumVector.Fill(itk::NumericTraits<InternalPixelType>::max());
158 
159  PixelType maximumVector;
160  maximumVector.SetSize(numberOfComponent);
161  maximumVector.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
162 
163  // Find the min/max over all threads and accumulate count, sum and
164  // sum of squares
165  for (i = 0; i < numberOfThreads; ++i)
166  {
167  for (unsigned int j = 0; j < numberOfComponent; ++j)
168  {
169  if (m_ThreadMin[i][j] < minimumVector[j])
170  {
171  minimumVector[j] = m_ThreadMin[i][j];
172  }
173  if (m_ThreadMax[i][j] > maximumVector[j])
174  {
175  maximumVector[j] = m_ThreadMax[i][j];
176  }
177  }
178  } // end for( i = 0; i < numberOfThreads; ++i)
179 
180  // Set the outputs
181  this->GetMinimumOutput()->Set(minimumVector);
182  this->GetMaximumOutput()->Set(maximumVector);
183 }
184 
185 template <class TInputImage>
186 void PersistentMinMaxVectorImageFilter<TInputImage>::ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType threadId)
187 {
191  InputImagePointer inputPtr = const_cast<TInputImage*>(this->GetInput());
192  // support progress methods/callbacks
193  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
195 
196  itk::ImageRegionConstIteratorWithIndex<TInputImage> it(inputPtr, outputRegionForThread);
197  it.GoToBegin();
198 
199  // do the work
200  while (!it.IsAtEnd())
201  {
202  // IndexType index = it.GetIndex();
203  PixelType vectorValue = it.Get();
204  for (unsigned int j = 0; j < vectorValue.GetSize(); ++j)
205  {
206  InternalPixelType value = vectorValue[j];
207 
208  if ((!m_NoDataFlag) || value != m_NoDataValue)
209  {
210  if (value < m_ThreadMin[threadId][j])
211  {
212  m_ThreadMin[threadId][j] = value;
213  }
214  if (value > m_ThreadMax[threadId][j])
215  {
216  m_ThreadMax[threadId][j] = value;
217  }
218  }
219  }
220  ++it;
221  progress.CompletedPixel();
222  }
223 }
224 
225 template <class TImage>
226 void PersistentMinMaxVectorImageFilter<TImage>::PrintSelf(std::ostream& os, itk::Indent indent) const
227 {
228  Superclass::PrintSelf(os, indent);
229 
230  os << indent << "Minimum: " << this->GetMinimumOutput()->Get() << std::endl;
231  os << indent << "Maximum: " << this->GetMaximumOutput()->Get() << std::endl;
232 }
233 
234 } // end namespace otb
235 #endif
itk::SimpleDataObjectDecorator< PixelType > PixelObjectType
itk::ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType
void PrintSelf(std::ostream &os, itk::Indent indent) const override
DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx) override
void ThreadedGenerateData(const RegionType &outputRegionForThread, itk::ThreadIdType threadId) override
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.