OTB  9.0.0
Orfeo Toolbox
otbSarParametricMapFunction.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 
22 #ifndef otbSarParametricMapFunction_hxx
23 #define otbSarParametricMapFunction_hxx
24 
26 #include "itkNumericTraits.h"
27 
28 #include "itkMetaDataObject.h"
29 #include "otbMetaDataKey.h"
30 
31 #include <vnl/algo/vnl_svd.h>
32 
33 namespace otb
34 {
35 
39 template <class TInputImage, class TCoordRep>
41  : m_PointSet(PointSetType::New()), m_IsInitialize(false), m_ProductWidth(0), m_ProductHeight(0)
42 {
43  m_Coeff.SetSize(1, 1);
44  m_Coeff.Fill(0);
45 }
47 
48 template <class TInputImage, class TCoordRep>
50 {
51  PointType p0;
52  p0.Fill(0);
53  m_ProductWidth = 1;
54  m_ProductHeight = 1;
55  m_IsInitialize = false;
56  m_PointSet->Initialize();
57  m_PointSet->SetPoint(0, p0);
58  m_PointSet->SetPointData(0, value);
59  EvaluateParametricCoefficient();
60  this->Modified();
61 }
62 
63 
64 template <class TInputImage, class TCoordRep>
66 {
67  m_Coeff.SetSize(polynomalSize[1] + 1, polynomalSize[0] + 1);
68  m_Coeff.Fill(0);
69  this->Modified();
70 }
71 
72 template <class TInputImage, class TCoordRep>
74 {
75  SetPolynomalSize(IndexType {polynomalSize[0], polynomalSize[1]});
76 }
77 
78 template <class TInputImage, class TCoordRep>
80 {
81  // Implementation of a Horner scheme evaluation for bivariate polynomial
82 
83  // let's avoid conversion between float and double!
84  const double p0 = point[0] / m_ProductWidth;
85  const double p1 = point[1] / m_ProductHeight;
86 
87  double result = 0;
88  for (unsigned int ycoeff = m_Coeff.Rows(); ycoeff > 0; --ycoeff)
89  {
90  double intermediate = 0;
91  for (unsigned int xcoeff = m_Coeff.Cols(); xcoeff > 0; --xcoeff)
92  {
93  // std::cout << "m_Coeff(" << ycoeff-1 << "," << xcoeff-1 << ") = " << m_Coeff(ycoeff-1, xcoeff-1) << std::endl;
94  intermediate = intermediate * p0 + m_Coeff(ycoeff - 1, xcoeff - 1);
95  }
96  result = result * p1 + intermediate;
97  }
98 
99  return result;
100 }
101 
102 template <class TInputImage, class TCoordRep>
104 {
105  PointSetPointer pointSet = this->GetPointSet();
106 
107  PointType coef;
108  PointType point;
109  coef.Fill(0);
110  point.Fill(0);
111  typename PointSetType::PixelType pointValue;
112  pointValue = itk::NumericTraits<PixelType>::Zero;
113 
114  if (pointSet->GetNumberOfPoints() == 0)
115  {
116  itkExceptionMacro(<< "PointSet must be set before evaluating the parametric coefficient (at least one value)");
117  }
118  else if (pointSet->GetNumberOfPoints() == 1)
119  {
120  pointSet->GetPointData(0, &pointValue);
121  m_Coeff(0, 0) = pointValue;
122  }
123  else
124  {
125  // Get input region for normalization of coordinates
126  auto imd = this->GetInputImage()->GetImageMetadata();
127  if (imd.Has(MDNum::NumberOfLines))
128  m_ProductHeight = imd[MDNum::NumberOfLines];
129  else
130  m_ProductHeight = this->GetInputImage()->GetLargestPossibleRegion().GetSize()[1];
131  if (imd.Has(MDNum::NumberOfColumns))
132  m_ProductWidth = imd[MDNum::NumberOfColumns];
133  else
134  m_ProductWidth = this->GetInputImage()->GetLargestPossibleRegion().GetSize()[0];
135 
136  // Perform the plane least square estimation
137  unsigned int nbRecords = pointSet->GetNumberOfPoints();
138  unsigned int nbCoef = m_Coeff.Rows() * m_Coeff.Cols();
139 
140  vnl_matrix<double> a(nbRecords, nbCoef);
141  vnl_vector<double> b(nbRecords), bestParams(nbCoef);
142  a.fill(0);
143  b.fill(0);
144  bestParams.fill(0);
145 
146  // Fill the linear system
147  for (unsigned int i = 0; i < nbRecords; ++i)
148  {
149  this->GetPointSet()->GetPoint(i, &point);
150  this->GetPointSet()->GetPointData(i, &pointValue);
151  b(i) = pointValue;
152  // std::cout << "point = " << point << std::endl;
153  // std::cout << "b(" << i << ") = " << pointValue << std::endl;
154 
155  for (unsigned int xcoeff = 0; xcoeff < m_Coeff.Cols(); ++xcoeff)
156  {
157  double xpart = std::pow(static_cast<double>(point[0]) / m_ProductWidth, static_cast<double>(xcoeff));
158  //std::cout << "xpart(" << i << ") = (" << static_cast<double>(point[0]) << " / " << m_ProductWidth << ")^" << xcoeff << "\n";
159  for (unsigned int ycoeff = 0; ycoeff < m_Coeff.Rows(); ++ycoeff)
160  {
161  double ypart = std::pow(static_cast<double>(point[1]) / m_ProductHeight, static_cast<double>(ycoeff));
162  a(i, xcoeff * m_Coeff.Rows() + ycoeff) = xpart * ypart;
163  // std::cout << "a(" << i << "," << xcoeff * m_Coeff.Rows() + ycoeff << ") = " << xpart << " * " << ypart << std::endl;
164  }
165  }
166  }
167 
168  // Solve linear system with SVD decomposition
169  vnl_svd<double> svd(a);
170  bestParams = svd.solve(b);
171 
172  for (unsigned int xcoeff = 0; xcoeff < m_Coeff.Cols(); ++xcoeff)
173  {
174  for (unsigned int ycoeff = 0; ycoeff < m_Coeff.Rows(); ++ycoeff)
175  {
176  m_Coeff(ycoeff, xcoeff) = bestParams(xcoeff * m_Coeff.Rows() + ycoeff);
177  // std::cout << "m_Coeff(" << ycoeff << "," << xcoeff << ") = " << m_Coeff(ycoeff, xcoeff) << std::endl;
178  }
179  }
180  }
181  m_IsInitialize = true;
182 }
183 
187 template <class TInputImage, class TCoordRep>
190 {
191  RealType result = itk::NumericTraits<RealType>::Zero;
192 
193  if (!m_IsInitialize)
194  {
195  itkExceptionMacro(<< "Must call EvaluateParametricCoefficient before evaluating");
196  }
197  else if (m_Coeff.Rows() * m_Coeff.Cols() == 1)
198  {
199  result = m_Coeff(0, 0);
200  }
201  else
202  {
203  result = this->Horner(point);
204  }
205  return result;
206 }
207 
208 
212 template <class TInputImage, class TCoordRep>
213 void SarParametricMapFunction<TInputImage, TCoordRep>::PrintSelf(std::ostream& os, itk::Indent indent) const
214 {
215  this->Superclass::PrintSelf(os, indent);
216  os << indent << "Polynom coefficients: " << m_Coeff << std::endl;
217 }
219 
220 
221 } // end namespace otb
222 
223 #endif
otb::SarParametricMapFunction::IndexType
Superclass::IndexType IndexType
Definition: otbSarParametricMapFunction.h:63
otb::SarParametricMapFunction::EvaluateParametricCoefficient
void EvaluateParametricCoefficient()
Definition: otbSarParametricMapFunction.hxx:103
otb::SarParametricMapFunction::ArrayIndexType
std::array< int, 2 > ArrayIndexType
Definition: otbSarParametricMapFunction.h:64
otb::SarParametricMapFunction::PointSetType
itk::PointSet< OutputType, ImageDimension > PointSetType
Definition: otbSarParametricMapFunction.h:69
otb::SarParametricMapFunction::SarParametricMapFunction
SarParametricMapFunction()
Definition: otbSarParametricMapFunction.hxx:40
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::SarParametricMapFunction::SetPolynomalSize
void SetPolynomalSize(const IndexType PolynomalSize)
Definition: otbSarParametricMapFunction.hxx:65
otb::SarParametricMapFunction::Horner
double Horner(PointType point) const
the width of the complete product (read from metadata)
Definition: otbSarParametricMapFunction.hxx:79
otb::MDNum::NumberOfColumns
@ NumberOfColumns
otb::SarParametricMapFunction::RealType
itk::NumericTraits< InputPixelType >::ScalarRealType RealType
Definition: otbSarParametricMapFunction.h:78
otb::SarParametricMapFunction::Evaluate
RealType Evaluate(const PointType &point) const override
Definition: otbSarParametricMapFunction.hxx:189
otbMetaDataKey.h
otbSarParametricMapFunction.h
otb::SarParametricMapFunction::SetConstantValue
void SetConstantValue(const RealType &value)
Definition: otbSarParametricMapFunction.hxx:49
otb::SarParametricMapFunction::PointType
PointSetType::PointType PointType
Definition: otbSarParametricMapFunction.h:72
otb::SarParametricMapFunction::m_Coeff
MatrixType m_Coeff
the width of the complete product (read from metadata)
Definition: otbSarParametricMapFunction.h:145
otb::SarParametricMapFunction::PointSetPointer
PointSetType::Pointer PointSetPointer
Definition: otbSarParametricMapFunction.h:70
otb::SarParametricMapFunction::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
the width of the complete product (read from metadata)
Definition: otbSarParametricMapFunction.hxx:213
otb::MDNum::NumberOfLines
@ NumberOfLines