OTB  10.0.0
Orfeo Toolbox
otbBCOInterpolateImageFunction.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 otbBCOInterpolateImageFunction_hxx
22 #define otbBCOInterpolateImageFunction_hxx
23 
25 
26 #include "itkNumericTraits.h"
27 
28 namespace otb
29 {
30 
31 template <class TInputImage, class TCoordRep>
32 void BCOInterpolateImageFunctionBase<TInputImage, TCoordRep>::PrintSelf(std::ostream& os, itk::Indent indent) const
33 {
34  Superclass::PrintSelf(os, indent);
35  os << indent << "Radius: " << m_Radius << std::endl;
36  os << indent << "Alpha: " << m_Alpha << std::endl;
37 }
38 
39 template <class TInputImage, class TCoordRep>
41 {
42  if (radius < 2)
43  {
44  itkExceptionMacro(<< "Radius must be strictly greater than 1");
45  }
46  else
47  {
48  m_Radius = radius;
49  m_WinSize = 2 * m_Radius + 1;
50  }
51 }
52 
53 template <class TInputImage, class TCoordRep>
54 typename itk::InterpolateImageFunction<TInputImage, TCoordRep>::SizeType BCOInterpolateImageFunctionBase<TInputImage, TCoordRep>::GetRadius() const
55 {
56  typename itk::InterpolateImageFunction<TInputImage, TCoordRep>::SizeType radius({m_Radius,m_Radius});
57  return radius;
58 }
59 
60 template <class TInputImage, class TCoordRep>
62 {
63  m_Alpha = alpha;
64 }
65 
66 template <class TInputImage, class TCoordRep>
68 {
69  return m_Alpha;
70 }
71 
72 template <class TInputImage, class TCoordRep>
75 {
76  double offset, dist, position, step;
77 
79 
80  offset = indexValue - itk::Math::Floor<IndexValueType>(indexValue + 0.5);
81 
82  // Compute BCO coefficients
83  step = 4. / static_cast<double>(2 * m_Radius);
84  position = -static_cast<double>(m_Radius) * step;
85 
86  double sum = 0.0;
87  auto alpha = this->m_Alpha;
88 
89  for (unsigned int i = 0; i < m_WinSize; ++i)
90  {
91  // Compute the BCO coefficients according to alpha.
92  dist = std::abs(position - offset * step);
93 
94  double coef;
95  if (dist <= 2.)
96  {
97  if (dist <= 1.)
98  {
99  coef = (alpha + 2.) * dist * dist * dist - (alpha + 3.) * dist * dist + 1;
100  }
101  else
102  {
103  coef = alpha * dist * dist * dist - 5 * alpha * dist * dist + 8 * alpha * dist - 4 * alpha;
104  }
105  }
106  else
107  {
108  coef = 0.0;
109  }
110 
111  sum += coef;
112  position += step;
113 
114  bcoCoef[i] = coef;
115  }
116 
117  for (unsigned int i = 0; i < m_WinSize; ++i)
118  bcoCoef[i] /= sum;
119 
120  return bcoCoef;
121 }
122 
123 template <class TInputImage, class TCoordRep>
124 void BCOInterpolateImageFunction<TInputImage, TCoordRep>::PrintSelf(std::ostream& os, itk::Indent indent) const
125 {
126  Superclass::PrintSelf(os, indent);
127 }
128 
129 template <class TInputImage, class TCoordRep>
132 {
133  unsigned int dim;
134 
135  IndexType baseIndex;
136  IndexType neighIndex;
137 
138  RealType value = itk::NumericTraits<RealType>::Zero;
139 
140  const auto& BCOCoefX = this->EvaluateCoef(index[0]);
141  const auto& BCOCoefY = this->EvaluateCoef(index[1]);
142 
143  // Compute base index = closet index
144  for (dim = 0; dim < ImageDimension; dim++)
145  {
146  baseIndex[dim] = itk::Math::Floor<IndexValueType>(index[dim] + 0.5);
147  }
148 
149  for (unsigned int i = 0; i < this->m_WinSize; ++i)
150  {
151  RealType lineRes = 0.;
152  for (unsigned int j = 0; j < this->m_WinSize; ++j)
153  {
154  // get neighbor index
155  neighIndex[0] = baseIndex[0] + i - this->m_Radius;
156  neighIndex[1] = baseIndex[1] + j - this->m_Radius;
157 
158  if (neighIndex[0] > this->m_EndIndex[0])
159  {
160  neighIndex[0] = this->m_EndIndex[0];
161  }
162  if (neighIndex[0] < this->m_StartIndex[0])
163  {
164  neighIndex[0] = this->m_StartIndex[0];
165  }
166  if (neighIndex[1] > this->m_EndIndex[1])
167  {
168  neighIndex[1] = this->m_EndIndex[1];
169  }
170  if (neighIndex[1] < this->m_StartIndex[1])
171  {
172  neighIndex[1] = this->m_StartIndex[1];
173  }
174  lineRes += static_cast<RealType>(this->GetInputImage()->GetPixel(neighIndex)) * BCOCoefY[j];
175  }
176  value += lineRes * BCOCoefX[i];
177  }
178 
179 
180  return (static_cast<OutputType>(value));
181 }
182 
183 template <typename TPixel, unsigned int VImageDimension, class TCoordRep>
184 void BCOInterpolateImageFunction<otb::VectorImage<TPixel, VImageDimension>, TCoordRep>::PrintSelf(std::ostream& os, itk::Indent indent) const
185 {
186  Superclass::PrintSelf(os, indent);
187 }
188 
189 template <typename TPixel, unsigned int VImageDimension, class TCoordRep>
191 BCOInterpolateImageFunction<otb::VectorImage<TPixel, VImageDimension>, TCoordRep>::EvaluateAtContinuousIndex(const ContinuousIndexType& index) const
192 {
193  typedef typename itk::NumericTraits<InputPixelType>::ScalarRealType ScalarRealType;
194 
195 
196  unsigned int dim;
197  unsigned int componentNumber = this->GetInputImage()->GetNumberOfComponentsPerPixel();
198 
199  IndexType baseIndex;
200  IndexType neighIndex;
201 
202  boost::container::small_vector<ScalarRealType, 8> lineRes(componentNumber);
203 
204  OutputType output(componentNumber);
205  output.Fill(itk::NumericTraits<ScalarRealType>::Zero);
206 
207  const auto& BCOCoefX = this->EvaluateCoef(index[0]);
208  const auto& BCOCoefY = this->EvaluateCoef(index[1]);
209 
210  // Compute base index = closet index
211  for (dim = 0; dim < ImageDimension; dim++)
212  {
213  baseIndex[dim] = itk::Math::Floor<IndexValueType>(index[dim] + 0.5);
214  }
215 
216  for (unsigned int i = 0; i < this->m_WinSize; ++i)
217  {
218  std::fill(lineRes.begin(), lineRes.end(), itk::NumericTraits<ScalarRealType>::Zero);
219  for (unsigned int j = 0; j < this->m_WinSize; ++j)
220  {
221  // get neighbor index
222  neighIndex[0] = baseIndex[0] + i - this->m_Radius;
223  neighIndex[1] = baseIndex[1] + j - this->m_Radius;
224  if (neighIndex[0] > this->m_EndIndex[0])
225  {
226  neighIndex[0] = this->m_EndIndex[0];
227  }
228  if (neighIndex[0] < this->m_StartIndex[0])
229  {
230  neighIndex[0] = this->m_StartIndex[0];
231  }
232  if (neighIndex[1] > this->m_EndIndex[1])
233  {
234  neighIndex[1] = this->m_EndIndex[1];
235  }
236  if (neighIndex[1] < this->m_StartIndex[1])
237  {
238  neighIndex[1] = this->m_StartIndex[1];
239  }
240 
241  const InputPixelType& pixel = this->GetInputImage()->GetPixel(neighIndex);
242  for (unsigned int k = 0; k < componentNumber; ++k)
243  {
244  lineRes[k] += pixel.GetElement(k) * BCOCoefY[j];
245  }
246  }
247  for (unsigned int k = 0; k < componentNumber; ++k)
248  {
249  output[k] += lineRes[k] * BCOCoefX[i];
250  }
251  }
252 
253  return (output);
254 }
255 
256 } // namespace otb
257 
258 #endif
CoefContainerType EvaluateCoef(const ContinuousIndexValueType &indexValue) const
boost::container::small_vector< double, 7 > CoefContainerType
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Interpolate an image at specified positions using bicubic interpolation.
Superclass::ContinuousIndexType ContinuousIndexType
OutputType EvaluateAtContinuousIndex(const ContinuousIndexType &index) const override
void PrintSelf(std::ostream &os, itk::Indent indent) const override
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.