OTB  10.0.0
Orfeo Toolbox
otbConvolutionImageFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2024 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 otbConvolutionImageFilter_hxx
22 #define otbConvolutionImageFilter_hxx
24 
25 #include "itkConstNeighborhoodIterator.h"
26 #include "itkImageRegionIterator.h"
27 #include "itkOffset.h"
28 #include "itkProgressReporter.h"
29 #include "itkConstantBoundaryCondition.h"
30 
31 #include "otbMacro.h"
32 
33 
34 namespace otb
35 {
36 
37 template <class TInputImage, class TOutputImage, class TBoundaryCondition, class TFilterPrecision>
39 {
40  m_Radius.Fill(1);
41  m_Filter.SetSize(3 * 3);
42  m_Filter.Fill(1);
43  m_NormalizeFilter = false;
44 }
45 
46 template <class TInputImage, class TOutputImage, class TBoundaryCondition, class TFilterPrecision>
48 {
49  // call the superclass' implementation of this method
50  Superclass::GenerateInputRequestedRegion();
51 
52  // get pointers to the input and output
53  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage*>(this->GetInput());
54  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
55 
56  if (!inputPtr || !outputPtr)
57  {
58  return;
59  }
60 
61  // get a copy of the input requested region (should equal the output
62  // requested region)
63  typename TInputImage::RegionType inputRequestedRegion;
64  inputRequestedRegion = inputPtr->GetRequestedRegion();
65 
66  // pad the input requested region by the operator radius
67  inputRequestedRegion.PadByRadius(m_Radius);
68  otbMsgDevMacro(<< "Padding by " << m_Radius);
69  otbMsgDevMacro(<< "Region is now " << inputRequestedRegion.GetIndex() << ", " << inputRequestedRegion.GetSize());
70 
71  // crop the input requested region at the input's largest possible region
72  if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
73  {
74  inputPtr->SetRequestedRegion(inputRequestedRegion);
75  return;
76  }
77  else
78  {
79  // Couldn't crop the region (requested region is outside the largest
80  // possible region). Throw an exception.
81 
82  // store what we tried to request (prior to trying to crop)
83  inputPtr->SetRequestedRegion(inputRequestedRegion);
84 
85  // build an exception
86  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
87  e.SetLocation(ITK_LOCATION);
88  e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
89  e.SetDataObject(inputPtr);
90  throw e;
91  }
92 }
93 
94 template <class TInputImage, class TOutputImage, class TBoundaryCondition, class TFilterPrecision>
96  const OutputImageRegionType& outputRegionForThread)
97 {
98  // Allocate output
99  typename OutputImageType::Pointer output = this->GetOutput();
100  typename InputImageType::ConstPointer input = this->GetInput();
101 
102 
103  InputRealType sum = itk::NumericTraits<InputRealType>::Zero;
104 
105  InputImageRegionType inputRegionForThread;
106  this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
107 
108  itk::ConstNeighborhoodIterator<InputImageType, BoundaryConditionType> inputIt(m_Radius, input, inputRegionForThread);
109  itk::ImageRegionIterator<OutputImageType> outputIt(output, outputRegionForThread);
110 
111  inputIt.GoToBegin();
112  const unsigned int neighborhoodSize = inputIt.Size();
113 
114 
115  // Compute the norm of the filter
116  if (m_NormalizeFilter)
117  {
118  InputRealType norm = itk::NumericTraits<InputRealType>::Zero;
119  for (unsigned int i = 0; i < neighborhoodSize; ++i)
120  {
121  norm += static_cast<InputRealType>(std::abs(m_Filter(i)));
122  }
123  const double norm_double = 1. / static_cast<double>(std::abs(norm));
124 
125  while (!inputIt.IsAtEnd())
126  {
127  sum = itk::NumericTraits<InputRealType>::Zero;
128 
129  for (unsigned int i = 0; i < neighborhoodSize; ++i)
130  {
131  sum += static_cast<InputRealType>(inputIt.GetPixel(i) * m_Filter(i));
132  }
133 
134  // get the mean value
135  outputIt.Set(static_cast<OutputPixelType>(sum * norm_double));
136 
137  ++inputIt;
138  ++outputIt;
139  }
140  }
141  else
142  {
143  while (!inputIt.IsAtEnd())
144  {
145  sum = itk::NumericTraits<InputRealType>::Zero;
146 
147  for (unsigned int i = 0; i < neighborhoodSize; ++i)
148  {
149  sum += static_cast<InputRealType>(inputIt.GetPixel(i) * m_Filter(i));
150  }
151 
152  outputIt.Set(static_cast<OutputPixelType>(sum));
153 
154  ++inputIt;
155  ++outputIt;
156  }
157  }
158 }
159 
163 template <class TInputImage, class TOutput, class TBoundaryCondition, class TFilterPrecision>
165 {
166  Superclass::PrintSelf(os, indent);
167  os << indent << "Radius: " << m_Radius << '\n';
168 }
170 
171 } // end namespace otb
172 
173 #endif
InputImageType::RegionType InputImageRegionType
OutputImageType::RegionType OutputImageRegionType
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) override
itk::NumericTraits< InputPixelType >::RealType InputRealType
OutputImageType::PixelType OutputPixelType
void PrintSelf(std::ostream &os, itk::Indent indent) const override
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
#define otbMsgDevMacro(x)
Definition: otbMacro.h:116