Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Quadric3D.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 #include "Quadric3D.hh"
27 #include <climits>
28 
29 #define SVD_ZERO_THRESH DBL_EPSILON * 16.0
30 
31 #define SINGULAR_THRESH_INVERSION 1e-20
32 
33 using namespace BIAS;
34 using namespace std;
35 
37  const CovMatrix3x3& cov,
38  const double &dScale) {
39  BIAS::Matrix3x3<double> InvCov, Tmp = cov * (dScale * dScale);
40 
41  int InversionResult = Tmp.GetInverse(InvCov);
42  if (InversionResult!=0) {
43  // degenerate covariance matrix !
44  SVD CovSVD((Matrix<double>)Tmp);
46  S = CovSVD.GetS();
47  Matrix3x3<double> V, UT, SdT;
48  SdT.SetZero();
49 
50  if (S[0]<SINGULAR_THRESH_INVERSION)
51  S[0]=SINGULAR_THRESH_INVERSION;
52  if (S[1]<SINGULAR_THRESH_INVERSION)
53  S[1]=SINGULAR_THRESH_INVERSION;
54  if (S[2]<SINGULAR_THRESH_INVERSION)
55  S[2]=SINGULAR_THRESH_INVERSION;
56 
57  SdT[0][0] = 1.0/S[0];
58  SdT[1][1] = 1.0/S[1];
59  SdT[2][2] = 1.0/S[2];
60 
61  V = CovSVD.GetV();
62  UT = CovSVD.GetU().Transpose();
63  InvCov = V * SdT * UT;
64  //cout << "using svd to invert Tmp "<< Tmp<<"\n"<<InvCov<<endl;
65  }
66 
67  BIAS::Matrix4x4<double> EllipsoidAtOrigin;
68  EllipsoidAtOrigin.SetIdentity();
69  for (unsigned int i=0; i<3; i++) {
70  for (unsigned int j=0; j<3; j++) {
71  EllipsoidAtOrigin[i][j] = InvCov[i][j];
72  }
73  }
74  EllipsoidAtOrigin[3][3] = -1;
75 
76  Matrix4x4<double> MoveToOrigin;
77  MoveToOrigin.SetIdentity();
78 
79  for (int i=0; i<3; i++) {
80  MoveToOrigin[i][3] = -C[i];
81  }
82  MoveToOrigin[3][3] = C[3];
83 
84 
85  (*this) = MoveToOrigin.Transpose() * (EllipsoidAtOrigin * MoveToOrigin);
86  // Quadric has radii dScale*sigma_i and is centered at point3d now
87 
88  Normalize();
89 }
90 
91 unsigned int Quadric3D::GetSignature() {
92  // do singular value decomposition of this
93  SVD svd(*this);
97  VT = svd.GetVT();
98 
99  // now we need the eigenvalues (with sign !)
100  // compute this by projecting the (normalized) eigenvectors onto their images
101  Vector4<double> eigenvector, eigenimage;
102  signed char Signature = 0;
103  for (unsigned int i=0; i<4; i++) {
104  // get ith eigenvector and its image
105  eigenvector = VT.GetRow(i);
106  eigenimage = (*this)*eigenvector;
107  // compute scalar product, we are not "thinking" homogenized now
108  // this is simply an analysis of a 4x4 matrix !
109  S[i] = eigenimage[0] * eigenvector[0] + eigenimage[1] * eigenvector[1]+
110  eigenimage[2] * eigenvector[2]+ eigenimage[3] * eigenvector[3];
111  if (S[i]<-SVD_ZERO_THRESH) Signature--;
112  else if (S[i]>SVD_ZERO_THRESH) Signature++;
113  }
114 
115  // return number of eigenvalues with one sign minus number of eigenvalues
116  // with opposite sign, choosing signs such that difference is not negative
117  if (Signature<0) return (unsigned int)(-Signature);
118  return (unsigned int)Signature;
119 }
120 
122  if (UseSVD) {
123  // we want to be numerically robust
124  SVD qsvd((*this), SVD_ZERO_THRESH, false);
125  return (qsvd.Invert());
126  }
127 
128  // do it the fast way
129  const QUADRIC3D_TYPE& a = (*this)[0][0];
130  const QUADRIC3D_TYPE& b = (*this)[0][1];
131  const QUADRIC3D_TYPE& c = (*this)[0][2];
132  const QUADRIC3D_TYPE& d = (*this)[0][3];
133  const QUADRIC3D_TYPE& e = (*this)[1][1];
134  const QUADRIC3D_TYPE& f = (*this)[1][2];
135  const QUADRIC3D_TYPE& g = (*this)[1][3];
136  const QUADRIC3D_TYPE& h = (*this)[2][2];
137  const QUADRIC3D_TYPE& i = (*this)[2][3];
138  const QUADRIC3D_TYPE& k = (*this)[3][3];
139 
140  // analytical inverse, neglecting determinant
141  Quadric3D Dual;
142  Dual[0][0] = 2.0*f*g*i - e*i*i - f*f*k + e*h*k - g*g*h;
143  Dual[1][0] = Dual[0][1] = d*g*h - d*f*i - c*g*i + b*i*i + c*f*k - b*h*k;
144  Dual[2][0] = Dual[0][2] = c*g*g + d*e*i - b*g*i - c*e*k + b*f*k -d*f*g;
145  Dual[3][0] = Dual[0][3] = b*g*h + d*f*f - d*e*h + c*e*i - b*f*i -c*f*g;
146  Dual[1][1] = 2.0*c*d*i - a*i*i - c*c*k + a*h*k -d*d*h;
147  Dual[2][1] = Dual[1][2] = a*g*i - d*(c*g + b*i - d*f) + b*c*k - a*f*k;
148  Dual[3][1] = Dual[1][3] = b*d*h - a*g*h + a*f*i - c*(d*f + b*i - c*g);
149  Dual[2][2] = 2.0*b*d*g - a*g*g - b*b*k + a*e*k - d*d*e;
150  Dual[3][2] = Dual[2][3] = c*d*e - b*d*f - b*c*g + a*f*g + b*b*i - a*e*i;
151  Dual[3][3] = 2.0*b*c*f - a*f*f - b*b*h + a*e*h -c*c*e;
152  return Dual;
153 }
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Definition: SVD.hh:92
Matrix< T > Transpose() const
transpose function, storing data destination matrix
Definition: Matrix.hh:823
A quadric as a 4x4 matrix describing a surface in 3d projective space defined by a quadratic equation...
Definition: Quadric3D.hh:106
class Vector4 contains a Vector of dim.
Definition: Vector4.hh:65
Matrix< double > GetV() const
return V
Definition: SVD.hh:396
int GetInverse(Matrix3x3< T > &inv) const
Matrix inversion: inverts this and stores resulty in argument inv.
Definition: Matrix3x3.cpp:373
const Matrix< double > & GetVT() const
return VT (=transposed(V))
Definition: SVD.hh:177
class for 3x3 covariance matrices
Definition: CovMatrix3x3.hh:50
Matrix4x4 Transpose() const
Definition: Matrix4x4.hh:315
const Vector< double > & GetS() const
return S which is a vector of the singular values of A in descending order.
Definition: SVD.hh:167
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
void SetIdentity()
set the elements of this matrix to the identity matrix (posisbly overriding the inherited method) ...
Definition: Matrix4x4.hh:260
const Matrix< double > & GetU() const
return U U is a m x m orthogonal matrix
Definition: SVD.hh:187
Matrix< double > Invert()
returns pseudoinverse of A = U * S * V^T A^+ = V * S^+ * U^T
Definition: SVD.cpp:214
unsigned int GetSignature()
computes signature of matrix, (no.
Definition: Quadric3D.cpp:91
Quadric3D GetDualQuadric(bool UseSVD=false) const
computes the dual quadric (points &lt;-&gt; planes)
Definition: Quadric3D.cpp:121