Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ExampleFMatrix.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  @example ExampleFMatrix.cpp
27  @relates FMatrix
28  @brief Example computing F matrix with 8-point, non-lin optimize, and gold standard
29  @ingroup g_examples
30  @author MIP
31 */
32 
33 #include "Geometry/FMatrix.hh"
34 #include "Geometry/RMatrix.hh"
35 #include "Geometry/EMatrix.hh"
36 #include "Base/Geometry/KMatrix.hh"
37 #include "../FMatrixEstimation.hh"
38 #include "../PMatrixEstimation.hh"
39 #include "../PMatrixLinear.hh"
40 #include "../Triangulation.hh"
41 #include "../../Base/Math/Random.hh"
42 #include "Utils/ThreeDOut.hh"
43 
44 using namespace BIAS;
45 using namespace std;
46 
47 int main() {
48  BIAS::FMatrix F;
49 
50  BIAS::PMatrix P1, P2, P1Comp, P2Comp;
51  BIAS::Random Randomizer;
52 
53  BIAS::RMatrix R1, R2;
55  BIAS::Vector3<double> C1, C2;
56 
57  // set rotation matrices
58  R1.SetIdentity();
59  R2.SetXYZ(0, 10.0*M_PI/180.0, 0);
60 
61  // camera center coordiantes
62  C1[0] = 0.0;
63  C1[1] = 0.0;
64  C1[2] = 0.0;
65 
66  // C2[0] = -1.0/sqrt(2.0);
67  // C2[1] = 1.0/sqrt(2.0);
68  C2[0] = -1.0;
69  C2[1] = 0.0;
70  C2[2] = 0.0;
71 
72  // camera matrix for both cameras
73  K.SetFx(400.0);
74  K.SetFy(400.0);
75  // in image coordinates
76  K.SetHx(100.0);
77  K.SetHy(100.0);
78  K.SetSkew(0.0);
79 
80  K[2][2] = 1;
81 
82  // combine camera matrix, rotation matrix and camera center to projection matrices
83  P1.Compose(K, R1, C1);
84  P2.Compose(K, R2, C2);
85 
86  cout << "R1 " << R1 << endl;
87  cout << "R2 " << R2 << endl;
88  cout << "C1 " << C1 << endl;
89  cout << "C2 " << C2 << endl;
90  cout << "K " << K << endl;
91  cout << "P1 " << P1 << endl;
92  cout << "P2 " << P2 << endl;
93 
94  // compute randomized correspondences
95  // later compute more and put them on planes, check angle of reconstruction
96  vector<HomgPoint3D> points, pointsComp;
97  vector<HomgPoint2D> p1, p2;
98 
99  cout << "Randomized correspondences are "<<endl;
100  int numPoints = 20;
101  double noise = 0.5;
102  for (int p=0; p<numPoints; p++) {
103  points.push_back(HomgPoint3D(
104  Randomizer.GetUniformDistributed(-1.0, 1.0),
105  Randomizer.GetUniformDistributed(-1.0, 1.0),
106  Randomizer.GetUniformDistributed(3.0, 5.0)));
107  p1.push_back(P1 * points[p]);
108  if(noise > 0){
109  p1[p][0] += Randomizer.GetNormalDistributed(0, noise);
110  p1[p][1] += Randomizer.GetNormalDistributed(0, noise);
111  }
112  p1[p].Homogenize();
113  cout << "{ "<<p1[p]<<" ";
114  p2.push_back(P2 * points[p]);
115  if(noise > 0){
116  p2[p][0] += Randomizer.GetNormalDistributed(0, noise);
117  p2[p][1] += Randomizer.GetNormalDistributed(0, noise);
118  }
119  p2[p].Homogenize();
120  cout << p2[p]<<" } "<<endl;
121  }
122 
123  // compute points on line with right angle - are not used for eight point algorithm
124  int numPointsOnLines = 20;
125  vector<HomgPoint3D> line1, line2, line1Comp, line2Comp;
126  vector<HomgPoint2D> l1P1, l1P2, l2P1, l2P2;
127  double randLambda = 0.0;
128  for (int i = 0; i < numPointsOnLines; i++) {
129  randLambda = Randomizer.GetUniformDistributed(-0.5, 3.0);
130  line1.push_back(HomgPoint3D(-1.0 + randLambda, 1.0 + randLambda, 1.0
131  + randLambda));
132  l1P1.push_back(P1 * line1[i]);
133  l1P1[i].Homogenize();
134  l1P2.push_back(P2 * line1[i]);
135  l1P2[i].Homogenize();
136  randLambda = Randomizer.GetUniformDistributed(-1.0, 1.0);
137  line2.push_back(HomgPoint3D(1.0 + randLambda, -1.0 + randLambda, 1.0
138  + randLambda));
139  l2P1.push_back(P1 * line2[i]);
140  l2P1[i].Homogenize();
141  l2P2.push_back(P2 * line2[i]);
142  l2P2[i].Homogenize();
143 
144  }
145 
146  // Compute FMatrix from correspondences
147  bool NormalizeHartley = true;
148  FMatrixEstimation FEstimator(NormalizeHartley);
149  FEstimator.EightPoint(F, p1, p2);
150  FMatrix F_opt = F;
151  FEstimator.Optimize(F_opt, p1, p2);
152 
153  // test putting F together using both Pmatrices
154  FMatrix testCompF(P1, P2);
155  F.Normalize();
156  cout << "F " << F << endl;
157  cout << "F residualError " << F.GetResidualError(p1, p2) << endl;
158  F_opt.Normalize();
159  cout << "F " << F_opt << endl;
160  cout << "F residualError " << F_opt.GetResidualError(p1, p2) << endl;
161  testCompF.Normalize();
162  cout << "testCompF " << testCompF << endl;
163  cout << "testCompF " << testCompF.GetResidualError(p1, p2) << endl;
164 
165  // some resetting
166  P1Comp.SetIdentity();
167  P1Comp.InvalidateDecomposition();
168  P2Comp.SetIdentity();
169  P2Comp.InvalidateDecomposition();
170 
171  // disturb KMatrix
172  KMatrix KFalsch(K);
173  KFalsch[0][0] *= (1.0 + Randomizer.GetUniformDistributed(-0.75, 1.0));
174  KFalsch[1][1] = KFalsch[0][0];
175 
176  cout << "disturbed kmatrix " << KFalsch << endl;
177 
178  // compute essential matrix from fundamental matrix and disturbed k matrices
179  EMatrix E;
180  // initFromF enforces the rotation part of the Ematrix to be a rotation
181  E.InitFromF(F, KFalsch, KFalsch);
182 
183  // check epipoles
184  HomgPoint2D Epipole1, Epipole2;
185  E.GetEpipoles(Epipole1, Epipole2);
186  cout << "Epipole1 " << Epipole1.Homogenize() << " Epipole2 "
187  << Epipole2.Homogenize() << endl;
188 
189  // Estimate PMatrix using PMatrixEstimation using essential matrix because P1 is assumed to be identity
190  PMatrixEstimation pEstimator;
191  double BaselineMagnitude = (C1-C2).NormL2();
192 
193  // use foerstner method for rotation estimation
194  pEstimator.ComputeFromFDirect(E, BaselineMagnitude, P1Comp, P2Comp);
195  // use ?pollefey's? method for rotation estimation
196  // pEstimator.ComputeFromFQuasiEuklid(E, BaselineMagnitude,P1Comp,P2Comp);
197 
198  // turn baseline if necessary - using ground truth
199  if (P2Comp.GetC().ScalarProduct(C2) < 0.0)
200  pEstimator.ComputeFromFDirect(E, -BaselineMagnitude, P1Comp, P2Comp);
201  //pEstimator.ComputeFromFQuasiEuklid(E, -BaselineMagnitude,P1Comp,P2Comp);
202 
203  // add assumed KMatrix to Projection matrices
204  P1Comp = KFalsch * P1Comp;
205  P1Comp.InvalidateDecomposition();
206  P2Comp = KFalsch * P2Comp;
207  P2Comp.InvalidateDecomposition();
208 
209  cout << "P2COMP IS " << P2Comp << endl;
210  cout<< "Resulting C vectors " << P1Comp.GetC() <<" " << P2Comp.GetC()
211  <<endl;
212 
213  // Check if estimated rotation matrix for P2 really is a/the correct rotation matrix
214  RMatrix REst;
215  double almostZero = 1e-10;
216 
217  REst = (RMatrix) P2Comp.GetR();
218  double det = REst.GetDeterminant();
219  Matrix3x3<double> id = REst * REst.Transpose();
220 
221  cout << "resulting rotation matrices " << P1Comp.GetR() << " " << REst
222  << endl;
223  cout << "Det of P2 " << det << endl;
224  cout << id << " identity test: " << id.IsIdentity(1) << endl;
225 
226  double phiX, phiY, phiZ;
227  REst.GetRotationAnglesXYZ(phiX, phiY, phiZ);
228  cout << "Rotation angles " << phiX*180.0/M_PI << " " << phiY*180.0 /M_PI
229  << " " << phiZ*180.0/M_PI << endl;
230 
231  // check for orthonormal columns
232  bool isOrthonormal = true;
233  double scalarProduct1 = REst.GetColumn(0).ScalarProduct(REst.GetColumn(1));
234  double scalarProduct2 = REst.GetColumn(0).ScalarProduct(REst.GetColumn(2));
235  double scalarProduct3 = REst.GetColumn(1).ScalarProduct(REst.GetColumn(2));
236 
237  if (fabs(scalarProduct1) >= almostZero)
238  isOrthonormal = false;
239  if (fabs(scalarProduct2) >= almostZero)
240  isOrthonormal = false;
241  if (fabs(scalarProduct3) >= almostZero)
242  isOrthonormal = false;
243 
244  if (!id.IsIdentity(1.0))
245  isOrthonormal = false;
246 
247  cout << "sp 1 " << scalarProduct1 << " sp 2 " << scalarProduct2 << " sp 3 "
248  << scalarProduct3 << " orthonormal columns " << isOrthonormal
249  << endl;
250 
251  cout << "p1 est " << P1Comp << endl;
252  cout << "p2 est " << P2Comp << endl;
253 
254  // triangulate using the new projection matrices -
255  // are for example lines still lines?
256  Triangulation triangulator;
257  Vector3<double> tempPoint;
258  for (int i = 0; i < numPoints; i++) {
259  cout << "point " << i << " triangulation "
260  <<
261  triangulator.Triangulate(P1Comp, P2Comp, p1[i], p2[i], tempPoint)
262  << " ";
263  pointsComp.push_back(HomgPoint3D(tempPoint));
264  }
265  cout << endl;
266 
267  for (int i = 0; i < numPointsOnLines; i++) {
268  triangulator.Triangulate(P1Comp, P2Comp, l1P1[i], l1P2[i],
269  tempPoint);
270  line1Comp.push_back(HomgPoint3D(tempPoint));
271  triangulator.Triangulate(P1Comp, P2Comp, l2P1[i], l2P2[i],
272  tempPoint);
273  line2Comp.push_back(HomgPoint3D(tempPoint));
274  }
275 
276  ThreeDOutParameters param;
277  param.CameraStyle = PyramidMesh;
278  param.PointStyle = Box;
279  param.PointSize = 0.1;
280  param.LineStyle = Solid;
281  param.DrawUncertaintyEllipsoids = false;
282  ThreeDOut threeDOut(param);
283 
284  for (int i = 0; i < numPoints; i++) {
285  threeDOut.AddPoint(points[i], RGBAuc(0, 0, 255, 127));
286  }
287 
288  for (int i = 0; i < numPoints; i++) {
289  threeDOut.AddPoint(pointsComp[i], RGBAuc(255, 0, 0, 127));
290  }
291  for (int i = 0; i < numPointsOnLines; i++) {
292  threeDOut.AddPoint(line1[i], RGBAuc(0, 255, 255, 127));
293  threeDOut.AddPoint(line2[i], RGBAuc(255, 255, 255, 127));
294  }
295 
296  for (int i = 0; i < numPointsOnLines; i++) {
297  threeDOut.AddPoint(line1Comp[i], RGBAuc(255, 255, 0, 127));
298  threeDOut.AddPoint(line2Comp[i], RGBAuc(255, 0, 255, 127));
299  }
300 
301  threeDOut.AddPMatrix(P1, 512, 512, RGBAuc_WHITE_OPAQUE, 0.1);
302  threeDOut.AddPMatrix(P2, 512, 512, RGBAuc(255, 0, 0, 127), 0.1);
303  threeDOut.AddPMatrix(P1Comp, 512, 512, RGBAuc(0, 255, 255, 127), 0.1);
304  threeDOut.AddPMatrix(P2Comp, 512, 512, RGBAuc(255, 0, 255, 127), 0.1);
305  Vector3<double> start(0.0, 0.0, 0.0);
306  Vector3<double> end(1.0, 0.0, 0.0);
307  threeDOut.AddLine(start, end, RGBAuc(255, 0, 0, 127));
308  end.Set(0.0, 1.0, 0.0);
309  threeDOut.AddLine(start, end, RGBAuc(0, 255, 0, 127));
310  end.Set(0.0, 0.0, 1.0);
311  threeDOut.AddLine(start, end, RGBAuc(0, 0, 255, 127));
312  threeDOut.VRMLOut("test.wrl");
313  threeDOut.Dump();
314 
315  return 0;
316 }
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
void SetXYZ(ROTATION_MATRIX_TYPE PhiX, ROTATION_MATRIX_TYPE PhiY, ROTATION_MATRIX_TYPE PhiZ)
Set Euler angles (in rad) in order XYZ.
Unified output of 3D entities via OpenGL or VRML.
Definition: ThreeDOut.hh:349
HomgPoint2D & Homogenize()
homogenize class data member elements to W==1 by divison by W
Definition: HomgPoint2D.hh:215
configuration struct for drawing styles of various 3d objects
Definition: ThreeDOut.hh:309
void SetSkew(const KMATRIX_TYPE &val)
Definition: KMatrix.cpp:81
void GetColumn(const unsigned int col, Vector3< T > &r) const
extract one column (&#39;Spalte&#39;) from this matrix (for convenience)
Definition: Matrix3x3.cpp:299
bool IsIdentity(const T eps=std::numeric_limits< T >::epsilon()) const
Definition: Matrix3x3.cpp:518
class representing an Essential matrix
Definition: EMatrix.hh:52
double GetUniformDistributed(const double min, const double max)
on succesive calls return uniform distributed random variable between min and max ...
Definition: Random.hh:84
CameraDrawingStyle CameraStyle
Definition: ThreeDOut.hh:313
Class for triangulation of 3Dpoints from 2D matches. Covariance matrix (refering to an uncertainty el...
3D rotation matrix
Definition: RMatrix.hh:49
double GetResidualError(const std::vector< BIAS::HomgPoint2D > &p1, const std::vector< BIAS::HomgPoint2D > &p2)
returns residual error as in Zisserman p.
Definition: FMatrix.cpp:148
void SetIdentity()
set the elements of this matrix to the matrix 1 0 0 0 0 1 0 0 0 0 1 0 which is no strict identity (!)...
Definition: Matrix3x4.hh:240
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)
void InvalidateDecomposition()
to re-Decompose_() after filling with data use this.
Definition: PMatrix.hh:499
functions for estimating a fundamental matrix (FMatrix) given a set of 2d-2d correspondences (no outl...
LineDrawingStyle LineStyle
Definition: ThreeDOut.hh:314
BIAS::Vector4< unsigned char > RGBAuc
Definition: RGBA.hh:47
int InitFromF(const FMatrixBase &F, const KMatrix &K1, const KMatrix &K2)
assuming K1 and K2 as calibrations of the cameras which refer to the fmatrix, create the nearest vali...
Definition: EMatrix.cpp:34
compute standard P1/P2 from F.
void SetFx(const KMATRIX_TYPE &val)
Definition: KMatrix.cpp:75
int ComputeFromFDirect(BIAS::FMatrix &F, const double &BaselineMagnitude, BIAS::PMatrix &P1, BIAS::PMatrix &P2)
given an FMatrix set P1 as identity and compute P2 to be consistent with F and P1 such that P2 is euc...
int GetC(Vector3< double > &C)
computes translation vector origin world coo -&gt; origin camera coo (center), uses decomposition, which is cached
Definition: PMatrix.cpp:165
Matrix3x3< T > Transpose() const
returns transposed matrix tested 12.06.2002
Definition: Matrix3x3.cpp:167
int GetRotationAnglesXYZ(double &PhiX, double &PhiY, double &PhiZ) const
Get Euler angles for this rotation matrix in order XYZ.
void SetHy(const KMATRIX_TYPE &val)
Definition: KMatrix.cpp:87
void SetFy(const KMATRIX_TYPE &val)
Definition: KMatrix.cpp:78
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
int GetEpipoles(HomgPoint2D &Epipole1, HomgPoint2D &Epipole2) const
Computes the epipoles from this F Matrix.
Definition: FMatrix.cpp:69
double GetNormalDistributed(const double mean, const double sigma)
on succesive calls return normal distributed random variable with mean and standard deviation sigma ...
Definition: Random.hh:71
describes a projective 3D -&gt; 2D mapping in homogenous coordinates
Definition: PMatrix.hh:88
PointDrawingStyle PointStyle
Definition: ThreeDOut.hh:312
void SetHx(const KMATRIX_TYPE &val)
Definition: KMatrix.cpp:84
class for producing random numbers from different distributions
Definition: Random.hh:51
T Normalize()
divide this by biggest absolute entry, returns biggest entry
Definition: Matrix3x3.cpp:580
void Compose(const Matrix3x3< double > &K, const Matrix3x3< double > &R, const Vector3< double > &C)
composes this from K, R and C using P = [ K R&#39; | -K R&#39; C ] with R&#39; = transpose(R) ...
Definition: PMatrix.cpp:581
class BIASGeometryBase_EXPORT HomgPoint3D
void SetIdentity()
set the elements of this matrix to the identity matrix (possibly overriding the inherited method) ...
Definition: Matrix3x3.hh:429