Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
EMatrix.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 "EMatrix.hh"
27 #include <Base/Geometry/Quaternion.hh>
28 #include <limits.h>
29 
30 using namespace std;
31 using namespace BIAS;
32 
33 int EMatrix::
34 InitFromF(const FMatrixBase &F, const KMatrix &K1, const KMatrix &K2)
35 {
36  FMatrix Fnorm;
37 
38  // normalize
39  double normalization = F.NormFrobenius();
40  if (fabs(normalization)>DBL_EPSILON)
41  Fnorm = (F / normalization );
42  else return -1;
43 
44  Matrix<double> tmp(K2.Transpose()*Fnorm*K1);
45 
46  normalization = tmp.NormFrobenius();
47  if (fabs(normalization)>DBL_EPSILON)
48  Fnorm = tmp / normalization;
49  else return -1;
50 
51  // compose nearest essential matrix
52  SVD Fnorm_svd((Matrix<FMATRIX_TYPE>)Fnorm);
53  Vector<double> S(Fnorm_svd.GetS());
54  tmp.SetZero();
55  tmp[1][1] = tmp[0][0] = 0.5*(S[0]+S[1]);
56  tmp[2][2] = 0.0;
57  (*this) = Matrix3x3<double>( Fnorm_svd.GetU()*tmp*Fnorm_svd.GetVT() );
58  return 0;
59 }
60 
61 
62 
63 int EMatrix::
64 GetRotationTranslation(RMatrix &R, Vector3<double> &C,
65  const std::vector<HomgPoint2D> &inlier1,
66  const std::vector<HomgPoint2D> &inlier2)
67 {
68  //AddDebugLevel(D_EMATRIX_ROT_TRANS);
69  BIASCDOUT(D_EMATRIX_ROT_TRANS, "EMatrix::GetRotationTranslation()\n");
70  // at first compute possible candidates for base sign and rotation
71  // @see for details see Hartley Zisserman pp. 239
72  SVD svd;
73  if (svd.Compute((Matrix<FMATRIX_TYPE>)(*this))!=0) return -10;
74  Matrix<double> U = svd.GetU();
75  Vector3<double> e(U.GetCol(2));
76  BIASCDOUT(D_EMATRIX_ROT_TRANS,"epipol = "<<e<<endl);
77 #ifdef BIAS_DEBUG
78  HomgPoint2D te1, te2;
79  this->GetEpipolesHomogenized(te1, te2);
80  BIASCDOUT(D_EMATRIX_ROT_TRANS, "epipoles homogenized: te1 = "<<te1
81  <<"\tte2 = "<<te2<<endl);
82 #endif
83  Matrix<double> W(3,3); W.SetZero();
84  W[0][1] = -1.0; W[1][0] = 1.0; W[2][2] = 1.0;
85 
86  std::vector<RMatrix> RotCand;
87  BIASCDOUT(D_EMATRIX_ROT_TRANS, "- Compute rotation candidates : \n");
88 
89  // first candidate
90  R = svd.GetU()*W*svd.GetVT();
91  R.TransposeIP();
92  RotCand.push_back(R.GetDeterminant()*R);
93  BIASCDOUT(D_EMATRIX_ROT_TRANS, " R[0] = " << RotCand[0]);
94 
95  // second candidate
96  R = svd.GetU()*W.Transpose()*svd.GetVT();
97  R = R.Transpose();
98  RotCand.push_back(R.GetDeterminant()*R);
99  BIASCDOUT(D_EMATRIX_ROT_TRANS, " R[1] = " << RotCand[1]);
100 #ifdef BIAS_DEBUG
101  {
102  BIAS::Quaternion<double> tmpQ[2];
103  RotCand[0].GetQuaternion(tmpQ[0]);
104  RotCand[1].GetQuaternion(tmpQ[1]);
105  BIASCDOUT(D_EMATRIX_ROT_TRANS, " Q[0] = " << tmpQ[0]
106  << " (angle = " << tmpQ[0].GetRotationAngle()*180.0/M_PI
107  << ", axis = " << tmpQ[0].GetRotationAxis() << endl);
108  BIASCDOUT(D_EMATRIX_ROT_TRANS, " Q[1] = " << tmpQ[1]
109  << " (angle = " << tmpQ[1].GetRotationAngle()*180.0/M_PI
110  << ", axis = " << tmpQ[1].GetRotationAxis() << endl);
111  }
112 #endif
113 
114  // now evaluate the candidates to find the best one
115  unsigned int inlier_count, best_inlier_count = 0;
116  Triangulation triangulator;
117  HomgPoint3D p3d;
118  const Vector3<double> C1(0.0, 0.0, 0.0);
119  Vector3<double> CCurrent;
120  const Quaternion<double> Q1(0.0, 0.0, 0.0, 1.0); //identity
122 
123  for (unsigned int i = 0; i < RotCand.size(); i++)
124  {
125  for (double base_sign = -1.0; base_sign <= 2.0 ; base_sign += 2.0)
126  {
127  // since we want to set +/-e as the last column of P (which is -R^T*C)
128  // we have to compute a current C that produces this row,
129  // therefore we undo R^T by multiplying by R
130  CCurrent = Vector3<double>(base_sign*RotCand[i]*e);
131  RotCand[i].GetQuaternion(Q2);
132  // evaluate inliers
133  inlier_count = 0;
134  BIAS::Vector3<double> eucl3d;
135  for (unsigned int n = 0; n < inlier1.size(); n++) {
136  // now run triangulation
137  int tri_res =
138  triangulator.Triangulate(C1, Q1, CCurrent, Q2,
139  inlier1[n], inlier2[n], eucl3d);
140  p3d.Set(eucl3d);
141  if (tri_res == 0) {
142  inlier_count++;
143  }
144  }
145  if (inlier_count > best_inlier_count){
146  BIASCDOUT(D_EMATRIX_ROT_TRANS, "- set best inlier count "
147  << inlier_count << " for R = " << RotCand[i]
148  << "C = " << CCurrent << endl);
149  best_inlier_count = inlier_count;
150  // save the same R and C we used for the test
151  R = RotCand[i];
152  C = CCurrent;
153  } else {
154  BIASCDOUT(D_EMATRIX_ROT_TRANS, "- inlier count " << inlier_count
155  << " for R = " << RotCand[i] << "C = " << CCurrent << endl);
156  }
157  } // loop over base signs
158  } // loop over rotation candidates
159 
160  if (best_inlier_count == 0) {
161  BIASERR("No inlier found during triangulation for essential candidates!");
162  return -1;
163  }
164 #ifdef BIAS_DEBUG
165  else {
167  R.GetQuaternion(tmpQ);
168  BIASCDOUT(D_EMATRIX_ROT_TRANS, "-> solution is R = " << R
169  << " Q = " << tmpQ
170  << " (angle = " << tmpQ.GetRotationAngle()*180.0/M_PI
171  << ", axis = " << tmpQ.GetRotationAxis() << endl
172  << " C = " << C << endl);
173  }
174 #endif
175 
176  return 0;
177 }
178 
179 int EMatrix::
180 GetRotationTranslation(Quaternion<double> &Q, Vector3<double> &C,
181  const vector<HomgPoint2D> &inlier1,
182  const vector<HomgPoint2D> &inlier2)
183 {
184  RMatrix R;
185  int res = GetRotationTranslation(R, C, inlier1, inlier2);
186  if (res==0){
187  if (R.GetQuaternion(Q)!=0){
188  return -20;
189  }
190  }
191  return res;
192 }
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Definition: SVD.hh:92
void TransposeIP()
tranpose this matrix &quot;in place&quot; example: 0 1 2 –&gt; 0 3 6 3 4 5 –&gt; 1 4 7 6 7 8 –&gt; 2 5 8 ...
Definition: Matrix3x3.hh:385
Matrix< T > Transpose() const
transpose function, storing data destination matrix
Definition: Matrix.hh:823
void Set(const HOMGPOINT3D_TYPE &x, const HOMGPOINT3D_TYPE &y, const HOMGPOINT3D_TYPE &z)
set elementwise with given 3 euclidean scalar values.
Definition: HomgPoint3D.hh:321
Vector< T > GetCol(const int &col) const
return a copy of column &quot;col&quot;, zero based counting
Definition: Matrix.cpp:252
int Compute(const Matrix< double > &M, double ZeroThreshold=DEFAULT_DOUBLE_ZERO_THRESHOLD)
set a new matrix and compute its decomposition.
Definition: SVD.cpp:102
void SetZero()
equivalent to matrix call
Definition: Vector.hh:156
describes the epipolar relationship between a point and his mapping on a corresponding epipolar line...
Definition: FMatrixBase.hh:67
int GetQuaternion(Quaternion< ROTATION_MATRIX_TYPE > &quat) const
Calculates quaternion representation for this rotation matrix.
Class for triangulation of 3Dpoints from 2D matches. Covariance matrix (refering to an uncertainty el...
3D rotation matrix
Definition: RMatrix.hh:49
void SetZero()
Sets all values to zero.
Definition: Matrix.hh:856
double NormFrobenius() const
Definition: Matrix3x3.hh:446
Vector3< QUAT_TYPE > GetRotationAxis() const
Returns rotation axis.
const Matrix< double > & GetVT() const
return VT (=transposed(V))
Definition: SVD.hh:177
class representing a Fundamental matrix
Definition: FMatrix.hh:46
int Triangulate(PMatrix &P1, PMatrix &P2, const HomgPoint2D &p1, const HomgPoint2D &p2, BIAS::Vector3< double > &point3d)
Triangulation for metric PMatrices (using C and Hinf)
QUAT_TYPE GetRotationAngle() const
Returns rotation angle notation in radians.
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
Matrix3x3< T > Transpose() const
returns transposed matrix tested 12.06.2002
Definition: Matrix3x3.cpp:167
const Matrix< double > & GetU() const
return U U is a m x m orthogonal matrix
Definition: SVD.hh:187
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
Definition: KMatrix.hh:48
T GetDeterminant() const
returns the Determinant |A| of this
Definition: Matrix3x3.cpp:347
double NormFrobenius() const
Return Frobenius norm = sqrt(trace(A^t * A)).
Definition: Matrix.hh:897