1 #include "AbsoluteOrientation.hh"
2 #include <Base/Math/Matrix3x3.hh>
3 #include <Base/Math/Matrix.hh>
4 #include <Base/Math/Vector.hh>
5 #include <Base/Geometry/Quaternion.hh>
6 #include <MathAlgo/SVD.hh>
7 #include <MathAlgo/SVD3x3.hh>
13 const unsigned int AbsoluteOrientation::MIN_CORRESPONDENCES = 3;
15 AbsoluteOrientation::AbsoluteOrientation()
16 : epsilon_(1e-14), rotationAlgorithm_(HORN_ALGORITHM)
24 int AbsoluteOrientation::
28 double &ds,
bool enforceScale,
const std::vector<double> &w)
30 const unsigned int num = X.size();
31 const bool useWeights = (w.size() > 0);
35 BIASASSERT(X.size() == num && Y.size() == num);
36 BIASASSERT(!useWeights || w.size() == num);
41 double sumWeights = 0.0;
42 for (
register unsigned int i = 0; i < num; i++) {
43 BIASASSERT(w[i] >= 0.0);
45 centX.AddIP(w[i]*X[i]);
46 centY.AddIP(w[i]*Y[i]);
48 centX.DivideIP(sumWeights);
49 centY.DivideIP(sumWeights);
51 for (
register unsigned int i = 0; i < num; i++) {
55 centX.DivideIP((
double)num);
56 centY.DivideIP((
double)num);
60 std::vector< BIAS::Vector3<double> > normX;
61 std::vector< BIAS::Vector3<double> > normY;
64 for (
register unsigned int i = 0; i < num; i++) {
70 if (normPointX.
NormL2() > epsilon_ && normPointY.
NormL2() > epsilon_) {
71 normX.push_back(X[i] - centX);
72 normY.push_back(Y[i] - centY);
95 double sumX = 0, sumY = 0;
97 for (
register unsigned int i = 0; i < num; i++) {
98 sumX += w[i]*normX[i].ScalarProduct(normX[i]);
99 sumY += w[i]*normY[i].ScalarProduct(normY[i]);
102 for (
register unsigned int i = 0; i < num; i++) {
103 sumX += normX[i].ScalarProduct(normX[i]);
104 sumY += normY[i].ScalarProduct(normY[i]);
107 BIASASSERT(sumX > epsilon_);
108 ds = sqrt(sumY/sumX);
110 dt = centY - ds*dR*centX;
121 switch (rotationAlgorithm_)
124 return ComputeRotationHorn_(X, Y, dR, w);
126 return ComputeRotationKabsch_(X, Y, dR, w);
128 BIASERR(
"Unknown rotation estimation method given!");
132 int AbsoluteOrientation::
137 const unsigned int num = X.size();
138 const bool useWeights = (w.size() > 0);
142 BIASASSERT(X.size() == num && Y.size() == num);
143 BIASASSERT(!useWeights || w.size() == num);
151 for (
register unsigned int i = 0; i < num; i++) {
152 BIASASSERT(X[i].NormL2() > epsilon_ && Y[i].NormL2() > epsilon_);
153 S += w[i]*X[i].OuterProduct(Y[i]);
156 for (
register unsigned int i = 0; i < num; i++) {
157 BIASASSERT(X[i].NormL2() > epsilon_ && Y[i].NormL2() > epsilon_);
158 S += X[i].OuterProduct(Y[i]);
163 N[0][0] = S[0][0]+S[1][1]+S[2][2];
164 N[0][1] = S[1][2]-S[2][1];
165 N[0][2] = S[2][0]-S[0][2];
166 N[0][3] = S[0][1]-S[1][0];
167 N[1][0] = S[1][2]-S[2][1];
168 N[1][1] = S[0][0]-S[1][1]-S[2][2];
169 N[1][2] = S[0][1]+S[1][0];
170 N[1][3] = S[2][0]+S[0][2];
171 N[2][0] = S[2][0]-S[0][2];
172 N[2][1] = S[0][1]+S[1][0];
173 N[2][2] =-S[0][0]+S[1][1]-S[2][2];
174 N[2][3] = S[1][2]+S[2][1];
175 N[3][0] = S[0][1]-S[1][0];
176 N[3][1] = S[2][0]+S[0][2];
177 N[3][2] = S[1][2]+S[2][1];
178 N[3][3] =-S[0][0]-S[1][1]+S[2][2];
195 int AbsoluteOrientation::
200 const unsigned int num = X.size();
201 const bool useWeights = (w.size() > 0);
205 BIASASSERT(X.size() == num && Y.size() == num);
206 BIASASSERT(!useWeights || w.size() == num);
213 for (
register unsigned int i = 0; i < num; i++) {
214 BIASASSERT(X[i].NormL2() > epsilon_ && Y[i].NormL2() > epsilon_);
215 S += w[i]*Y[i].OuterProduct(X[i]);
218 for (
register unsigned int i = 0; i < num; i++) {
219 BIASASSERT(X[i].NormL2() > epsilon_ && Y[i].NormL2() > epsilon_);
220 S += Y[i].OuterProduct(X[i]);
231 if (S.GetDeterminant() < 0) D[2][2] = -1.0;
235 UD.Mult(svd.
GetVT(), UDVT);
247 const double &ds,
const std::vector<double> &w)
249 const unsigned int num = X.size();
250 const bool useWeights = (w.size() > 0);
252 BIASASSERT(X.size() == num && Y.size() == num);
253 BIASASSERT(!useWeights || w.size() == num);
260 for (
register unsigned int i = 0; i < num; i++) {
261 e = Y[i] - ds*dR*X[i] - dt;
266 for (
register unsigned int i = 0; i < num; i++) {
267 e = Y[i] - ds*dR*X[i] - dt;
284 const unsigned int num = X.size();
286 BIASASSERT(X.size() == num && Y.size() == num);
287 BIASASSERT(CovX.size() == num && CovY.size() == num);
294 for (
register unsigned int i = 0; i < num; i++) {
295 Cov = ds*ds*dR*(CovX[i]*dR.
Transpose()) + CovY[i];
297 BEXCEPTION(
"Unable to invert covariance matrix: " << Cov);
299 e = Y[i] - ds*dR*X[i] - dt;
300 invCov.
Mult(e, invCovE);
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
static const unsigned int MIN_CORRESPONDENCES
int Compute(const Matrix< double > &M, double ZeroThreshold=DEFAULT_DOUBLE_ZERO_THRESHOLD)
set a new matrix and compute its decomposition.
void ScalarProduct(const Vector3< T > &argvec, T &result) const
scalar product (=inner product) of two vectors, storing the result in result
Vector< T > GetCol(const int &col) const
return a copy of column "col", zero based counting
int SetFromQuaternion(const Quaternion< ROTATION_MATRIX_TYPE > &q)
Set rotation matrix from a quaternion.
int Compute(const Matrix< double > &M, double ZeroThreshold=DEFAULT_DOUBLE_ZERO_THRESHOLD)
set a new matrix and compute its decomposition.
void SetQuaternion(QUAT_TYPE real, QUAT_TYPE i, QUAT_TYPE j, QUAT_TYPE k)
Sets all parts of quaternion in mathematical order, real part first, then 1.,2.
void Normalize()
Scales quaternion to unit length, i.e.
void Mult(const Vector3< T > &argvec, Vector3< T > &destvec) const
matrix - vector multiplicate this matrix with Vector3, storing the result in destvec calculates: dest...
Matrix< double > GetV() const
return V
int GetInverse(Matrix3x3< T > &inv) const
Matrix inversion: inverts this and stores resulty in argument inv.
singular value decomposition for 3x3 matrices
const Matrix< double > & GetVT() const
return VT (=transposed(V))
double GetResidualErrors(std::vector< double > &errors, const std::vector< Vector3< double > > &X, const std::vector< Vector3< double > > &Y, const RMatrix &dR, const Vector3< double > &dt, const double &ds=1.0, const std::vector< double > &w=std::vector< double >(0))
Computes residual errors of 3D point sets X and Y with respect to given rotation dR, translation dt and isometric scale ds.
void Mult(const Matrix< T > &arg, Matrix< T > &result) const
matrix multiplication, result is not allocated
Matrix3x3< T > Transpose() const
returns transposed matrix tested 12.06.2002
const Matrix< double > & GetU() const
return U U is a m x m orthogonal matrix
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
int ComputeRotation(const std::vector< Vector3< double > > &X, const std::vector< Vector3< double > > &Y, RMatrix &dR, const std::vector< double > &w=std::vector< double >(0))
Computes rotation dR between corresponding 3D ray sets X and Y using the currently set algorithm...