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