21 #ifndef otbLeastSquareAffineTransformEstimator_hxx
22 #define otbLeastSquareAffineTransformEstimator_hxx
24 #include <vnl/algo/vnl_lsqr.h>
25 #include <vnl/vnl_sparse_matrix_linear_system.h>
26 #include <vnl/vnl_least_squares_function.h>
34 template <
class TPo
int>
36 : m_TiePointsContainer(), m_RMSError(), m_RelativeResidual(), m_Matrix(), m_Offset(), m_AffineTransform()
42 template <
class TPo
int>
46 this->ClearTiePoints();
49 template <
class TPo
int>
52 return m_TiePointsContainer;
55 template <
class TPo
int>
58 m_TiePointsContainer = container;
61 template <
class TPo
int>
65 m_TiePointsContainer.clear();
68 template <
class TPo
int>
75 m_TiePointsContainer.push_back(tpoints);
78 template <
class TPo
int>
82 unsigned int nbPoints = m_TiePointsContainer.size();
87 itkExceptionMacro(<<
"No tie points were given to the LeastSquareAffineTransformEstimator");
91 typedef vnl_sparse_matrix<double> VnlMatrixType;
92 typedef vnl_vector<double> VnlVectorType;
96 std::vector<VnlMatrixType> matrixPerDim(PointDimension, VnlMatrixType(nbPoints, PointDimension + 1));
97 std::vector<VnlVectorType> vectorPerDim(PointDimension, VnlVectorType(nbPoints));
100 for (
unsigned int pId = 0; pId < nbPoints; ++pId)
103 for (
unsigned int dim1 = 0; dim1 < PointDimension; ++dim1)
106 vectorPerDim[dim1][pId] =
static_cast<double>(m_TiePointsContainer[pId].second[dim1]);
109 for (
unsigned int dim2 = 0; dim2 < PointDimension; ++dim2)
111 matrixPerDim[dim1](pId, dim2) =
static_cast<double>(m_TiePointsContainer[pId].first[dim2]);
115 matrixPerDim[dim1](pId, PointDimension) = 1.;
121 for (
unsigned int dim1 = 0; dim1 < PointDimension; ++dim1)
124 vnl_sparse_matrix_linear_system<double> linearSystem(matrixPerDim[dim1], vectorPerDim[dim1]);
127 if (linearSystem.get_number_of_unknowns() > nbPoints * PointDimension)
129 itkExceptionMacro(<<
"There are " << linearSystem.get_number_of_unknowns() <<
" unknowns in the linear systems but only " << nbPoints
130 <<
" points are provided.");
132 otbMsgDebugMacro(<<
"Number of unknowns: " << linearSystem.get_number_of_unknowns());
136 vnl_vector<double> solution(PointDimension + 1);
139 vnl_lsqr linearSystemSolver(linearSystem);
142 linearSystemSolver.minimize(solution);
145 m_RMSError[dim1] = linearSystem.get_rms_error(solution);
148 m_RelativeResidual[dim1] = linearSystem.get_relative_residual(solution);
151 for (
unsigned int dim2 = 0; dim2 < PointDimension; ++dim2)
153 m_Matrix(dim1, dim2) =
static_cast<PrecisionType>(solution[dim2]);
156 m_Offset[dim1] =
static_cast<PrecisionType>(solution[PointDimension]);
160 m_AffineTransform->SetMatrix(m_Matrix);
161 m_AffineTransform->SetOffset(m_Offset);
164 template <
class TPo
int>
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;