Orfeo ToolBox  4.2
Orfeo ToolBox is not a black box
otbSFSTexturesImageFilter.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 
13  This software is distributed WITHOUT ANY WARRANTY; without even
14  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  PURPOSE. See the above copyright notices for more information.
16 
17 =========================================================================*/
18 #ifndef __otbSFSTexturesImageFilter_txx
19 #define __otbSFSTexturesImageFilter_txx
20 
22 
23 #include "itkProgressReporter.h"
24 #include "itkImageRegionIterator.h"
26 #include "otbMath.h"
27 
28 namespace otb
29 {
30 
31 template <class TInputImage, class TOutputImage>
34 {
35  this->SetNumberOfRequiredInputs(1);
36  this->SetNumberOfRequiredInputs(1);
37  this->SetNumberOfRequiredOutputs(6);
38  this->SetNumberOfRequiredOutputs(1);
39 
40  this->SetNthOutput(0, OutputImageType::New());
41  this->SetNthOutput(1, OutputImageType::New());
42  this->SetNthOutput(2, OutputImageType::New());
43  this->SetNthOutput(3, OutputImageType::New());
44  this->SetNthOutput(4, OutputImageType::New());
45  this->SetNthOutput(5, OutputImageType::New());
46 
47  m_Radius = this->GetSpatialThreshold();
48  m_FunctorList.clear();
49 
50 }
51 /************************************************************
52  *
53  * OUTPUTS MANIPULATION
54  *
55  ************************************************************/
56 // Return output length image
57 template <class TInputImage, class TOutputImage>
61 {
62  if (this->GetNumberOfOutputs() < 1)
63  {
64  return 0;
65  }
66  if (this->GetTexturesStatus()[0] == false)
67  {
68  itkExceptionMacro(<< "Impossible to create length image : texture not selected");
69  }
70  return static_cast<const OutputImageType *> (this->itk::ProcessObject::GetOutput(0));
71 }
72 template <class TInputImage, class TOutputImage>
76 {
77  if (this->GetNumberOfOutputs() < 1)
78  {
79  return 0;
80  }
81  if (this->GetTexturesStatus()[0] == false)
82  {
83  itkExceptionMacro(<< "Impossible to create length image : texture not selected");
84  }
85  return static_cast<OutputImageType *>(this->itk::ProcessObject::GetOutput(0));
86 }
87 
88 // Return output width image
89 template <class TInputImage, class TOutputImage>
93 {
94  if (this->GetNumberOfOutputs() < 2)
95  {
96  return 0;
97  }
98  if (this->GetTexturesStatus()[1] == false)
99  {
100  itkExceptionMacro(<< "Impossible to create width image : texture not selected");
101  }
102  return static_cast<const OutputImageType *> (this->itk::ProcessObject::GetOutput(1));
103 }
104 template <class TInputImage, class TOutputImage>
108 {
109  if (this->GetNumberOfOutputs() < 2)
110  {
111  return 0;
112  }
113  if (this->GetTexturesStatus()[1] == false)
114  {
115  itkExceptionMacro(<< "Impossible to create width image : texture not selected");
116  }
117  return static_cast<OutputImageType *>(this->itk::ProcessObject::GetOutput(1));
118 }
119 
120 //Return output PSI image
121 template <class TInputImage, class TOutputImage>
125 {
126  if (this->GetNumberOfOutputs() < 3)
127  {
128  return 0;
129  }
130  if (this->GetTexturesStatus()[2] == false)
131  {
132  itkExceptionMacro(<< "Impossible to create PSI image : texture not selected");
133  }
134  return static_cast<const OutputImageType *> (this->itk::ProcessObject::GetOutput(2));
135 }
136 template <class TInputImage, class TOutputImage>
140 {
141  if (this->GetNumberOfOutputs() < 3)
142  {
143  return 0;
144  }
145  if (this->GetTexturesStatus()[2] == false)
146  {
147  itkExceptionMacro(<< "Impossible to create PSI image : texture not selected");
148  }
149 
150  return static_cast<OutputImageType *>(this->itk::ProcessObject::GetOutput(2));
151 }
152 
153 // Return output WMean image
154 template <class TInputImage, class TOutputImage>
158 {
159  if (this->GetNumberOfOutputs() < 4)
160  {
161  return 0;
162  }
163  if (this->GetTexturesStatus()[3] == false)
164  {
165  itkExceptionMacro(<< "Impossible to create W-Mean image : texture not selected");
166  }
167  return static_cast<const OutputImageType *> (this->itk::ProcessObject::GetOutput(3));
168 }
169 template <class TInputImage, class TOutputImage>
173 {
174  if (this->GetNumberOfOutputs() < 4)
175  {
176  return 0;
177  }
178  if (this->GetTexturesStatus()[3] == false)
179  {
180  itkExceptionMacro(<< "Impossible to create W-Mean image : texture not selected");
181  }
182  return static_cast<OutputImageType *>(this->itk::ProcessObject::GetOutput(3));
183 }
184 
185 // Return output ratio image
186 template <class TInputImage, class TOutputImage>
190 {
191  if (this->GetNumberOfOutputs() < 5)
192  {
193  return 0;
194  }
195  if (this->GetTexturesStatus()[4] == false)
196  {
197  itkExceptionMacro(<< "Impossible to create Ratio image : texture not selected");
198  }
199  return static_cast<const OutputImageType *> (this->itk::ProcessObject::GetOutput(4));
200 }
201 template <class TInputImage, class TOutputImage>
205 {
206  if (this->GetNumberOfOutputs() < 5)
207  {
208  return 0;
209  }
210  if (this->GetTexturesStatus()[4] == false)
211  {
212  itkExceptionMacro(<< "Impossible to create Ratio image : texture not selected");
213  }
214  return static_cast<OutputImageType *>(this->itk::ProcessObject::GetOutput(4));
215 }
216 
217 // Return output SD image
218 template <class TInputImage, class TOutputImage>
222 {
223  if (this->GetNumberOfOutputs() < 6)
224  {
225  return 0;
226  }
227  if (this->GetTexturesStatus()[5] == false)
228  {
229  itkExceptionMacro(<< "Impossible to create SD image : texture not selected");
230  }
231  return static_cast<const OutputImageType *> (this->itk::ProcessObject::GetOutput(5));
232 }
233 template <class TInputImage, class TOutputImage>
237 {
238  if (this->GetNumberOfOutputs() < 6)
239  {
240  return 0;
241  }
242  if (this->GetTexturesStatus()[5] == false)
243  {
244  itkExceptionMacro(<< "Impossible to create SD image : texture not selected");
245  }
246 
247  return static_cast<OutputImageType *>(this->itk::ProcessObject::GetOutput(5));
248 }
249 
250 template <class TInputImage, class TOutputImage>
251 void
254 {
255  Superclass::BeforeThreadedGenerateData();
256  if (this->GetSpatialThreshold() < this->GetRatioMaxConsiderationNumber())
257  {
258  itkExceptionMacro(<< "Spatial Threshold (" << this->GetSpatialThreshold()
259  << ") is lower than Ration Max Consideration Number ("
260  << this->GetRatioMaxConsiderationNumber() << ") what is not allowed.");
261  }
262  for (unsigned int i = 0; i < this->GetNumberOfThreads(); ++i)
263  {
264  m_FunctorList.push_back(m_Functor);
265  }
266  this->InitFeatureStatus(true);
267 }
268 
269 template <class TInputImage, class TOutputImage>
270 void
273 {
274  // call the superclass' implementation of this method
275  Superclass::GenerateInputRequestedRegion();
276 
277  // get pointers to the input and output
278  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage *>(this->GetInput());
279  typename Superclass::OutputImagePointer outputPtr1 = this->GetOutput(0); //this->GetLengthOutput();
280  typename Superclass::OutputImagePointer outputPtr2 = this->GetOutput(1); //this->GetWidthOutput();
281  typename Superclass::OutputImagePointer outputPtr3 = this->GetOutput(2); //this->GetPSIOutput();
282  typename Superclass::OutputImagePointer outputPtr4 = this->GetOutput(3); //this->GetWMeanOutput();
283  typename Superclass::OutputImagePointer outputPtr5 = this->GetOutput(4); //this->GetRatioOutput();
284  typename Superclass::OutputImagePointer outputPtr6 = this->GetOutput(5); //this->GetSDOutput();
285 
286  if (!inputPtr || !outputPtr1 || !outputPtr2 || !outputPtr3 || !outputPtr4 || !outputPtr5 || !outputPtr6)
287  {
288  return;
289  }
290  // get a copy of the input requested region (should equal the output
291  // requested region)
292  typename TInputImage::RegionType inputRequestedRegion;
293  inputRequestedRegion = inputPtr->GetRequestedRegion();
294 
295  // pad the input requested region by the operator radius
296  InputImageSizeType rad;
297  rad[0] = m_Radius;
298  rad[1] = m_Radius;
299  inputRequestedRegion.PadByRadius(rad);
300 
301  // crop the input requested region at the input's largest possible region
302  if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
303  {
304  inputPtr->SetRequestedRegion(inputRequestedRegion);
305  return;
306  }
307  else
308  {
309  // Couldn't crop the region (requested region is outside the largest
310  // possible region). Throw an exception.
311 
312  // store what we tried to request (prior to trying to crop)
313  inputPtr->SetRequestedRegion(inputRequestedRegion);
314 
315  // build an exception
316  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
317  std::ostringstream msg;
318  msg << this->GetNameOfClass()
319  << "::GenerateInputRequestedRegion()";
320  e.SetLocation(msg.str().c_str());
321  e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
322  e.SetDataObject(inputPtr);
323  throw e;
324  }
325 }
326 
327 template <class TInputImage, class TOutputImage>
328 void
331 {
332  Superclass::GenerateOutputInformation();
333  //this->GetOutput()->SetNumberOfComponentsPerPixel(6);
334 }
335 
336 template <class TInputImage, class TOutputImage>
337 void
339 ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
340 {
342 
343 // We use dynamic_cast since inputs are stored as DataObjects. The
344 // ImageToImageFilter::GetInput(int) always returns a pointer to a
345 // TInputImage so it cannot be used for the second input.
346  InputImagePointerType inputPtr = dynamic_cast<const TInputImage*>(ProcessObjectType::GetInput(0));
347  OutputImagePointerType outputPtr1 = this->GetOutput(0);
348  OutputImagePointerType outputPtr2 = this->GetOutput(1);
349  OutputImagePointerType outputPtr3 = this->GetOutput(2);
350  OutputImagePointerType outputPtr4 = this->GetOutput(3);
351  OutputImagePointerType outputPtr5 = this->GetOutput(4);
352  OutputImagePointerType outputPtr6 = this->GetOutput(5);
353 
354  RadiusType r;
355  r.Fill(this->GetRadius());
356  NeighborhoodIteratorType neighInputIt;
357 
358  itk::ImageRegionIterator<TOutputImage> outputIt1, outputIt2, outputIt3, outputIt4, outputIt5, outputIt6;
359  FunctorOutputType outputFunctor;
360 
361  // Find the data-set boundary "faces"
364  faceList = bC(inputPtr, outputRegionForThread, r);
365 
367 
368  // support progress methods/callbacks
369  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
370 
371  // Process each of the boundary faces. These are N-d regions which border
372  // the edge of the buffer.
373 
374  std::vector<bool> textStatus = this->GetTexturesStatus();
375  for (fit = faceList.begin(); fit != faceList.end(); ++fit)
376  {
377  neighInputIt = itk::ConstNeighborhoodIterator<TInputImage>(r, inputPtr, *fit);
378 
379  outputIt1 = itk::ImageRegionIterator<TOutputImage>(outputPtr1, *fit);
380  outputIt2 = itk::ImageRegionIterator<TOutputImage>(outputPtr2, *fit);
381  outputIt3 = itk::ImageRegionIterator<TOutputImage>(outputPtr3, *fit);
382  outputIt4 = itk::ImageRegionIterator<TOutputImage>(outputPtr4, *fit);
383  outputIt5 = itk::ImageRegionIterator<TOutputImage>(outputPtr5, *fit);
384  outputIt6 = itk::ImageRegionIterator<TOutputImage>(outputPtr6, *fit);
385 
386  std::vector<itk::ImageRegionIterator<TOutputImage> *> outItList;
387  outItList.push_back(&outputIt1);
388  outItList.push_back(&outputIt2);
389  outItList.push_back(&outputIt3);
390  outItList.push_back(&outputIt4);
391  outItList.push_back(&outputIt5);
392  outItList.push_back(&outputIt6);
393 
394  neighInputIt.OverrideBoundaryCondition(&nbc);
395  neighInputIt.GoToBegin();
396 
397  for (unsigned int i = 0; i < outItList.size(); ++i)
398  {
399  (*outItList[i]).GoToBegin();
400  }
401 
402  while (!outputIt1.IsAtEnd())
403  {
404 
405  outputFunctor = m_FunctorList[threadId](neighInputIt);
406  for (unsigned int i = 0; i < outItList.size(); ++i)
407  {
408  if (textStatus[i] == true) (*outItList[i]).Set(outputFunctor[i]);
409  }
410 
411  ++neighInputIt;
412  for (unsigned int i = 0; i < outItList.size(); ++i)
413  {
414  ++(*outItList[i]);
415  }
416 
417  progress.CompletedPixel();
418  }
419  }
420 }
421 
422 template <class TInputImage, class TOutputImage>
423 void
426 {
427  for (FeatureType id = LENGTH; id <= SD;
428  id = static_cast<FeatureType>(id + 1))
429  {
430  this->SetFeatureStatus(static_cast<FeatureType>(id), status);
431  }
432 }
433 
437 template <class TInputImage, class TOutputImage>
438 void
440 ::PrintSelf(std::ostream& os, itk::Indent indent) const
441 {
442  Superclass::PrintSelf(os, indent);
443 
444  //os << indent << "Spatial Threshold : " << this->GetSpatialThreshold() << std::endl;
445  //os << indent << "Spectral Threshold : " << this->GetSpectralThreshold() << std::endl;
446  //os << indent << "Ratio Max Consideration Number: " << this->GetRatioMaxConsiderationNumber() << std::endl;
447  //os << indent << "Alpha : " << this->GetAlpha() << std::endl;
448  //os << indent << "Number Of Directions : " << this->GetNumberOfDirections() << std::endl;
449 
450 }
451 
452 } // end namespace otb
453 
454 #endif
virtual bool IsAtEnd() const
FunctorType::OutputType FunctorOutputType
const OutputImageType * GetWMeanOutput() const
void SetDataObject(DataObject *dobj)
virtual void SetDescription(const std::string &s)
virtual void SetLocation(const std::string &s)
virtual void OverrideBoundaryCondition(const ImageBoundaryConditionPointerType i)
void PrintSelf(std::ostream &os, itk::Indent indent) const
OutputImageType::Pointer OutputImagePointerType
const OutputImageType * GetSDOutput() const
virtual void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, itk::ThreadIdType threadId)
OutputImageType::RegionType OutputImageRegionType
const OutputImageType * GetRatioOutput() const
InputImageType::ConstPointer InputImagePointerType
NeighborhoodIteratorType::RadiusType RadiusType
const OutputImageType * GetWidthOutput() const
const OutputImageType * GetPSIOutput() const
InputImageType::SizeType InputImageSizeType
const OutputImageType * GetLengthOutput() const
unsigned int ThreadIdType