21 #ifndef otbBSplineInterpolateImageFunction_hxx
22 #define otbBSplineInterpolateImageFunction_hxx
24 #include "itkImageLinearIteratorWithIndex.h"
25 #include "itkImageRegionConstIteratorWithIndex.h"
26 #include "itkImageRegionIterator.h"
28 #include "itkVector.h"
30 #include "itkMatrix.h"
38 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
51 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
54 Superclass::PrintSelf(os, indent);
55 os << indent <<
"Spline Order: " << m_SplineOrder << std::endl;
59 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
62 m_CoefficientFilter->GetOutput()->UpdateOutputInformation();
63 m_CoefficientFilter->GetOutput()->SetRequestedRegion(m_CoefficientFilter->GetInput()->GetBufferedRegion());
64 m_CoefficientFilter->GetOutput()->PropagateRequestedRegion();
65 m_CoefficientFilter->GetOutput()->UpdateOutputData();
66 m_Coefficients = m_CoefficientFilter->GetOutput();
67 m_CurrentBufferedRegion = m_CoefficientFilter->GetInput()->GetBufferedRegion();
69 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
74 m_CoefficientFilter->SetInput(inputData);
81 UpdateCoefficientsFilter();
85 Superclass::SetInputImage(inputData);
87 m_DataLength = inputData->GetBufferedRegion().GetSize();
91 m_Coefficients =
nullptr;
95 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
98 if (SplineOrder == m_SplineOrder)
102 m_SplineOrder = SplineOrder;
103 m_CoefficientFilter->SetSplineOrder(SplineOrder);
106 m_MaxNumberInterpolationPoints = 1;
107 for (
unsigned int n = 0; n < ImageDimension; ++n)
109 m_MaxNumberInterpolationPoints *= (m_SplineOrder + 1);
111 this->GeneratePointsToIndex();
114 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
119 vnl_matrix<long> EvaluateIndex(ImageDimension, (m_SplineOrder + 1));
122 this->DetermineRegionOfSupport(EvaluateIndex, x, m_SplineOrder);
125 vnl_matrix<double> weights(ImageDimension, (m_SplineOrder + 1));
126 SetInterpolationWeights(x, EvaluateIndex, weights, m_SplineOrder);
135 this->ApplyMirrorBoundaryConditions(EvaluateIndex, m_SplineOrder);
138 double interpolated = 0.0;
141 for (
unsigned int p = 0; p < m_MaxNumberInterpolationPoints; ++p)
147 for (
unsigned int n = 0; n < ImageDimension; ++n)
149 w *= weights[n][m_PointsToIndex[p][n]];
150 coefficientIndex[n] = EvaluateIndex[n][m_PointsToIndex[p][n]];
156 interpolated += w * m_Coefficients->GetPixel(coefficientIndex);
178 return (interpolated);
181 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
185 UpdateCoefficientsFilter();
186 vnl_matrix<long> EvaluateIndex(ImageDimension, (m_SplineOrder + 1));
190 this->DetermineRegionOfSupport(EvaluateIndex, x, m_SplineOrder);
193 vnl_matrix<double> weights(ImageDimension, (m_SplineOrder + 1));
194 SetInterpolationWeights(x, EvaluateIndex, weights, m_SplineOrder);
196 vnl_matrix<double> weightsDerivative(ImageDimension, (m_SplineOrder + 1));
197 SetDerivativeWeights(x, EvaluateIndex, weightsDerivative, (m_SplineOrder));
200 this->ApplyMirrorBoundaryConditions(EvaluateIndex, m_SplineOrder);
206 for (
unsigned int n = 0; n < ImageDimension; ++n)
208 derivativeValue[n] = 0.0;
209 for (
unsigned int p = 0; p < m_MaxNumberInterpolationPoints; ++p)
212 for (
unsigned int n1 = 0; n1 < ImageDimension; n1++)
215 coefficientIndex[n1] = EvaluateIndex[n1][m_PointsToIndex[p][n1]];
220 tempValue *= weightsDerivative[n1][m_PointsToIndex[p][n1]];
224 tempValue *= weights[n1][m_PointsToIndex[p][n1]];
227 derivativeValue[n] += m_Coefficients->GetPixel(coefficientIndex) * tempValue;
229 derivativeValue[n] /= this->GetInputImage()->GetSignedSpacing()[n];
232 return (derivativeValue);
235 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
237 const vnl_matrix<long>& EvaluateIndex,
238 vnl_matrix<double>& weights,
239 unsigned int splineOrder)
const
244 double w, w2, w4, t, t0, t1;
249 for (
unsigned int n = 0; n < ImageDimension; ++n)
251 w = x[n] - (double)EvaluateIndex[n][1];
252 weights[n][3] = (1.0 / 6.0) * w * w * w;
253 weights[n][0] = (1.0 / 6.0) + 0.5 * w * (w - 1.0) - weights[n][3];
254 weights[n][2] = w + weights[n][0] - 2.0 * weights[n][3];
255 weights[n][1] = 1.0 - weights[n][0] - weights[n][2] - weights[n][3];
259 for (
unsigned int n = 0; n < ImageDimension; ++n)
265 for (
unsigned int n = 0; n < ImageDimension; ++n)
267 w = x[n] - (double)EvaluateIndex[n][0];
269 weights[n][0] = 1.0 - w;
273 for (
unsigned int n = 0; n < ImageDimension; ++n)
276 w = x[n] - (double)EvaluateIndex[n][1];
277 weights[n][1] = 0.75 - w * w;
278 weights[n][2] = 0.5 * (w - weights[n][1] + 1.0);
279 weights[n][0] = 1.0 - weights[n][1] - weights[n][2];
283 for (
unsigned int n = 0; n < ImageDimension; ++n)
286 w = x[n] - (double)EvaluateIndex[n][2];
288 t = (1.0 / 6.0) * w2;
289 weights[n][0] = 0.5 - w;
290 weights[n][0] *= weights[n][0];
291 weights[n][0] *= (1.0 / 24.0) * weights[n][0];
292 t0 = w * (t - 11.0 / 24.0);
293 t1 = 19.0 / 96.0 + w2 * (0.25 - t);
294 weights[n][1] = t1 + t0;
295 weights[n][3] = t1 - t0;
296 weights[n][4] = weights[n][0] + t0 + 0.5 * w;
297 weights[n][2] = 1.0 - weights[n][0] - weights[n][1] - weights[n][3] - weights[n][4];
301 for (
unsigned int n = 0; n < ImageDimension; ++n)
304 w = x[n] - (double)EvaluateIndex[n][2];
306 weights[n][5] = (1.0 / 120.0) * w * w2 * w2;
311 weights[n][0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - weights[n][5];
312 t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0);
313 t1 = (-1.0 / 12.0) * w * (t + 4.0);
314 weights[n][2] = t0 + t1;
315 weights[n][3] = t0 - t1;
316 t0 = (1.0 / 16.0) * (9.0 / 5.0 - t);
317 t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0);
318 weights[n][1] = t0 + t1;
319 weights[n][4] = t0 - t1;
324 itk::ExceptionObject err(__FILE__, __LINE__);
325 err.SetLocation(ITK_LOCATION);
326 err.SetDescription(
"SplineOrder must be between 0 and 5. Requested spline order has not been implemented yet.");
332 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
334 const vnl_matrix<long>& EvaluateIndex,
335 vnl_matrix<double>& weights,
unsigned int splineOrder)
const
342 double w, w1, w2, w3, w4, w5, t, t0, t1, t2;
343 int derivativeSplineOrder = (int)splineOrder - 1;
345 switch (derivativeSplineOrder)
351 for (
unsigned int n = 0; n < ImageDimension; ++n)
357 for (
unsigned int n = 0; n < ImageDimension; ++n)
359 weights[n][0] = -1.0;
364 for (
unsigned int n = 0; n < ImageDimension; ++n)
366 w = x[n] + 0.5 - (double)EvaluateIndex[n][1];
370 weights[n][0] = 0.0 - w1;
371 weights[n][1] = w1 - w;
377 for (
unsigned int n = 0; n < ImageDimension; ++n)
379 w = x[n] + .5 - (double)EvaluateIndex[n][2];
381 w3 = 0.5 * (w - w2 + 1.0);
384 weights[n][0] = 0.0 - w1;
385 weights[n][1] = w1 - w2;
386 weights[n][2] = w2 - w3;
392 for (
unsigned int n = 0; n < ImageDimension; ++n)
394 w = x[n] + 0.5 - (double)EvaluateIndex[n][2];
395 w4 = (1.0 / 6.0) * w * w * w;
396 w1 = (1.0 / 6.0) + 0.5 * w * (w - 1.0) - w4;
397 w3 = w + w1 - 2.0 * w4;
398 w2 = 1.0 - w1 - w3 - w4;
400 weights[n][0] = 0.0 - w1;
401 weights[n][1] = w1 - w2;
402 weights[n][2] = w2 - w3;
403 weights[n][3] = w3 - w4;
408 for (
unsigned int n = 0; n < ImageDimension; ++n)
410 w = x[n] + .5 - (double)EvaluateIndex[n][3];
412 t = (1.0 / 6.0) * t2;
415 w1 *= (1.0 / 24.0) * w1;
416 t0 = w * (t - 11.0 / 24.0);
417 t1 = 19.0 / 96.0 + t2 * (0.25 - t);
420 w5 = w1 + t0 + 0.5 * w;
421 w3 = 1.0 - w1 - w2 - w4 - w5;
423 weights[n][0] = 0.0 - w1;
424 weights[n][1] = w1 - w2;
425 weights[n][2] = w2 - w3;
426 weights[n][3] = w3 - w4;
427 weights[n][4] = w4 - w5;
434 itk::ExceptionObject err(__FILE__, __LINE__);
435 err.SetLocation(ITK_LOCATION);
436 err.SetDescription(
"SplineOrder (for derivatives) must be between 1 and 5. Requested spline order has not been implemented yet.");
443 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
448 m_PointsToIndex.resize(m_MaxNumberInterpolationPoints);
449 for (
unsigned int p = 0; p < m_MaxNumberInterpolationPoints; ++p)
452 unsigned long indexFactor[ImageDimension];
454 for (
int j = 1; j < static_cast<int>(ImageDimension); ++j)
456 indexFactor[j] = indexFactor[j - 1] * (m_SplineOrder + 1);
458 for (
int j = (
static_cast<int>(ImageDimension) - 1); j >= 0; j--)
460 m_PointsToIndex[p][j] = pp / indexFactor[j];
461 pp = pp % indexFactor[j];
466 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
469 unsigned int splineOrder)
const
474 for (
unsigned int n = 0; n < ImageDimension; ++n)
478 indx = (long)std::floor((
float)x[n]) - splineOrder / 2;
482 for (
unsigned int k = 0; k <= splineOrder; ++k)
484 evaluateIndex[n][k] = indx++;
490 indx = (long)std::floor((
float)(x[n] + 0.5)) - splineOrder / 2;
494 for (
unsigned int k = 0; k <= splineOrder; ++k)
496 evaluateIndex[n][k] = indx++;
502 template <
class TImageType,
class TCoordRep,
class TCoefficientType>
504 unsigned int splineOrder)
const
507 for (
unsigned int n = 0; n < ImageDimension; ++n)
509 long dataLength = m_DataLength[n];
510 long dataOffset = m_CurrentBufferedRegion.GetIndex()[n];
514 if (m_DataLength[n] == 1)
516 for (
unsigned int k = 0; k <= splineOrder; ++k)
518 evaluateIndex[n][k] = 0;
523 for (
unsigned int k = 0; k <= splineOrder; ++k)
526 evaluateIndex[n][k] = (evaluateIndex[n][k] < dataOffset) ? (dataOffset + (dataOffset - evaluateIndex[n][k]) % dataLength) : (evaluateIndex[n][k]);
527 if ((
long)dataLength + dataOffset <= evaluateIndex[n][k])
529 evaluateIndex[n][k] = dataOffset + dataLength - (evaluateIndex[n][k] - dataOffset - dataLength) % dataLength;