OTB  6.1.0
Orfeo Toolbox
otbBinaryFunctorNeighborhoodImageFilter.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 otbBinaryFunctorNeighborhoodImageFilter_txx
22 #define otbBinaryFunctorNeighborhoodImageFilter_txx
23 
25 #include "itkImageRegionIterator.h"
27 #include "itkProgressReporter.h"
28 
29 namespace otb
30 {
31 
35 template <class TInputImage1, class TInputImage2,
36  class TOutputImage, class TFunction>
39 {
40  this->SetNumberOfRequiredInputs(2);
41  m_Radius.Fill(3);
42 }
44 
48 template <class TInputImage1, class TInputImage2,
49  class TOutputImage, class TFunction>
50 void
52 ::SetInput1(const TInputImage1 * image1)
53 {
54  // Process object is not const-correct so the const casting is required.
55  this->SetNthInput(0, const_cast<TInputImage1 *>(image1));
56 }
57 
61 template <class TInputImage1, class TInputImage2,
62  class TOutputImage, class TFunction>
63 void
65 ::SetInput2(const TInputImage2 * image2)
66 {
67  // Process object is not const-correct so the const casting is required.
68  this->SetNthInput(1, const_cast<TInputImage2 *>(image2));
69 }
70 
71 template <class TInputImage1, class TInputImage2,
72  class TOutputImage, class TFunction>
73 const TInputImage1 *
76 {
77  if (this->GetNumberOfInputs() < 1)
78  {
79  return ITK_NULLPTR;
80  }
81  return static_cast<const TInputImage1 *>(this->itk::ProcessObject::GetInput(0));
82 }
83 
84 template <class TInputImage1, class TInputImage2,
85  class TOutputImage, class TFunction>
86 const TInputImage2 *
89 {
90  if (this->GetNumberOfInputs() < 2)
91  {
92  return ITK_NULLPTR;
93  }
94  return static_cast<const TInputImage2 *>(this->itk::ProcessObject::GetInput(1));
95 }
96 
97 template <class TInputImage1, class TInputImage2,
98  class TOutputImage, class TFunction>
99 void
102 {
103  // call the superclass' implementation of this method
104  Superclass::GenerateInputRequestedRegion();
105 
106  // get pointers to the input and output
107  Input1ImagePointer inputPtr1 =
108  const_cast<TInputImage1 *>(this->GetInput1());
109  Input2ImagePointer inputPtr2 =
110  const_cast<TInputImage2 *>(this->GetInput2());
111  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
112 
113  if (!inputPtr1 || !inputPtr2 || !outputPtr)
114  {
115  return;
116  }
117  // get a copy of the input requested region (should equal the output
118  // requested region)
119  typename TInputImage1::RegionType inputRequestedRegion1, inputRequestedRegion2;
120  inputRequestedRegion1 = inputPtr1->GetRequestedRegion();
121 
122  // pad the input requested region by the operator radius
123  inputRequestedRegion1.PadByRadius(m_Radius);
124  inputRequestedRegion2 = inputRequestedRegion1;
125 
126  // crop the input requested region at the input's largest possible region
127  if (inputRequestedRegion1.Crop(inputPtr1->GetLargestPossibleRegion()))
128  {
129  inputPtr1->SetRequestedRegion(inputRequestedRegion1);
130  }
131  else
132  {
133  // Couldn't crop the region (requested region is outside the largest
134  // possible region). Throw an exception.
135 
136  // store what we tried to request (prior to trying to crop)
137  inputPtr1->SetRequestedRegion(inputRequestedRegion1);
138 
139  // build an exception
140  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
141  std::ostringstream msg;
142  msg << this->GetNameOfClass()
143  << "::GenerateInputRequestedRegion()";
144  e.SetLocation(msg.str().c_str());
145  e.SetDescription("Requested region is (at least partially) outside the largest possible region of image 1.");
146  e.SetDataObject(inputPtr1);
147  throw e;
148  }
149  if (inputRequestedRegion2.Crop(inputPtr2->GetLargestPossibleRegion()))
150  {
151  inputPtr2->SetRequestedRegion(inputRequestedRegion2);
152  }
153  else
154  {
155  // Couldn't crop the region (requested region is outside the largest
156  // possible region). Throw an exception.
157 
158  // store what we tried to request (prior to trying to crop)
159  inputPtr2->SetRequestedRegion(inputRequestedRegion2);
160 
161  // build an exception
162  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
163  std::ostringstream msg;
164  msg << this->GetNameOfClass()
165  << "::GenerateInputRequestedRegion()";
166  e.SetLocation(msg.str().c_str());
167  e.SetDescription("Requested region is (at least partially) outside the largest possible region of image 1.");
168  e.SetDataObject(inputPtr2);
169  throw e;
170  }
171  return;
172 }
173 
177 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
178 void
180 ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
181  itk::ThreadIdType threadId)
182 {
183 
184  //unsigned int i;
187 
188 // We use dynamic_cast since inputs are stored as DataObjects. The
189 // ImageToImageFilter::GetInput(int) always returns a pointer to a
190 // TInputImage1 so it cannot be used for the second input.
191  Input1ImageConstPointer inputPtr1
192  = dynamic_cast<const TInputImage1*>(ProcessObjectType::GetInput(0));
193  Input2ImageConstPointer inputPtr2
194  = dynamic_cast<const TInputImage2*>(ProcessObjectType::GetInput(1));
195  OutputImagePointer outputPtr = this->GetOutput(0);
196 
197  RadiusType1 r1;
198  r1[0] = m_Radius[0];
199  r1[1] = m_Radius[1];
200  NeighborhoodIteratorType1 neighInputIt1;
201 
202  RadiusType2 r2;
203  r2[0] = m_Radius[0];
204  r2[1] = m_Radius[1];
205  NeighborhoodIteratorType2 neighInputIt2;
206 
208 
209  // Find the data-set boundary "faces"
212  faceList1 = bC1(inputPtr1, outputRegionForThread, r1);
213 
216  faceList2 = bC2(inputPtr2, outputRegionForThread, r2);
217 
220 
221  // support progress methods/callbacks
222  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
223 
224  // Process each of the boundary faces. These are N-d regions which border
225  // the edge of the buffer.
226  for (fit1 = faceList1.begin(), fit2 = faceList2.begin();
227  fit1 != faceList1.end() && fit2 != faceList2.end();
228  ++fit1, ++fit2)
229  {
230  neighInputIt1 = itk::ConstNeighborhoodIterator<TInputImage1>(r1, inputPtr1, *fit1);
231  neighInputIt2 = itk::ConstNeighborhoodIterator<TInputImage2>(r2, inputPtr2, *fit2);
232  // outputIt = itk::ImageRegionIterator<TOutputImage>(outputPtr, outputRegionForThread);
233 
234  outputIt = itk::ImageRegionIterator<TOutputImage>(outputPtr, *fit1);
235  neighInputIt1.OverrideBoundaryCondition(&nbc1);
236  neighInputIt1.GoToBegin();
237  neighInputIt2.OverrideBoundaryCondition(&nbc2);
238  neighInputIt2.GoToBegin();
239 
240  while (!outputIt.IsAtEnd())
241  {
242 
243  outputIt.Set(m_Functor(neighInputIt1, neighInputIt2));
244 
245  ++neighInputIt1;
246  ++neighInputIt2;
247  ++outputIt;
248  progress.CompletedPixel();
249  }
250  }
251 
252 }
253 
254 } // end namespace otb
255 
256 #endif
virtual bool IsAtEnd() 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)
OutputImageType::Pointer OutputImagePointer
unsigned int ThreadIdType
DataObject * GetInput(const DataObjectIdentifierType &key)
OutputImageType::RegionType OutputImageRegionType
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, itk::ThreadIdType threadId) ITK_OVERRIDE