OTB  9.0.0
Orfeo Toolbox
otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.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 otbBinaryFunctorNeighborhoodJoinHistogramImageFilter_hxx
22 #define otbBinaryFunctorNeighborhoodJoinHistogramImageFilter_hxx
23 
25 #include "itkImageRegionIterator.h"
26 #include "itkNeighborhoodAlgorithm.h"
27 #include "itkProgressReporter.h"
28 
29 namespace otb
30 {
31 
35 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
37 {
38  this->SetNumberOfRequiredInputs(2);
39  m_Radius = 3;
40  m_UsePaddingValue = false;
41  m_UpperBoundIncreaseFactor = 0.001;
42 }
44 
48 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
50 {
51  // Process object is not const-correct so the const casting is required.
52  this->SetNthInput(0, const_cast<TInputImage1*>(image1));
53 }
54 
58 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
60 {
61  // Process object is not const-correct so the const casting is required.
62  this->SetNthInput(1, const_cast<TInputImage2*>(image2));
63 }
64 
65 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
67 {
68  if (this->GetNumberOfInputs() < 1)
69  {
70  return nullptr;
71  }
72  return static_cast<const TInputImage1*>(this->itk::ProcessObject::GetInput(0));
73 }
74 
75 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
77 {
78  if (this->GetNumberOfInputs() < 2)
79  {
80  return nullptr;
81  }
82  return static_cast<const TInputImage2*>(this->itk::ProcessObject::GetInput(1));
83 }
84 
85 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
87 {
88  // call the superclass' implementation of this method
89  Superclass::GenerateInputRequestedRegion();
90 
91  // get pointers to the input and output
92  Input1ImagePointer inputPtr1 = const_cast<TInputImage1*>(this->GetInput1());
93  Input2ImagePointer inputPtr2 = const_cast<TInputImage2*>(this->GetInput2());
94  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
95 
96  if (!inputPtr1 || !inputPtr2 || !outputPtr)
97  {
98  return;
99  }
100  // get a copy of the input requested region (should equal the output
101  // requested region)
102  typename TInputImage1::RegionType inputRequestedRegion1, inputRequestedRegion2;
103  inputRequestedRegion1 = inputPtr1->GetRequestedRegion();
104 
105  // pad the input requested region by the operator radius
106  inputRequestedRegion1.PadByRadius(m_Radius);
107  inputRequestedRegion2 = inputRequestedRegion1;
108 
109  // crop the input requested region at the input's largest possible region
110  if (inputRequestedRegion1.Crop(inputPtr1->GetLargestPossibleRegion()))
111  {
112  inputPtr1->SetRequestedRegion(inputRequestedRegion1);
113  }
114  else
115  {
116  // Couldn't crop the region (requested region is outside the largest
117  // possible region). Throw an exception.
118 
119  // store what we tried to request (prior to trying to crop)
120  inputPtr1->SetRequestedRegion(inputRequestedRegion1);
121 
122  // build an exception
123  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
124  std::ostringstream msg;
125  msg << this->GetNameOfClass() << "::GenerateInputRequestedRegion()";
126  e.SetLocation(msg.str());
127  e.SetDescription("Requested region is (at least partially) outside the largest possible region of image 1.");
128  e.SetDataObject(inputPtr1);
129  throw e;
130  }
131  if (inputRequestedRegion2.Crop(inputPtr2->GetLargestPossibleRegion()))
132  {
133  inputPtr2->SetRequestedRegion(inputRequestedRegion2);
134  }
135  else
136  {
137  // Couldn't crop the region (requested region is outside the largest
138  // possible region). Throw an exception.
139 
140  // store what we tried to request (prior to trying to crop)
141  inputPtr2->SetRequestedRegion(inputRequestedRegion2);
142 
143  // build an exception
144  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
145  std::ostringstream msg;
146  msg << this->GetNameOfClass() << "::GenerateInputRequestedRegion()";
147  e.SetLocation(msg.str());
148  e.SetDescription("Requested region is (at least partially) outside the largest possible region of image 1.");
149  e.SetDataObject(inputPtr2);
150  throw e;
151  }
152  return;
153 }
154 
155 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
157 {
158  this->ComputeHistogram();
159 }
160 
164 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
166 {
167  // Calculate min and max image values in input1 image.
168  Input1ImageConstPointer pInput1Image = dynamic_cast<const TInputImage1*>(ProcessObjectType::GetInput(0));
169 
170  Input1ImagePixelType minInput1, maxInput1;
171  itk::ImageRegionConstIterator<Input1ImageType> fiIt(pInput1Image, pInput1Image->GetBufferedRegion());
172  fiIt.GoToBegin();
173  minInput1 = fiIt.Value();
174  maxInput1 = fiIt.Value();
175  ++fiIt;
176  while (!fiIt.IsAtEnd())
177  {
178  Input1ImagePixelType value = fiIt.Value();
179 
180  if (value < minInput1)
181  {
182  minInput1 = value;
183  }
184  else if (value > maxInput1)
185  {
186  maxInput1 = value;
187  }
188 
189  ++fiIt;
190  }
191 
192  // Calculate min and max image values in input2 image.
193  Input2ImageConstPointer pInput2Image = dynamic_cast<const TInputImage2*>(ProcessObjectType::GetInput(1));
194  Input2ImagePixelType minInput2, maxInput2;
195  itk::ImageRegionConstIterator<Input2ImageType> miIt(pInput2Image, pInput2Image->GetBufferedRegion());
196  miIt.GoToBegin();
197  minInput2 = miIt.Value();
198  maxInput2 = miIt.Value();
199  ++miIt;
200  while (!miIt.IsAtEnd())
201  {
202  Input2ImagePixelType value = miIt.Value();
203 
204  if (value < minInput2)
205  {
206  minInput2 = value;
207  }
208  else if (value > maxInput2)
209  {
210  maxInput2 = value;
211  }
212  ++miIt;
213  }
214 
215 
216  // Set the size of the upper and lower bounds of the histogram:
217  MeasurementVectorType lowerBound, upperBound;
218  lowerBound.SetSize(2);
219  upperBound.SetSize(2);
220 
221  // Initialize the upper and lower bounds of the histogram.
222  lowerBound[0] = minInput1;
223  lowerBound[1] = minInput2;
224  upperBound[0] = maxInput1 + (maxInput1 - minInput1) * m_UpperBoundIncreaseFactor;
225  upperBound[1] = maxInput2 + (maxInput2 - minInput2) * m_UpperBoundIncreaseFactor;
226 
227  typedef itk::ImageRegionConstIteratorWithIndex<Input1ImageType> Input1IteratorType;
228  typedef itk::ImageRegionConstIteratorWithIndex<Input2ImageType> Input2IteratorType;
229 
230  typename Input1ImageType::RegionType input1Region;
231  typename Input1ImageType::RegionType input2Region;
232 
233  input1Region = pInput1Image->GetRequestedRegion();
234  Input1IteratorType ti1(pInput1Image, input1Region);
235 
236  input2Region = pInput2Image->GetRequestedRegion();
237  Input2IteratorType ti2(pInput2Image, input2Region);
238 
239  typename HistogramType::Pointer histogram = HistogramType::New();
240  HistogramSizeType histogramSize(2);
241  histogramSize.Fill(256);
242  histogram->SetMeasurementVectorSize(2);
243  histogram->Initialize(histogramSize, lowerBound, upperBound);
244 
245  ti1.GoToBegin();
246  ti2.GoToBegin();
247  while (!ti1.IsAtEnd() && !ti2.IsAtEnd())
248  {
249 
250  typename HistogramType::IndexType sample(2);
251  sample[0] = ti1.Get();
252  sample[1] = ti2.Get();
253  if (sample[0] != itk::NumericTraits<Input1ImagePixelType>::Zero && sample[1] != itk::NumericTraits<Input2ImagePixelType>::Zero)
254  histogram->IncreaseFrequencyOfIndex(sample, 1);
255 
256  ++ti1;
257  ++ti2;
258  }
259 
260  m_Histogram = histogram;
261 }
262 
266 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
268  const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
269 {
270  itk::ZeroFluxNeumannBoundaryCondition<TInputImage1> nbc1;
271  itk::ZeroFluxNeumannBoundaryCondition<TInputImage2> nbc2;
272 
273  // We use dynamic_cast since inputs are stored as DataObjects. The
274  // ImageToJoinHistogramImageFilter::GetInput(int) always returns a pointer to a
275  // TInputImage1 so it cannot be used for the second input.
276  Input1ImageConstPointer inputPtr1 = dynamic_cast<const TInputImage1*>(ProcessObjectType::GetInput(0));
277  Input2ImageConstPointer inputPtr2 = dynamic_cast<const TInputImage2*>(ProcessObjectType::GetInput(1));
278  OutputImagePointer outputPtr = this->GetOutput(0);
279 
280  RadiusType1 r1;
281  r1.Fill(m_Radius);
282  NeighborhoodIteratorType1 neighInputIt1;
283 
284  RadiusType2 r2;
285  r2.Fill(m_Radius);
286  NeighborhoodIteratorType2 neighInputIt2;
287 
288  itk::ImageRegionIterator<TOutputImage> outputIt;
289 
290  // Find the data-set boundary "faces"
291  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage1>::FaceListType faceList1;
292  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage1> bC1;
293  faceList1 = bC1(inputPtr1, outputRegionForThread, r1);
294 
295  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage2>::FaceListType faceList2;
296  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage2> bC2;
297  faceList2 = bC2(inputPtr2, outputRegionForThread, r2);
298 
299  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage1>::FaceListType::iterator fit1;
300  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage2>::FaceListType::iterator fit2;
301 
302  // support progress methods/callbacks
303  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
304 
305  // Process each of the boundary faces. These are N-d regions which border
306  // the edge of the buffer.
307  for (fit1 = faceList1.begin(), fit2 = faceList2.begin(); fit1 != faceList1.end() && fit2 != faceList2.end(); ++fit1, ++fit2)
308  {
309  neighInputIt1 = itk::ConstNeighborhoodIterator<TInputImage1>(r1, inputPtr1, *fit1);
310  neighInputIt2 = itk::ConstNeighborhoodIterator<TInputImage2>(r1, inputPtr2, *fit2);
311  outputIt = itk::ImageRegionIterator<TOutputImage>(outputPtr, outputRegionForThread);
312 
313  outputIt = itk::ImageRegionIterator<TOutputImage>(outputPtr, *fit1);
314  neighInputIt1.OverrideBoundaryCondition(&nbc1);
315  neighInputIt1.GoToBegin();
316  neighInputIt2.OverrideBoundaryCondition(&nbc2);
317  neighInputIt2.GoToBegin();
318 
319  while (!outputIt.IsAtEnd())
320  {
321 
322  outputIt.Set(m_Functor(neighInputIt1, neighInputIt2, m_Histogram));
323 
324  ++neighInputIt1;
325  ++neighInputIt2;
326  ++outputIt;
327  progress.CompletedPixel();
328  }
329  }
330 }
331 
332 } // end namespace otb
333 
334 #endif
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter::SetInput2
void SetInput2(const TInputImage2 *image2)
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.hxx:59
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter::GetInput2
const TInputImage2 * GetInput2()
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.hxx:76
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter::GetInput1
const TInputImage1 * GetInput1()
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.hxx:66
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::Input2ImageConstPointer
Input2ImageType::ConstPointer Input2ImageConstPointer
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:68
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter::BinaryFunctorNeighborhoodJoinHistogramImageFilter
BinaryFunctorNeighborhoodJoinHistogramImageFilter()
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.hxx:36
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::OutputImageRegionType
OutputImageType::RegionType OutputImageRegionType
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:73
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::Input2ImagePointer
Input2ImageType::Pointer Input2ImagePointer
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:67
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::Input1ImageConstPointer
Input1ImageType::ConstPointer Input1ImageConstPointer
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:63
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter::ComputeHistogram
void ComputeHistogram()
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.hxx:165
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::NeighborhoodIteratorType1
itk::ConstNeighborhoodIterator< TInputImage1 > NeighborhoodIteratorType1
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:78
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter::SetInput1
void SetInput1(const TInputImage1 *image1)
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.hxx:49
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::OutputImagePointer
OutputImageType::Pointer OutputImagePointer
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:72
otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::MeasurementVectorType
HistogramType::MeasurementVectorType MeasurementVectorType
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:90
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter::GenerateInputRequestedRegion
void GenerateInputRequestedRegion(void) override
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.hxx:86
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::Input1ImagePointer
Input1ImageType::Pointer Input1ImagePointer
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:62
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::Input1ImagePixelType
Input1ImageType::PixelType Input1ImagePixelType
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:65
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::HistogramSizeType
HistogramType::SizeType HistogramSizeType
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:91
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::RadiusType1
NeighborhoodIteratorType1::RadiusType RadiusType1
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:81
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::NeighborhoodIteratorType2
itk::ConstNeighborhoodIterator< TInputImage2 > NeighborhoodIteratorType2
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:79
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::Input2ImagePixelType
Input2ImageType::PixelType Input2ImagePixelType
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:70
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter< TInputImage1, TInputImage2, TOutputImage, Functor::JoinHistogramMI< itk::ConstNeighborhoodIterator< TInputImage1 >, itk::ConstNeighborhoodIterator< TInputImage2 >, TOutputImage::PixelType > >::RadiusType2
NeighborhoodIteratorType2::RadiusType RadiusType2
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.h:82
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter::BeforeThreadedGenerateData
void BeforeThreadedGenerateData() override
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.hxx:156
otb::BinaryFunctorNeighborhoodJoinHistogramImageFilter::ThreadedGenerateData
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, itk::ThreadIdType threadId) override
Definition: otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.hxx:267