OTB  9.0.0
Orfeo Toolbox
otbImageToPointSetFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbImageToPointSetFilter_hxx
22 #define otbImageToPointSetFilter_hxx
23 
25 
26 namespace otb
27 {
28 
32 template <class TInputImage, class TOutputPointSet>
34 {
35  this->ProcessObjectType::SetNumberOfRequiredInputs(1);
36 
37  OutputPointSetPointer output = dynamic_cast<OutputPointSetType*>(this->MakeOutput(0).GetPointer());
38 
39  ProcessObjectType::SetNumberOfRequiredOutputs(1);
40  ProcessObjectType::SetNthOutput(0, output.GetPointer());
41 
42  m_PointsContainerPerThread.clear();
43  m_PointDataContainerPerThread.clear();
44 
45  // create default region splitter
46  m_StreamingManager = StreamingManagerType::New();
47 }
48 
52 template <class TInputImage, class TOutputPointSet>
54 {
55  // process object is not const-correct, the const_cast
56  // is required here.
57  this->ProcessObjectType::SetNthInput(idx, const_cast<InputImageType*>(input));
58 }
59 
63 template <class TInputImage, class TOutputPointSet>
65 {
66  // process object is not const-correct, the const_cast
67  // is required here.
68  this->ProcessObjectType::SetNthInput(0, const_cast<InputImageType*>(input));
69 }
70 
74 template <class TInputImage, class TOutputPointSet>
77 {
78 
79  return dynamic_cast<const InputImageType*>(this->ProcessObjectType::GetInput(idx));
80 }
81 
85 template <class TInputImage, class TOutputPointSet>
87 {
88  if (this->GetNumberOfInputs() < 1)
89  return nullptr;
90 
91  return dynamic_cast<const InputImageType*>(this->ProcessObjectType::GetInput(0));
92 }
93 
97 template <class TInputImage, class TOutputPointSet>
98 void ImageToPointSetFilter<TInputImage, TOutputPointSet>::PrintSelf(std::ostream& os, itk::Indent indent) const
99 {
100  Superclass::PrintSelf(os, indent);
101 }
102 
108 template <class TInputImage, class TOutputPointSet>
110 {
111 }
112 
116 template <class TInputImage, class TOutputPointSet>
118 {
119 
120  PointsContainerType* outputPointsContainer = this->GetOutput()->GetPoints();
121  outputPointsContainer->Initialize();
122 
123  PointDataContainerType* outputPointDataContainer = this->GetOutput()->GetPointData();
124  outputPointDataContainer->Initialize();
125 
126  typename TInputImage::RegionType inputRegion = this->GetInput()->GetLargestPossibleRegion();
127 
128  // Input is an image, cast away the constness so we can set
129  // the requested region.
130  InputImagePointer input = const_cast<TInputImage*>(this->GetInput());
131 
132  m_StreamingManager->PrepareStreaming(input, inputRegion);
133 
134  unsigned long numDivisions = m_StreamingManager->GetNumberOfSplits();
135 
140  unsigned int piece;
141  InputImageRegionType streamRegion;
142  for (piece = 0; piece < numDivisions && !this->GetAbortGenerateData(); piece++)
143  {
144  streamRegion = m_StreamingManager->GetSplit(piece);
145  typedef itk::ImageToImageFilterDetail::ImageRegionCopier<itkGetStaticConstMacro(InputImageDimension), itkGetStaticConstMacro(InputImageDimension)>
146  OutputToInputRegionCopierType;
147  OutputToInputRegionCopierType regionCopier;
148  InputImageRegionType inputRegion2;
149  regionCopier(inputRegion2, streamRegion);
150  input->SetRequestedRegion(inputRegion2);
152 
153  // Call a method that can be overridden by a subclass to perform
154  // some calculations prior to splitting the main computations into
155  // separate threads
156  this->BeforeThreadedGenerateData();
157 
158  // Set up the multithreaded processing
159  ThreadStruct str;
160  str.Filter = this;
161 
162  // Initializing object per thread
163  typename PointsContainerType::Pointer defaultPointsContainer = PointsContainerType::New();
164  this->m_PointsContainerPerThread = OutputPointsContainerForThreadType(this->GetNumberOfThreads(), defaultPointsContainer);
165 
166  typename PointDataContainerType::Pointer defaultPointDataContainer = PointDataContainerType::New();
167  this->m_PointDataContainerPerThread = OutputPointDataContainerForThreadType(this->GetNumberOfThreads(), defaultPointDataContainer);
168 
169  // Setting up multithreader
170  this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
171  this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str);
172 
173  // multithread the execution
174  this->GetMultiThreader()->SingleMethodExecute();
175 
176  // Call a method that can be overridden by a subclass to perform
177  // some calculations after all the threads have completed
178  this->AfterThreadedGenerateData();
179  }
180 }
181 
182 template <class TInputImage, class TOutputPointSet>
184 {
185 }
186 
187 template <class TInputImage, class TOutputPointSet>
189 {
190  // copy the lists to the output
191  PointsContainerType* outputPointsContainer = this->GetOutput()->GetPoints();
192  unsigned long currentIndex = outputPointsContainer->Size();
193 
194  typedef typename PointsContainerType::ConstIterator OutputPointsContainerIterator;
195  for (unsigned int i = 0; i < this->m_PointsContainerPerThread.size(); ++i)
196  {
197  if (this->m_PointsContainerPerThread[i].IsNotNull())
198  {
199  for (OutputPointsContainerIterator it = this->m_PointsContainerPerThread[i]->Begin(); it != this->m_PointsContainerPerThread[i]->End(); ++it)
200  {
201  outputPointsContainer->InsertElement(currentIndex, it.Value());
202  ++currentIndex;
203  }
204  }
205  }
206 
207  PointDataContainerType* outputPointDataContainer = this->GetOutput()->GetPointData();
208  currentIndex = outputPointDataContainer->Size();
209 
210  typedef typename PointDataContainerType::ConstIterator OutputPointDataContainerIterator;
211  for (unsigned int i = 0; i < this->m_PointDataContainerPerThread.size(); ++i)
212  {
213  if (this->m_PointDataContainerPerThread[i].IsNotNull())
214  {
215  for (OutputPointDataContainerIterator it = this->m_PointDataContainerPerThread[i]->Begin(); it != this->m_PointDataContainerPerThread[i]->End(); ++it)
216  {
217  outputPointDataContainer->InsertElement(currentIndex, it.Value());
218  ++currentIndex;
219  }
220  }
221  }
222 }
223 
224 template <class TInputImage, class TOutputPointSet>
226 {
227  // The following code is equivalent to:
228  // itkExceptionMacro("subclass should override this method!!!");
229  // The ExceptionMacro is not used because gcc warns that a
230  // 'noreturn' function does return
231  std::ostringstream message;
232  message << "itk::ERROR: " << this->GetNameOfClass() << "(" << this << "): "
233  << "Subclass should override this method!!!";
234  itk::ExceptionObject e_(__FILE__, __LINE__, message.str(), ITK_LOCATION);
235  throw e_;
236 }
237 
238 template <class TInputImage, class TOutputPointSet>
240 {
241  ThreadStruct* str;
242  unsigned int total, threadCount;
243  itk::ThreadIdType threadId;
244 
245  threadId = ((itk::MultiThreader::ThreadInfoStruct*)(arg))->ThreadID;
246  threadCount = ((itk::MultiThreader::ThreadInfoStruct*)(arg))->NumberOfThreads;
247  str = (ThreadStruct*)(((itk::MultiThreader::ThreadInfoStruct*)(arg))->UserData);
248 
249  // execute the actual method with appropriate output region
250  // first find out how many pieces extent can be split into.
251  typename TInputImage::RegionType splitRegion;
252  total = str->Filter->SplitRequestedRegion(threadId, threadCount, splitRegion);
253 
254  if (threadId < total)
255  {
256  str->Filter->ThreadedGenerateData(splitRegion, threadId);
257  }
258  // else
259  // {
260  // otherwise don't use this thread. Sometimes the threads don't
261  // break up very well and it is just as efficient to leave a
262  // few threads idle.
263  // }
264 
265  return ITK_THREAD_RETURN_VALUE;
266 }
267 
268 template <class TInputImage, class TOutputPointSet>
270 {
271  // Get the output pointer
272  typename InputImageType::ConstPointer inputPtr = this->GetInput();
273  const typename TInputImage::SizeType& requestedRegionSize = inputPtr->GetRequestedRegion().GetSize();
274 
275  int splitAxis;
276  typename TInputImage::IndexType splitIndex;
277  typename TInputImage::SizeType splitSize;
278 
279  // Initialize the splitRegion to the output requested region
280  splitRegion = inputPtr->GetRequestedRegion();
281  splitIndex = splitRegion.GetIndex();
282  splitSize = splitRegion.GetSize();
283 
284  // split on the outermost dimension available
285  splitAxis = inputPtr->GetImageDimension() - 1;
286  while (requestedRegionSize[splitAxis] == 1)
287  {
288  --splitAxis;
289  if (splitAxis < 0)
290  { // cannot split
291  itkDebugMacro(" Cannot Split");
292  return 1;
293  }
294  }
295 
296  // determine the actual number of pieces that will be generated
297  typename TInputImage::SizeType::SizeValueType range = requestedRegionSize[splitAxis];
298  int valuesPerThread = (int)::std::ceil(range / (double)num);
299  int maxThreadIdUsed = (int)::std::ceil(range / (double)valuesPerThread) - 1;
300 
301  // Split the region
302  if (i < maxThreadIdUsed)
303  {
304  splitIndex[splitAxis] += i * valuesPerThread;
305  splitSize[splitAxis] = valuesPerThread;
306  }
307  if (i == maxThreadIdUsed)
308  {
309  splitIndex[splitAxis] += i * valuesPerThread;
310  // last thread needs to process the "rest" dimension being split
311  splitSize[splitAxis] = splitSize[splitAxis] - i * valuesPerThread;
312  }
313 
314  // set the split region ivars
315  splitRegion.SetIndex(splitIndex);
316  splitRegion.SetSize(splitSize);
317 
318  itkDebugMacro(" Split Piece: " << splitRegion);
319 
320  return maxThreadIdUsed + 1;
321 }
322 
323 } // end namespace otb
324 
325 #endif
otb::ImageToPointSetFilter< TInputImage, itk::PointSet< typename TInputImage::PixelType, 2 > >::OutputPointSetType
Superclass::OutputPointSetType OutputPointSetType
Definition: otbImageToPointSetFilter.h:65
otb::ImageToPointSetFilter< TInputImage, itk::PointSet< typename TInputImage::PixelType, 2 > >::OutputPointsContainerForThreadType
std::vector< typename OutputPointSetType::PointsContainer::Pointer > OutputPointsContainerForThreadType
Definition: otbImageToPointSetFilter.h:96
otb::ImageToPointSetFilter::SplitRequestedRegion
virtual int SplitRequestedRegion(int i, int num, InputImageRegionType &splitRegion)
Definition: otbImageToPointSetFilter.hxx:269
otb::ImageToPointSetFilter< TInputImage, itk::PointSet< typename TInputImage::PixelType, 2 > >::PointDataContainerType
Superclass::PointDataContainerType PointDataContainerType
Definition: otbImageToPointSetFilter.h:68
otb::ImageToPointSetFilter< TInputImage, itk::PointSet< typename TInputImage::PixelType, 2 > >::InputImagePointer
InputImageType::Pointer InputImagePointer
Definition: otbImageToPointSetFilter.h:58
otb::ImageToPointSetFilter::ThreaderCallback
static ITK_THREAD_RETURN_TYPE ThreaderCallback(void *arg)
Definition: otbImageToPointSetFilter.hxx:239
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::ImageToPointSetFilter< TInputImage, itk::PointSet< typename TInputImage::PixelType, 2 > >::OutputPointSetPointer
Superclass::OutputPointSetPointer OutputPointSetPointer
Definition: otbImageToPointSetFilter.h:66
otb::ImageToPointSetFilter::GetInput
const InputImageType * GetInput()
Definition: otbImageToPointSetFilter.hxx:86
otb::ImageToPointSetFilter::SetInput
void SetInput(unsigned int idx, const InputImageType *input)
Definition: otbImageToPointSetFilter.hxx:53
otb::ImageToPointSetFilter::GenerateData
void GenerateData(void) override
Definition: otbImageToPointSetFilter.hxx:117
otb::ImageToPointSetFilter::ThreadedGenerateData
virtual void ThreadedGenerateData(const InputImageRegionType &inputRegionForThread, itk::ThreadIdType threadId)
Definition: otbImageToPointSetFilter.hxx:225
otb::ImageToPointSetFilter< TInputImage, itk::PointSet< typename TInputImage::PixelType, 2 > >::OutputPointDataContainerForThreadType
std::vector< typename OutputPointSetType::PointDataContainer::Pointer > OutputPointDataContainerForThreadType
Definition: otbImageToPointSetFilter.h:97
otbImageToPointSetFilter.h
otb::ImageToPointSetFilter::GenerateOutputInformation
void GenerateOutputInformation(void) override
Definition: otbImageToPointSetFilter.hxx:109
otb::ImageToPointSetFilter::BeforeThreadedGenerateData
virtual void BeforeThreadedGenerateData()
Definition: otbImageToPointSetFilter.hxx:183
otb::ImageToPointSetFilter::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: otbImageToPointSetFilter.hxx:98
otb::ImageToPointSetFilter< TInputImage, itk::PointSet< typename TInputImage::PixelType, 2 > >::InputImageType
TInputImage InputImageType
Definition: otbImageToPointSetFilter.h:54
otb::ImageToPointSetFilter::ImageToPointSetFilter
ImageToPointSetFilter()
Definition: otbImageToPointSetFilter.hxx:33
otb::ImageToPointSetFilter< TInputImage, itk::PointSet< typename TInputImage::PixelType, 2 > >::InputImageRegionType
InputImageType::RegionType InputImageRegionType
Definition: otbImageToPointSetFilter.h:60
otb::ImageToPointSetFilter::AfterThreadedGenerateData
virtual void AfterThreadedGenerateData()
Definition: otbImageToPointSetFilter.hxx:188
otb::ImageToPointSetFilter< TInputImage, itk::PointSet< typename TInputImage::PixelType, 2 > >::PointsContainerType
Superclass::PointsContainerType PointsContainerType
Definition: otbImageToPointSetFilter.h:67