Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
FMatrixEstimation.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 #include "FMatrixEstimation.hh"
26 #include "MathAlgo/SVD.hh"
27 
28 #include "MathAlgo/Minpack.hh"
29 #include "Base/Geometry/KMatrix.hh"
30 #include "PMatrixEstimation.hh"
31 
32 #include <Base/Common/CompareFloatingPoint.hh>
33 
34 #include <Base/Common/BIASpragma.hh>
35 
36 using namespace BIAS;
37 using namespace std;
38 
39 int
40 FErrorFunction_(void *p,int m, int n, const double *x, double *fvec, int iflag) {
41  FMatrixEstimation *pCurrentObject = (FMatrixEstimation*)p;
42  Parametrization *Para = pCurrentObject->currentPara_;
43 
44  vector<double> params;
45  params.reserve(7);
46  for (unsigned int i=0; i<7; i++){
47  params.push_back(x[i]);
48 // cout<<"Param:"<<x[i]<<endl;
49  }
50  //construct FMatrix from parameters
51  BIAS::FMatrix F;
52  Para->ParamsToFMatrix(F, params);
53 // cout<<"F:"<<F<<endl;
54  F = FMatrix(pCurrentObject->NormF2_.Transpose() * F * pCurrentObject->NormF1_);
55 
56  const unsigned int uiDataSize = pCurrentObject->p1_->size();
57  const vector<BIAS::HomgPoint2D> &p1 = *pCurrentObject->p1_;
58  const vector<BIAS::HomgPoint2D> &p2 = *pCurrentObject->p2_;
59 
60 
61  HomgPoint2D epi1, epi2;
62  F.GetEpipolesHomogenized(epi1, epi2);
63  F.Normalize();
64 
65  double error = 0.0;
66 
67  for (unsigned int j=0; j<uiDataSize; j++) {
68  fvec[j] = F.GetEpipolarErrorHomogenized(p1[j], p2[j]);
69  error += fvec[j];
70  }
71 
72 // cout << "f error " << error << endl;
73  return 0;
74 }
75 
76 int
77 FGoldStandardErrorFunction_(void *p,int m, int n, const double *x, double *fvec, int iflag) {
78 
79  // increase iteration counter
80  FMatrixEstimation* pCurrentObject = (FMatrixEstimation*)p;
81 
83 
84  // rebuild P2
86  // write params from x into P2
87  for (int i = 0; i < 3; i++) {
88  for (int j = 0; j < 4; j++) {
89  P2[i][j] = x[i*4 + j];
90  }
91  }
92 
93  // get correspondences
94  const unsigned int uiDataSize = pCurrentObject->p1_->size();
95  const std::vector<BIAS::HomgPoint2D> &p1 = *pCurrentObject->p1_;
96  const std::vector<BIAS::HomgPoint2D> &p2 = *pCurrentObject->p2_;
97 
98  // rebuild 3D points
99  vector<HomgPoint3D> points3D;
100  for (unsigned int i = 0; i < uiDataSize; i++) {
101  points3D.push_back(HomgPoint3D(x[12 + i*3], x[12 + i*3 + 1], x[12 + i*3 + 2], 1.0));
102  }
103 
104  // compute cost function
105  HomgPoint2D p1Est;
106  HomgPoint2D p2Est;
107  double error1x, error2x, error1y, error2y;
108  HomgPoint2D p1Temp, p2Temp;
109 
110  for (unsigned int i = 0; i < uiDataSize; i++) {
111  // project points
112  p1Est = P1 * points3D[i];
113  p1Est.Homogenize();
114  p2Est = P2 * points3D[i];
115  p2Est.Homogenize();
116 
117  error1x = (p1Est[0] - p1[i][0]) * (p1Est[0] - p1[i][0]);
118  error1y = (p1Est[1] - p1[i][1]) * (p1Est[1] - p1[i][1]);
119  error2x = (p2Est[0] - p2[i][0]) * (p2Est[0] - p2[i][0]);
120  error2y = (p2Est[1] - p2[i][1]) * (p2Est[1] - p2[i][1]);
121 
122  fvec[i*4 ] = error1x;
123  fvec[i*4+1] = error1y;
124  fvec[i*4+2] = error2x;
125  fvec[i*4+3] = error2y;
126  }
127  return 0;
128 }
129 
130 int FMatrixEstimation::SevenPoint(std::vector<BIAS::FMatrix>& vecF,
131  const std::vector<BIAS::HomgPoint2D> &p1,
132  const std::vector<BIAS::HomgPoint2D> &p2) {
133 #ifdef BIAS_DEBUG
134  if ((p1.size()!=7) || (p2.size()!=7)) {
135  BIASERR("Must provide 7 point correspondences for 7-Point algorithm"
136  <<"p1.size="<<p1.size()<<"p2.size="<<p2.size());
137  BIASABORT;
138  }
139 #endif
140 
141  const std::vector<BIAS::HomgPoint2D> *pp1 = &p1;
142  const std::vector<BIAS::HomgPoint2D> *pp2 = &p2;
143  std::vector<BIAS::HomgPoint2D> p1norm;
144  std::vector<BIAS::HomgPoint2D> p2norm;
145  KMatrix K1, K2;
146  if (NormalizeHartley_) {
147  // for (unsigned int i=0; i<7; i++) cout <<" " <<p1[i];
148  N_.Hartley(p1, p1norm, K1);
149  // for (unsigned int i=0; i<7; i++) cout <<" " <<p2[i];
150  N_.Hartley(p2, p2norm, K2);
151  pp1 = &p1norm;
152  pp2 = &p2norm;
153  }
154 
155  // determine rank of equation system
156  BIAS::Matrix<double> A(7, 9);
157 
158  for (unsigned int i=0; i<7; i++) {
159  // run over all rows of A (and all point correspondences)
160  A[i][0] = (*pp1)[i][0] * (*pp2)[i][0];
161  A[i][1] = (*pp1)[i][1] * (*pp2)[i][0];
162  A[i][2] = (*pp2)[i][0];
163  A[i][3] = (*pp1)[i][0] * (*pp2)[i][1];
164  A[i][4] = (*pp1)[i][1] * (*pp2)[i][1];
165  A[i][5] = (*pp2)[i][1];
166  A[i][6] = (*pp1)[i][0];
167  A[i][7] = (*pp1)[i][1];
168  A[i][8] = 1;
169  }
170 
171  BIAS::SVD A_SVD(A);
172  Vector<double> f1(9), f2(9);
173  if (!A_SVD.GetNullvector(f1, 0)) {
174  BIASERR("Error retrieving first F !");
175  }
176  if (!A_SVD.GetNullvector(f2, 1)) {
177  BIASERR("Error retrieving second F !");
178  }
179 
180  // f1 and f2 span a 2dimensional null space of A
181  // find matrix with rank<3 in this subspace:
182  // impose constraint that det(alpha*f1+(1-alpha)*f2)=0)
183  std::vector<POLYNOMIALSOLVE_TYPE> AlphaPolynomial, Alphas;
184  GetDetPolynomial(f1, f2, AlphaPolynomial);
185 
186  // solve for alpha
187  PolynomialSolve Solver;
188  Solver.CheckCoefficients(AlphaPolynomial);
189  const unsigned int uiNumberSolutions = Solver.Analytic(AlphaPolynomial, Alphas);
190 
191  vecF.resize(uiNumberSolutions);
192  if (uiNumberSolutions==0)
193  return -1;
194 
195  // compute (1 or 3) solutions from weighting with alphas
196  for (unsigned int i = 0; i<uiNumberSolutions; i++) {
197  vecF[i].SetFromVector(f1*Alphas[i] + f2*(1.0-Alphas[i]));
198  if (NormalizeHartley_)
199  vecF[i] = K2.Transpose() * vecF[i] * K1;
200  }
201 
202  return 0;
203 }
204 
205 int FMatrixEstimation::Linear(BIAS::FMatrix& F, const std::vector<BIAS::HomgPoint2D> &p1,
206  const std::vector<BIAS::HomgPoint2D> &p2) {
207 
208  const std::vector<BIAS::HomgPoint2D> *pp1 = &p1;
209  const std::vector<BIAS::HomgPoint2D> *pp2 = &p2;
210  std::vector<BIAS::HomgPoint2D> p1norm;
211  std::vector<BIAS::HomgPoint2D> p2norm;
212  KMatrix K1, K2;
213  if (NormalizeHartley_) {
214  N_.Hartley(p1, p1norm, K1);
215  N_.Hartley(p2, p2norm, K2);
216  pp1 = &p1norm;
217  pp2 = &p2norm;
218  }
219 
220  // determine rank of equation system
221  BIAS::Matrix<double> A(p1.size(), 9);
222 
223  for (unsigned int i=0; i<p1.size(); i++) {
224  // run over all rows of A (and all point correspondences)
225  A[i][0] = (*pp1)[i][0] * (*pp2)[i][0];
226  A[i][1] = (*pp1)[i][1] * (*pp2)[i][0];
227  A[i][2] = (*pp2)[i][0];
228  A[i][3] = (*pp1)[i][0] * (*pp2)[i][1];
229  A[i][4] = (*pp1)[i][1] * (*pp2)[i][1];
230  A[i][5] = (*pp2)[i][1];
231  A[i][6] = (*pp1)[i][0];
232  A[i][7] = (*pp1)[i][1];
233  A[i][8] = 1;
234  // cout<<"P1:"<<p1[i]<<p2[i]<<endl;
235  }
236 
237  BIAS::SVD A_SVD(A);
238  // cout<<"Linear FEst S:"<<A_SVD.GetS()<<endl;
239 
240  // get decomposition of F matrix
241  BIAS::Matrix<double> U, VT;
242  BIAS::Matrix<double> S(3, 3, 0.0);
244 
245  // solve equation system and compute least squares F usually with rank 3
246  VT = A_SVD.GetVT();
247 
248  for (unsigned int i=0; i<9; i++)
249  F[i/3][i%3] = VT[8][i];
250 
251  // re-add hartley normalization, so that f is valid for original coordinates
252  if (NormalizeHartley_)
253  F = K2.Transpose() * F * K1;
254 
255  // now F is a matrix probably of rank 3, limit to rank 2:
256  EnforceMaxRank2(F);
257 
258  return 0;
259 }
260 
261 int FMatrixEstimation::Optimize(BIAS::FMatrix& F, const std::vector<BIAS::HomgPoint2D> &p1,
262  const std::vector<BIAS::HomgPoint2D> &p2) {
263 #ifdef BIAS_DEBUG
264  if (p1.size()!=p2.size()) {
265  BIASERR("Vectors of corresponding points have different sizes !!!");
266  BIASABORT;
267  }
268  if (p1.size()<7) {
269  BIASERR("Too few points to optimize: "<<p1.size());
270  return -1;
271  }
272 #endif
273 
274  // we need to call an external function from levenberg-marquardt,
275  // prepare data structs
276  // warning: this section is not thread safe !
277  p1_ = &p1;
278  p2_ = &p2;
279 
280  HomgPoint2D epi1, epi2;
281  F.Normalize();
282  F.GetEpipolesHomogenized(epi1, epi2);
283 
284 // cout << "initial F " << F << endl;
285 // cout << "optimize Initial F " << epi1 << " " << epi2 << " " << F.GetResidualError(p1, p2) << endl;
286 
287  FMatrix F_normed;
288  ComputeNormFParam(F, F_normed);
289 
290  vector<double> vecFParamsStart, vecFParamsResult;
291  Vector<double> FParamsStart(7), FParamsResult(7);
292  currentPara_ = new Parametrization;
293  currentPara_->FMatrixToParams(F_normed, vecFParamsStart);
294  for (unsigned int i=0; i<7; i++)
295  FParamsStart[i] = vecFParamsStart[i];
296  int res;
297  if ((res = LevenbergMarquardt(&FErrorFunction_, this,
298  p1.size(), 7, FParamsStart, FParamsResult,
299  MINPACK_DEF_TOLERANCE))!=0) {
300  // BIASERR("Error in Levenberg-Marquardt-Optimization of F: "<<res);
301  return -1;
302  }
303  vecFParamsResult.resize(7);
304  for (unsigned int i=0; i<7; i++)
305  vecFParamsResult[i] = FParamsResult[i];
306  currentPara_->ParamsToFMatrix(F, vecFParamsResult);
307  delete currentPara_;
308  currentPara_ = NULL;
309 #ifdef BIAS_DEBUG
310  p1_ = NULL;
311  p2_ = NULL;
312 #endif
313 
314  F = FMatrix(NormF2_.Transpose() * F * NormF1_);
315 
316  return 0;
317 }
318 
319 int FMatrixEstimation::GoldStandard(BIAS::FMatrix& F, const std::vector<BIAS::HomgPoint2D> &p1,
320  const std::vector<BIAS::HomgPoint2D> &p2) {
321 
322  NormalizeHartley_ = true;
323 
324  int p1Size = p1.size();
325  BIASASSERT(p1Size == (int) p2.size());
326  BIASASSERT(p1Size >= 8);
327 
328  // std::vector<BIAS::HomgPoint2D> p1_15;
329  // std::vector<BIAS::HomgPoint2D> p2_15;
330  std::vector<BIAS::HomgPoint2D> p1_rest;
331  std::vector<BIAS::HomgPoint2D> p2_rest;
332 
333  for (int i = 0; i < p1Size; i++) {
334  if (i < 15) {
335  // p1_15.push_back(p1[i]);
336  // p2_15.push_back(p2[i]);
337  p1_rest.push_back(p1[i]);
338  p2_rest.push_back(p2[i]);
339  } else {
340  p1_rest.push_back(p1[i]);
341  p2_rest.push_back(p2[i]);
342  }
343  }
344 
345  // initialize F
346  Linear(F, p1, p2);
347  // std::cout << "Estimated F matrix " << 1/F[2][2] * F << std::endl;
348 
349  // initialize projection matrices with P1 = [I|0] and P2 = [[e']x F| e']
350  PMatrix P1, P2;
351  P1.SetIdentity();
352  P2.SetIdentity();
353 
354  HomgPoint2D epipole1, epipole2;
355  F.GetEpipoles(epipole1, epipole2);
356  if (epipole1[1]!=0.0)
357  epipole1.Normalize();
358  if (epipole2[1]!=0.0)
359  epipole2.Normalize();
360  // cout << "est. epipoles are "<< epipole1 <<" and "<<epipole2 <<endl;
361 
363  mMatrix = (Matrix3x3<double>)epipole2.GetSkewSymmetricMatrix() * F;
364  for (int i=0; i<3; i++) {
365  for (int j=0; j<3; j++) {
366  P2[i][j] = mMatrix[i][j];
367  }
368  }
369 
370  P2.SetCol(3, epipole2);
371 
372  // use correspondences p1 and p2 and F to triangulate 3D points
373  vector<HomgPoint3D> points3D;
374  Triangulation triangulator;
375  HomgPoint3D tempPoint3D;
376  for (int i = 0; i < p1Size; i++) {
377  triangulator.Optimal(P1, P2, p1_rest[i], p2_rest[i], tempPoint3D);
378  tempPoint3D.Homogenize();
379  points3D.push_back(tempPoint3D);
380  }
381 
382  // optimize 3D points and all 12 entries of P2
383 
384  // we need to call an external function from levenberg-marquardt,
385  // prepare data structs
386  // warning: this section is not thread safe !
387  p1_ = &p1;
388  p2_ = &p2;
389 
390  // build vector containing parameters to be optimized
391  // the first 12 positions contain the matrix P2, the others contain the 3D points
392  // [i+1], [i+2], [i+3]
393  Vector<double> FParamsStart(12 + 3*p1Size), FParamsResult(12 + 3*p1Size);
394 
395  // write P2 into FParamsStart
396  for (int i = 0; i < 3; i++) {
397  for (int j = 0; j < 4; j++) {
398  FParamsStart[i*4 + j] = P2[i][j];
399  }
400  }
401 
402  for (int i = 0; i < p1Size; i++) {
403  if (!points3D[i].IsHomogenized())
404  points3D[i].Homogenize();
405  FParamsStart[12 + i*3 ] = (points3D[i])[0];
406  FParamsStart[12 + i*3 + 1] = (points3D[i])[1];
407  FParamsStart[12 + i*3 + 2] = (points3D[i])[2];
408  }
409 
410  int res;
411  itersLM_ = 0;
412  if ((res = LevenbergMarquardt(&FGoldStandardErrorFunction_,
413  this, 4*p1Size, 12 + 3*p1Size, FParamsStart,
414  FParamsResult, MINPACK_DEF_TOLERANCE))!=0) {
415  BIASERR("Error in Levenberg-Marquardt-Optimization: "<<res);
416  return res;
417  }
418 
419  // rebuilding P2
420  for (int i = 0; i < 3; i++) {
421  for (int j = 0; j < 4; j++) {
422  P2[i][j]= FParamsResult[i*4 + j];
423  }
424  }
425 
426  P1.SetIdentity();
427 
428  // rebuilding F
429  epipole2[0] = FParamsResult[3];
430  epipole2[1] = FParamsResult[7];
431  epipole2[2] = FParamsResult[11];
432 
433  for (int i=0; i<3; i++) {
434  for (int j=0; j<3; j++) {
435  mMatrix[i][j] = FParamsResult[i*4 + j];
436  }
437  }
438 
439  F = (Matrix3x3<double>)epipole2.GetSkewSymmetricMatrix() * mMatrix;
440 
441  return 0;
442 }
443 
445  const BIAS::Vector<double> &F2,
446  std::vector<POLYNOMIALSOLVE_TYPE> &v) {
447 #ifdef BIAS_DEBUG
448  if (F1.size()!=9) {
449  BIASERR("Vector has wrong size "<<F1.size());
450  BIASABORT;
451  }
452  if (F2.size()!=9) {
453  BIASERR("Vector has wrong size "<<F2.size());
454  BIASABORT;
455  }
456  if (v.size()!=0) {
457  BIASERR("Vector v is not empty: "<<v.size());
458  BIASABORT;
459  }
460 #endif
461 
462  // We have two FMatrices in vector form F1, F2.
463  // We want to find a linear combination of these two which has rank 2
464 
465  // set up determinant equation using sarrus' rule for 3x3 matrices
466  // where our combined matrix F = alpha F1 + (1-alpha) F2
467  // we are looking for alpha, such that det(F)=0
468 
469  // first we need the differences
470  const double d[9] = { (F1[0]-F2[0]), (F1[1]-F2[1]), (F1[2]-F2[2]), (F1[3]-F2[3]), (F1[4]-F2[4]),
471  (F1[5]-F2[5]), (F1[6]-F2[6]), (F1[7]-F2[7]), (F1[8]-F2[8]) };
472 
473  // init coeffs with zero
474  v.resize(4, 0);
475 
476  // accessing matrix according to sarrus' rule
477  // better compute the determinant using short code from MAPLE or something
478  // like that, as it is done in v_x_l::FMatrixCompute7Point
479  // this here works definitely, but is quite slow
480  unsigned int x, y, z;
481  for (unsigned int i=0; i<3; i++) {
482  // + diagonal from top to bottom
483  x = i;
484  y = 3 + ((i+1)%3);
485  z = 6 + ((i+2)%3);
486  v[3] += d[x] * d[y] * d[z];
487  v[2] += d[x] * d[y] * F2[z] + d[x] * F2[y] * d[z] + F2[x] * d[y] * d[z];
488  v[1] += d[x] * F2[y] * F2[z] + F2[x] * d[y] * F2[z] + F2[x] * F2[y] * d[z];
489  v[0] += F2[x] * F2[y] * F2[z];
490 
491  // - diagonal from bottom to top
492  x = 6+i;
493  // y is the same
494  z = (i+2)%3;
495  v[3] -= d[x] * d[y] * d[z];
496  v[2] -= d[x] * d[y] * F2[z] + d[x] * F2[y] * d[z] + F2[x] * d[y] * d[z];
497  v[1] -= d[x] * F2[y] * F2[z] + F2[x] * d[y] * F2[z] + F2[x] * F2[y] * d[z];
498  v[0] -= F2[x] * F2[y] * F2[z];
499  }
500 }
501 
503  // get decomposition of F matrix
504  BIAS::Matrix<double> U, VT;
505  BIAS::Matrix<double> S(3, 3, 0.0);
507  // enforce rank 2 of F using SVD
509 
510  // get singular values of F
511  s = F_SVD.GetS();
512 
513  // compose S matrix
514  S[0][0] = s[0];
515  S[1][1] = s[1];
516  // leave smallest singular value at zero
517 
518  U = F_SVD.GetU();
519  VT = F_SVD.GetVT();
520 
521  // recompose F
522  F = U * S * VT;
523 }
524 
525 
526 /**
527  * rank 2 F matrix parametrization as implemented in Parametrization does not work in
528  * some cases, eg. when epipoles are at infinity. This normalizatin as described in
529  * Estimating the fundamental matrix by transforming image points in projective space
530  * by Zhang and Loop
531  * Application of this function can be seen in Optimize
532  */
534 
535  // cout << "initial F " << initialF << endl;
536 
537  // compute epipoles for initial matrix
538  HomgPoint2D epi1, epi2;
539  initialF.GetEpipoles(epi1, epi2);
540 
541 // cout << "epipoles " << epi1 << " " << epi2 << endl;
542 
543  // step 1 in paper
544  // initialize normalization matrices with identity
545  NormF1_.SetIdentity();
546  NormF2_.SetIdentity();
547 
548  // step 2 in paper
549  // find largest element in initial F matrix
550  double largest = 0.0;
551  int indexRow = 0;
552  int indexCol = 0;
553  for(int i = 0; i < 3; i++){
554  for(int j = 0; j < 3; j++){
555  if(initialF[i][j] > largest){
556  largest = initialF[i][j];
557  indexRow = i;
558  indexCol = j;
559  }
560  }
561  }
562 
563 // cout << "largest elem " << largest << " " << indexRow << " " << indexCol << endl;
564 
565 
566  Vector3<double> row1, row2;
567  double ep1, ep2;
568 
569  // step 3 in paper - permutation
570  if(indexCol != 0){
571  row1 = NormF1_.GetRow(0);
572  row2 = NormF1_.GetRow(indexCol);
573  NormF1_.SetRow(0, row2);
574  NormF1_.SetRow(indexCol, row1);
575  ep1 = epi1[0];
576  ep2 = epi1[indexCol];
577  epi1[indexCol] = ep1;
578  epi1[0] = ep2;
579  }
580 
581  // step 4 in paper - permutation
582  if(indexRow != 0){
583  row1 = NormF2_.GetRow(0);
584  row2 = NormF2_.GetRow(indexRow);
585  NormF2_.SetRow(0, row2);
586  NormF2_.SetRow(indexRow, row1);
587  ep1 = epi2[0];
588  ep2 = epi2[indexRow];
589  epi2[indexRow] = ep1;
590  epi2[0] = ep2;
591  }
592 
593  // step 5 in paper - permutation
594  if(fabs((float)epi1[1]) > fabs((float)epi1[2])){
595  row1 = NormF1_.GetRow(1);
596  row2 = NormF1_.GetRow(2);
597  NormF1_.SetRow(1, row2);
598  NormF1_.SetRow(2, row1);
599  ep1 = epi1[1];
600  ep2 = epi1[2];
601  epi1[2] = ep1;
602  epi1[1] = ep2;
603  }
604 
605  // step 5 in paper - permutation
606  if(fabs((float)epi2[1]) > fabs((float)epi2[2])){
607  row1 = NormF2_.GetRow(1);
608  row2 = NormF2_.GetRow(2);
609  NormF2_.SetRow(1, row2);
610  NormF2_.SetRow(2, row1);
611  ep1 = epi2[1];
612  ep2 = epi2[2];
613  epi2[1] = ep1;
614  epi2[2] = ep2;
615  }
616 
617  // cout << "resulting epipoles " << epi1 << " " << epi2 << endl;
618 
619 // cout << "normalization matrices " << NormF1_ << " " << NormF2_ << endl;
620 
621  normF = FMatrix(NormF2_ * initialF * NormF1_.Transpose());
622 
623 // cout << "norm F " << normF << endl;
624  normF.GetEpipoles(epi1, epi2);
625 // cout << "epipoles " << epi1 << " " << epi2 << endl;
626 
627 }
Vector< double > GetNullvector(const int last_offset=0)
return one of the nullvectors.
Definition: SVD.hh:404
class BIASGeometry_EXPORT FMatrix
int Optimize(BIAS::FMatrix &F, const std::vector< BIAS::HomgPoint2D > &p1, const std::vector< BIAS::HomgPoint2D > &p2)
optimize a given FMatrix regarding n 2d point correspondences
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 CheckCoefficients(std::vector< POLYNOMIALSOLVE_TYPE > &coeff, double eps=DBL_EPSILON)
removes leading zeros in coefficients
std::vector< BIAS::HomgPoint2D > const * p2_
pointer to vector of points in image2 (hack for Optimize)
bool ParamsToFMatrix(BIAS::FMatrix &Mat, const std::vector< double > &Params)
composes an F-matrix from the seven given parameters The deparametrization only works with the previo...
void ComputeNormFParam(const BIAS::FMatrix &initialF, BIAS::FMatrix &normF)
rank 2 F matrix parametrization as implemented in Parametrization does not work in some cases...
This class is used for parametrizing F- and H-matrices, generally for optimization purposes...
HomgPoint2D & Homogenize()
homogenize class data member elements to W==1 by divison by W
Definition: HomgPoint2D.hh:215
std::vector< BIAS::HomgPoint2D > const * p1_
pointer to vector of points in image1 (hack for Optimize)
void Homogenize()
homogenize class data member elements to W==1 by divison by W
Definition: HomgPoint3D.hh:308
void EnforceMaxRank2(BIAS::FMatrix &F)
enforces a maximum rank of two by setting the smallest singular value to zero
int Linear(BIAS::FMatrix &F, const std::vector< BIAS::HomgPoint2D > &p1, const std::vector< BIAS::HomgPoint2D > &p2)
compute an FMatrix from more than seven point correspondences
BIAS::Parametrization * currentPara_
base class for solving polynomial equations
Matrix< T > GetSkewSymmetricMatrix() const
constructs a skew symmetric 3x3 matrix from (*this), which can be used instead of the cross product ...
Definition: Vector3.cpp:257
Class for triangulation of 3Dpoints from 2D matches. Covariance matrix (refering to an uncertainty el...
void SetCol(const int row, const Vector< T > &data)
set a col of matrix from vector
Definition: Matrix.cpp:275
double GetEpipolarErrorHomogenized(const BIAS::HomgPoint2D &P1, const BIAS::HomgPoint2D &P2) const
computes error in epipolar geometry for the given correspondence P1;P2
Definition: FMatrixBase.hh:250
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
Matrix3x3< double > NormF2_
matrix for saving normalization of 2D points - important for f parametrization
const Matrix< double > & GetVT() const
return VT (=transposed(V))
Definition: SVD.hh:177
class representing a Fundamental matrix
Definition: FMatrix.hh:46
functions for estimating a fundamental matrix (FMatrix) given a set of 2d-2d correspondences (no outl...
long int LevenbergMarquardt(minpack_funcder_mn fun, void *p, long int m, long int n, Vector< double > &InitialGuess, Vector< double > &Result, double Tolerance)
Solves an overdetermined system f(x) = 0 of m non-linear equations with n parameters using the Levenb...
Definition: Minpack.cpp:97
const Vector< double > & GetS() const
return S which is a vector of the singular values of A in descending order.
Definition: SVD.hh:167
void GetEpipolesHomogenized(HomgPoint2D &E1, HomgPoint2D &E2) const
same as above, additionally homogenizes epipoles
Definition: FMatrix.hh:83
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
bool FMatrixToParams(const BIAS::FMatrix &Mat, std::vector< double > &Params)
parametizes an F-matrix to seven parameters
void GetDetPolynomial(const BIAS::Vector< double > &f1, const BIAS::Vector< double > &f2, std::vector< POLYNOMIALSOLVE_TYPE > &v)
set up a polynomial in alpha given Det(alpha*F1+(1-alpha)*F2)=0, where the f vectors are interpreted ...
int Optimal(PMatrix &P1, PMatrix &P2, HomgPoint2D &p1, HomgPoint2D &p2, HomgPoint3D &point3d)
method from Hartley Zisserman chapter 12.5 pp 315 first uses CorrectCorrespondences() and then calls ...
int Analytic(const std::vector< POLYNOMIALSOLVE_TYPE > &coeff, std::vector< POLYNOMIALSOLVE_TYPE > &sol)
solves polynomial of arbitrary order n&lt;=4 analytically coeff[n]x^n+...+coeff[2]x^2+coeff[1]x+coeff[0]...
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
int SevenPoint(std::vector< BIAS::FMatrix > &Fvec, const std::vector< BIAS::HomgPoint2D > &p1, const std::vector< BIAS::HomgPoint2D > &p2)
compute a vector of FMatrices from seven point correspondences
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
Definition: KMatrix.hh:48
int GetEpipoles(HomgPoint2D &Epipole1, HomgPoint2D &Epipole2) const
Computes the epipoles from this F Matrix.
Definition: FMatrix.cpp:69
describes a projective 3D -&gt; 2D mapping in homogenous coordinates
Definition: PMatrix.hh:88
int GoldStandard(BIAS::FMatrix &F, const std::vector< BIAS::HomgPoint2D > &p1, const std::vector< BIAS::HomgPoint2D > &p2)
Compute FMatrix using the Gold Standard algorithm as in Hartley and Zisserman p.
Vector3< T > & Normalize()
normalize this vector to length 1
Definition: Vector3.hh:663
Matrix3x3< double > NormF1_
matrix for saving normalization of 2D points - important for f parametrization
Subscript size() const
Definition: vec.h:262
T Normalize()
divide this by biggest absolute entry, returns biggest entry
Definition: Matrix3x3.cpp:580
class BIASGeometryBase_EXPORT HomgPoint3D