OTB  9.0.0
Orfeo Toolbox
otbSFSTexturesImageFilter.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 otbSFSTexturesImageFilter_hxx
22 #define otbSFSTexturesImageFilter_hxx
23 
25 
26 #include "itkProgressReporter.h"
27 #include "itkImageRegionIterator.h"
28 #include "itkNeighborhoodAlgorithm.h"
29 #include "otbMath.h"
30 
31 namespace otb
32 {
33 
34 template <class TInputImage, class TOutputImage>
36 {
37  this->SetNumberOfRequiredInputs(1);
38  this->SetNumberOfRequiredInputs(1);
39  this->SetNumberOfRequiredOutputs(6);
40  this->SetNumberOfRequiredOutputs(1);
41 
42  this->SetNthOutput(0, OutputImageType::New());
43  this->SetNthOutput(1, OutputImageType::New());
44  this->SetNthOutput(2, OutputImageType::New());
45  this->SetNthOutput(3, OutputImageType::New());
46  this->SetNthOutput(4, OutputImageType::New());
47  this->SetNthOutput(5, OutputImageType::New());
48 
49  m_Radius = this->GetSpatialThreshold();
50  m_FunctorList.clear();
51 }
57 // Return output length image
58 template <class TInputImage, class TOutputImage>
60 {
61  if (this->GetNumberOfOutputs() < 1)
62  {
63  return 0;
64  }
65  if (this->GetTexturesStatus()[0] == false)
66  {
67  itkExceptionMacro(<< "Impossible to create length image : texture not selected");
68  }
69  return static_cast<const OutputImageType*>(this->itk::ProcessObject::GetOutput(0));
70 }
71 template <class TInputImage, class TOutputImage>
73 {
74  if (this->GetNumberOfOutputs() < 1)
75  {
76  return nullptr;
77  }
78  if (this->GetTexturesStatus()[0] == false)
79  {
80  itkExceptionMacro(<< "Impossible to create length image : texture not selected");
81  }
82  return static_cast<OutputImageType*>(this->itk::ProcessObject::GetOutput(0));
83 }
85 
86 // Return output width image
87 template <class TInputImage, class TOutputImage>
89 {
90  if (this->GetNumberOfOutputs() < 2)
91  {
92  return 0;
93  }
94  if (this->GetTexturesStatus()[1] == false)
95  {
96  itkExceptionMacro(<< "Impossible to create width image : texture not selected");
97  }
98  return static_cast<const OutputImageType*>(this->itk::ProcessObject::GetOutput(1));
99 }
100 template <class TInputImage, class TOutputImage>
102 {
103  if (this->GetNumberOfOutputs() < 2)
104  {
105  return nullptr;
106  }
107  if (this->GetTexturesStatus()[1] == false)
108  {
109  itkExceptionMacro(<< "Impossible to create width image : texture not selected");
110  }
111  return static_cast<OutputImageType*>(this->itk::ProcessObject::GetOutput(1));
112 }
113 
114 // Return output PSI image
115 template <class TInputImage, class TOutputImage>
117 {
118  if (this->GetNumberOfOutputs() < 3)
119  {
120  return 0;
121  }
122  if (this->GetTexturesStatus()[2] == false)
123  {
124  itkExceptionMacro(<< "Impossible to create PSI image : texture not selected");
125  }
126  return static_cast<const OutputImageType*>(this->itk::ProcessObject::GetOutput(2));
127 }
128 template <class TInputImage, class TOutputImage>
130 {
131  if (this->GetNumberOfOutputs() < 3)
132  {
133  return nullptr;
134  }
135  if (this->GetTexturesStatus()[2] == false)
136  {
137  itkExceptionMacro(<< "Impossible to create PSI image : texture not selected");
138  }
139 
140  return static_cast<OutputImageType*>(this->itk::ProcessObject::GetOutput(2));
141 }
142 
143 // Return output WMean image
144 template <class TInputImage, class TOutputImage>
146 {
147  if (this->GetNumberOfOutputs() < 4)
148  {
149  return 0;
150  }
151  if (this->GetTexturesStatus()[3] == false)
152  {
153  itkExceptionMacro(<< "Impossible to create W-Mean image : texture not selected");
154  }
155  return static_cast<const OutputImageType*>(this->itk::ProcessObject::GetOutput(3));
156 }
157 template <class TInputImage, class TOutputImage>
159 {
160  if (this->GetNumberOfOutputs() < 4)
161  {
162  return nullptr;
163  }
164  if (this->GetTexturesStatus()[3] == false)
165  {
166  itkExceptionMacro(<< "Impossible to create W-Mean image : texture not selected");
167  }
168  return static_cast<OutputImageType*>(this->itk::ProcessObject::GetOutput(3));
169 }
170 
171 // Return output ratio image
172 template <class TInputImage, class TOutputImage>
174 {
175  if (this->GetNumberOfOutputs() < 5)
176  {
177  return 0;
178  }
179  if (this->GetTexturesStatus()[4] == false)
180  {
181  itkExceptionMacro(<< "Impossible to create Ratio image : texture not selected");
182  }
183  return static_cast<const OutputImageType*>(this->itk::ProcessObject::GetOutput(4));
184 }
185 template <class TInputImage, class TOutputImage>
187 {
188  if (this->GetNumberOfOutputs() < 5)
189  {
190  return nullptr;
191  }
192  if (this->GetTexturesStatus()[4] == false)
193  {
194  itkExceptionMacro(<< "Impossible to create Ratio image : texture not selected");
195  }
196  return static_cast<OutputImageType*>(this->itk::ProcessObject::GetOutput(4));
197 }
198 
199 // Return output SD image
200 template <class TInputImage, class TOutputImage>
202 {
203  if (this->GetNumberOfOutputs() < 6)
204  {
205  return 0;
206  }
207  if (this->GetTexturesStatus()[5] == false)
208  {
209  itkExceptionMacro(<< "Impossible to create SD image : texture not selected");
210  }
211  return static_cast<const OutputImageType*>(this->itk::ProcessObject::GetOutput(5));
212 }
213 template <class TInputImage, class TOutputImage>
215 {
216  if (this->GetNumberOfOutputs() < 6)
217  {
218  return nullptr;
219  }
220  if (this->GetTexturesStatus()[5] == false)
221  {
222  itkExceptionMacro(<< "Impossible to create SD image : texture not selected");
223  }
224 
225  return static_cast<OutputImageType*>(this->itk::ProcessObject::GetOutput(5));
226 }
227 
228 template <class TInputImage, class TOutputImage>
230 {
231  Superclass::BeforeThreadedGenerateData();
232  if (this->GetSpatialThreshold() < this->GetRatioMaxConsiderationNumber())
233  {
234  itkExceptionMacro(<< "Spatial Threshold (" << this->GetSpatialThreshold() << ") is lower than Ration Max Consideration Number ("
235  << this->GetRatioMaxConsiderationNumber() << ") what is not allowed.");
236  }
237  for (unsigned int i = 0; i < this->GetNumberOfThreads(); ++i)
238  {
239  m_FunctorList.push_back(m_Functor);
240  }
241  this->InitFeatureStatus(true);
242 }
243 
244 template <class TInputImage, class TOutputImage>
246 {
247  // call the superclass' implementation of this method
248  Superclass::GenerateInputRequestedRegion();
249 
250  // get pointers to the input and output
251  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage*>(this->GetInput());
252  typename Superclass::OutputImagePointer outputPtr1 = this->GetOutput(0); // this->GetLengthOutput();
253  typename Superclass::OutputImagePointer outputPtr2 = this->GetOutput(1); // this->GetWidthOutput();
254  typename Superclass::OutputImagePointer outputPtr3 = this->GetOutput(2); // this->GetPSIOutput();
255  typename Superclass::OutputImagePointer outputPtr4 = this->GetOutput(3); // this->GetWMeanOutput();
256  typename Superclass::OutputImagePointer outputPtr5 = this->GetOutput(4); // this->GetRatioOutput();
257  typename Superclass::OutputImagePointer outputPtr6 = this->GetOutput(5); // this->GetSDOutput();
258 
259  if (!inputPtr || !outputPtr1 || !outputPtr2 || !outputPtr3 || !outputPtr4 || !outputPtr5 || !outputPtr6)
260  {
261  return;
262  }
263  // get a copy of the input requested region (should equal the output
264  // requested region)
265  typename TInputImage::RegionType inputRequestedRegion;
266  inputRequestedRegion = inputPtr->GetRequestedRegion();
267 
268  // pad the input requested region by the operator radius
269  InputImageSizeType rad;
270  rad[0] = m_Radius;
271  rad[1] = m_Radius;
272  inputRequestedRegion.PadByRadius(rad);
273 
274  // crop the input requested region at the input's largest possible region
275  if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
276  {
277  inputPtr->SetRequestedRegion(inputRequestedRegion);
278  return;
279  }
280  else
281  {
282  // Couldn't crop the region (requested region is outside the largest
283  // possible region). Throw an exception.
284 
285  // store what we tried to request (prior to trying to crop)
286  inputPtr->SetRequestedRegion(inputRequestedRegion);
287 
288  // build an exception
289  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
290  std::ostringstream msg;
291  msg << this->GetNameOfClass() << "::GenerateInputRequestedRegion()";
292  e.SetLocation(msg.str());
293  e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
294  e.SetDataObject(inputPtr);
295  throw e;
296  }
297 }
298 
299 template <class TInputImage, class TOutputImage>
301 {
302  Superclass::GenerateOutputInformation();
303  // this->GetOutput()->SetNumberOfComponentsPerPixel(6);
304 }
305 
306 template <class TInputImage, class TOutputImage>
307 void SFSTexturesImageFilter<TInputImage, TOutputImage>::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
308 {
309  itk::ZeroFluxNeumannBoundaryCondition<TInputImage> nbc;
310 
311  // We use dynamic_cast since inputs are stored as DataObjects. The
312  // ImageToImageFilter::GetInput(int) always returns a pointer to a
313  // TInputImage so it cannot be used for the second input.
314  InputImagePointerType inputPtr = dynamic_cast<const TInputImage*>(ProcessObjectType::GetInput(0));
315  OutputImagePointerType outputPtr1 = this->GetOutput(0);
316  OutputImagePointerType outputPtr2 = this->GetOutput(1);
317  OutputImagePointerType outputPtr3 = this->GetOutput(2);
318  OutputImagePointerType outputPtr4 = this->GetOutput(3);
319  OutputImagePointerType outputPtr5 = this->GetOutput(4);
320  OutputImagePointerType outputPtr6 = this->GetOutput(5);
321 
322  RadiusType r;
323  r.Fill(this->GetRadius());
324  NeighborhoodIteratorType neighInputIt;
325 
326  itk::ImageRegionIterator<TOutputImage> outputIt1, outputIt2, outputIt3, outputIt4, outputIt5, outputIt6;
327  FunctorOutputType outputFunctor;
328 
329  // Find the data-set boundary "faces"
330  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage>::FaceListType faceList;
331  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage> bC;
332  faceList = bC(inputPtr, outputRegionForThread, r);
333 
334  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage>::FaceListType::iterator fit;
335 
336  // support progress methods/callbacks
337  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
338 
339  // Process each of the boundary faces. These are N-d regions which border
340  // the edge of the buffer.
341 
342  std::vector<bool> textStatus = this->GetTexturesStatus();
343  for (fit = faceList.begin(); fit != faceList.end(); ++fit)
344  {
345  neighInputIt = itk::ConstNeighborhoodIterator<TInputImage>(r, inputPtr, *fit);
346 
347  outputIt1 = itk::ImageRegionIterator<TOutputImage>(outputPtr1, *fit);
348  outputIt2 = itk::ImageRegionIterator<TOutputImage>(outputPtr2, *fit);
349  outputIt3 = itk::ImageRegionIterator<TOutputImage>(outputPtr3, *fit);
350  outputIt4 = itk::ImageRegionIterator<TOutputImage>(outputPtr4, *fit);
351  outputIt5 = itk::ImageRegionIterator<TOutputImage>(outputPtr5, *fit);
352  outputIt6 = itk::ImageRegionIterator<TOutputImage>(outputPtr6, *fit);
353 
354  std::vector<itk::ImageRegionIterator<TOutputImage>*> outItList;
355  outItList.push_back(&outputIt1);
356  outItList.push_back(&outputIt2);
357  outItList.push_back(&outputIt3);
358  outItList.push_back(&outputIt4);
359  outItList.push_back(&outputIt5);
360  outItList.push_back(&outputIt6);
361 
362  neighInputIt.OverrideBoundaryCondition(&nbc);
363  neighInputIt.GoToBegin();
364 
365  for (unsigned int i = 0; i < outItList.size(); ++i)
366  {
367  (*outItList[i]).GoToBegin();
368  }
369 
370  while (!outputIt1.IsAtEnd())
371  {
372 
373  outputFunctor = m_FunctorList[threadId](neighInputIt);
374  for (unsigned int i = 0; i < outItList.size(); ++i)
375  {
376  if (textStatus[i] == true)
377  (*outItList[i]).Set(outputFunctor[i]);
378  }
379 
380  ++neighInputIt;
381  for (unsigned int i = 0; i < outItList.size(); ++i)
382  {
383  ++(*outItList[i]);
384  }
385 
386  progress.CompletedPixel();
387  }
388  }
389 }
390 
391 template <class TInputImage, class TOutputImage>
393 {
394  for (FeatureType id = LENGTH; id <= SD; id = static_cast<FeatureType>(id + 1))
395  {
396  this->SetFeatureStatus(static_cast<FeatureType>(id), status);
397  }
398 }
399 
403 template <class TInputImage, class TOutputImage>
404 void SFSTexturesImageFilter<TInputImage, TOutputImage>::PrintSelf(std::ostream& os, itk::Indent indent) const
405 {
406  Superclass::PrintSelf(os, indent);
407 
408  // os << indent << "Spatial Threshold : " << this->GetSpatialThreshold() << std::endl;
409  // os << indent << "Spectral Threshold : " << this->GetSpectralThreshold() << std::endl;
410  // os << indent << "Ratio Max Consideration Number: " << this->GetRatioMaxConsiderationNumber() << std::endl;
411  // os << indent << "Alpha : " << this->GetAlpha() << std::endl;
412  // os << indent << "Number Of Directions : " << this->GetNumberOfDirections() << std::endl;
413 }
414 
415 } // end namespace otb
416 
417 #endif
otb::SFSTexturesImageFilter::GetWMeanOutput
const OutputImageType * GetWMeanOutput() const
Definition: otbSFSTexturesImageFilter.hxx:145
otb::SFSTexturesImageFilter::GenerateOutputInformation
void GenerateOutputInformation() override
Definition: otbSFSTexturesImageFilter.hxx:300
otb::SFSTexturesImageFilter::OutputImageRegionType
OutputImageType::RegionType OutputImageRegionType
Definition: otbSFSTexturesImageFilter.h:81
otbMath.h
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::SFSTexturesImageFilter::BeforeThreadedGenerateData
void BeforeThreadedGenerateData() override
Definition: otbSFSTexturesImageFilter.hxx:229
otb::SFSTexturesImageFilter::InitFeatureStatus
void InitFeatureStatus(bool status)
Definition: otbSFSTexturesImageFilter.hxx:392
otb::SFSTexturesImageFilter::FunctorOutputType
FunctorType::OutputType FunctorOutputType
Definition: otbSFSTexturesImageFilter.h:86
otb::SFSTexturesImageFilter::GetPSIOutput
const OutputImageType * GetPSIOutput() const
Definition: otbSFSTexturesImageFilter.hxx:116
otb::SFSTexturesImageFilter::GetLengthOutput
const OutputImageType * GetLengthOutput() const
Definition: otbSFSTexturesImageFilter.hxx:59
otb::SFSTexturesImageFilter::RadiusType
NeighborhoodIteratorType::RadiusType RadiusType
Definition: otbSFSTexturesImageFilter.h:84
otbSFSTexturesImageFilter.h
otb::SFSTexturesImageFilter::ThreadedGenerateData
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, itk::ThreadIdType threadId) override
Definition: otbSFSTexturesImageFilter.hxx:307
otb::SFSTexturesImageFilter::SFSTexturesImageFilter
SFSTexturesImageFilter()
Definition: otbSFSTexturesImageFilter.hxx:35
otb::SFSTexturesImageFilter::NeighborhoodIteratorType
itk::ConstNeighborhoodIterator< TInputImage > NeighborhoodIteratorType
Definition: otbSFSTexturesImageFilter.h:83
otb::SFSTexturesImageFilter::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: otbSFSTexturesImageFilter.hxx:404
otb::SFSTexturesImageFilter::GenerateInputRequestedRegion
void GenerateInputRequestedRegion(void) override
Definition: otbSFSTexturesImageFilter.hxx:245
otb::SFSTexturesImageFilter::OutputImagePointerType
OutputImageType::Pointer OutputImagePointerType
Definition: otbSFSTexturesImageFilter.h:80
otb::SFSTexturesImageFilter::OutputImageType
TOutputImage OutputImageType
Definition: otbSFSTexturesImageFilter.h:64
otb::SFSTexturesImageFilter::GetRatioOutput
const OutputImageType * GetRatioOutput() const
Definition: otbSFSTexturesImageFilter.hxx:173
otb::SFSTexturesImageFilter::GetSDOutput
const OutputImageType * GetSDOutput() const
Definition: otbSFSTexturesImageFilter.hxx:201
otb::SFSTexturesImageFilter::InputImageSizeType
InputImageType::SizeType InputImageSizeType
Definition: otbSFSTexturesImageFilter.h:79
otb::SFSTexturesImageFilter::GetWidthOutput
const OutputImageType * GetWidthOutput() const
Definition: otbSFSTexturesImageFilter.hxx:88
otb::SFSTexturesImageFilter::FeatureType
FeatureType
Definition: otbSFSTexturesImageFilter.h:174
otb::SFSTexturesImageFilter::InputImagePointerType
InputImageType::ConstPointer InputImagePointerType
Definition: otbSFSTexturesImageFilter.h:73