OTB  9.0.0
Orfeo Toolbox
otbLeastSquareAffineTransformEstimator.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 otbLeastSquareAffineTransformEstimator_hxx
22 #define otbLeastSquareAffineTransformEstimator_hxx
23 
24 #include <vnl/algo/vnl_lsqr.h>
25 #include <vnl/vnl_sparse_matrix_linear_system.h>
26 #include <vnl/vnl_least_squares_function.h>
27 
28 #include "otbMacro.h"
30 
31 namespace otb
32 {
33 
34 template <class TPoint>
36  : m_TiePointsContainer(), m_RMSError(), m_RelativeResidual(), m_Matrix(), m_Offset(), m_AffineTransform()
37 {
38  // Build the affine transform object
39  m_AffineTransform = AffineTransformType::New();
40 }
41 
42 template <class TPoint>
44 {
45  // Clear the tie points list
46  this->ClearTiePoints();
47 }
48 
49 template <class TPoint>
51 {
52  return m_TiePointsContainer;
53 }
54 
55 template <class TPoint>
57 {
58  m_TiePointsContainer = container;
59 }
60 
61 template <class TPoint>
63 {
64  // Clear the container
65  m_TiePointsContainer.clear();
66 }
67 
68 template <class TPoint>
70 {
71  // Build the tie point
72  TiePointsType tpoints(src, dst);
73 
74  // Add it to the container
75  m_TiePointsContainer.push_back(tpoints);
76 }
77 
78 template <class TPoint>
80 {
81  // Get the number of tie points
82  unsigned int nbPoints = m_TiePointsContainer.size();
83 
84  // Check if there are some points in
85  if (nbPoints == 0)
86  {
87  itkExceptionMacro(<< "No tie points were given to the LeastSquareAffineTransformEstimator");
88  }
89 
90  // Convenient typedefs
91  typedef vnl_sparse_matrix<double> VnlMatrixType;
92  typedef vnl_vector<double> VnlVectorType;
93 
94  // Step 1: build linear systems
95  // Build one linear system per dimension
96  std::vector<VnlMatrixType> matrixPerDim(PointDimension, VnlMatrixType(nbPoints, PointDimension + 1));
97  std::vector<VnlVectorType> vectorPerDim(PointDimension, VnlVectorType(nbPoints));
98 
99  // Iterate on points
100  for (unsigned int pId = 0; pId < nbPoints; ++pId)
101  {
102  // Iterate on dimension
103  for (unsigned int dim1 = 0; dim1 < PointDimension; ++dim1)
104  {
105  // Fill the vector
106  vectorPerDim[dim1][pId] = static_cast<double>(m_TiePointsContainer[pId].second[dim1]);
107 
108  // Iterate on dimension (second loop)
109  for (unsigned int dim2 = 0; dim2 < PointDimension; ++dim2)
110  {
111  matrixPerDim[dim1](pId, dim2) = static_cast<double>(m_TiePointsContainer[pId].first[dim2]);
112  }
113 
114  // Fill the last column
115  matrixPerDim[dim1](pId, PointDimension) = 1.;
116  }
117  }
118 
119  // Step 2: Solve linear systems
120 
121  for (unsigned int dim1 = 0; dim1 < PointDimension; ++dim1)
122  {
123  // Declare a linear system
124  vnl_sparse_matrix_linear_system<double> linearSystem(matrixPerDim[dim1], vectorPerDim[dim1]);
125 
126  // Check if there are enough points to solve
127  if (linearSystem.get_number_of_unknowns() > nbPoints * PointDimension)
128  {
129  itkExceptionMacro(<< "There are " << linearSystem.get_number_of_unknowns() << " unknowns in the linear systems but only " << nbPoints
130  << " points are provided.");
131  }
132  otbMsgDebugMacro(<< "Number of unknowns: " << linearSystem.get_number_of_unknowns());
133  otbMsgDebugMacro(<< "Number of equations: " << nbPoints);
134 
135  // A vector where the solution will be stored
136  vnl_vector<double> solution(PointDimension + 1);
137 
138  // Declare the solver
139  vnl_lsqr linearSystemSolver(linearSystem);
140 
141  // And solve it
142  linearSystemSolver.minimize(solution);
143 
144  // Get the RMS Error for that dimension
145  m_RMSError[dim1] = linearSystem.get_rms_error(solution);
146 
147  // Get the relative residual
148  m_RelativeResidual[dim1] = linearSystem.get_relative_residual(solution);
149 
150  // Fill the affine transform matrix
151  for (unsigned int dim2 = 0; dim2 < PointDimension; ++dim2)
152  {
153  m_Matrix(dim1, dim2) = static_cast<PrecisionType>(solution[dim2]);
154  }
155  // Fill the offset
156  m_Offset[dim1] = static_cast<PrecisionType>(solution[PointDimension]);
157  }
158 
159  // Set the affine transform parameters
160  m_AffineTransform->SetMatrix(m_Matrix);
161  m_AffineTransform->SetOffset(m_Offset);
162 }
163 
164 template <class TPoint>
165 void LeastSquareAffineTransformEstimator<TPoint>::PrintSelf(std::ostream& os, itk::Indent indent) const
166 {
167  Superclass::PrintSelf(os, indent);
168  os << indent << "Number of tie points: " << m_TiePointsContainer.size() << std::endl;
169  os << indent << "RMS error: " << m_RMSError << std::endl;
170  os << indent << "Relative residual: " << m_RelativeResidual << std::endl;
171 }
172 
173 } // end namespace otb
174 
175 #endif
otb::LeastSquareAffineTransformEstimator::Compute
void Compute()
Definition: otbLeastSquareAffineTransformEstimator.hxx:79
otb::LeastSquareAffineTransformEstimator::GetTiePointsContainer
TiePointsContainerType & GetTiePointsContainer()
Definition: otbLeastSquareAffineTransformEstimator.hxx:50
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::LeastSquareAffineTransformEstimator::PrecisionType
PointType::CoordRepType PrecisionType
Definition: otbLeastSquareAffineTransformEstimator.h:89
otb::LeastSquareAffineTransformEstimator::m_AffineTransform
AffineTransformPointerType m_AffineTransform
Definition: otbLeastSquareAffineTransformEstimator.h:161
otbMacro.h
otb::LeastSquareAffineTransformEstimator::LeastSquareAffineTransformEstimator
LeastSquareAffineTransformEstimator()
Definition: otbLeastSquareAffineTransformEstimator.hxx:35
otb::LeastSquareAffineTransformEstimator::AddTiePoints
void AddTiePoints(const PointType &src, const PointType &dst)
Definition: otbLeastSquareAffineTransformEstimator.hxx:69
otb::LeastSquareAffineTransformEstimator::~LeastSquareAffineTransformEstimator
~LeastSquareAffineTransformEstimator() override
Definition: otbLeastSquareAffineTransformEstimator.hxx:43
otb::LeastSquareAffineTransformEstimator::TiePointsType
std::pair< PointType, PointType > TiePointsType
Definition: otbLeastSquareAffineTransformEstimator.h:91
otbLeastSquareAffineTransformEstimator.h
otb::LeastSquareAffineTransformEstimator::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: otbLeastSquareAffineTransformEstimator.hxx:165
otb::LeastSquareAffineTransformEstimator::TiePointsContainerType
std::vector< TiePointsType > TiePointsContainerType
Definition: otbLeastSquareAffineTransformEstimator.h:92
otbMsgDebugMacro
#define otbMsgDebugMacro(x)
Definition: otbMacro.h:62
otb::LeastSquareAffineTransformEstimator::SetTiePointsContainer
void SetTiePointsContainer(const TiePointsContainerType &container)
Definition: otbLeastSquareAffineTransformEstimator.hxx:56
otb::LeastSquareAffineTransformEstimator::PointType
TPoint PointType
Definition: otbLeastSquareAffineTransformEstimator.h:88
otb::LeastSquareAffineTransformEstimator::ClearTiePoints
void ClearTiePoints()
Definition: otbLeastSquareAffineTransformEstimator.hxx:62