Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
PMatrixEstimation.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 "PMatrixEstimation.hh"
26 #include "MathAlgo/Minpack.hh"
27 #include <Base/Math/Operators.hh>
28 #include <Geometry/EMatrix.hh>
29 #include <Base/Common/BIASpragma.hh>
30 
31 #include <fstream>
32 
33 using namespace BIAS;
34 
35 /// error function, which punishes large differences of submatrix from
36 /// a rotation matrix
37 int DistanceFromRotation4Var(void *p,int n,const double *x, double *fvec, int iflag) {
38  if (n!=4) {
39  BIASERR("Caller supplied invalid n="<< (n));
40  return -1;
41  }
42  PMatrixEstimation *pCurrentObject = (PMatrixEstimation *)p;
43  BIAS::Matrix<double> E2(3, 1), BMat(1, 3);
44  for (int k=0; k< 3; k++) {
45  E2[k][0] = pCurrentObject->globalEpipole2_[k];
46  BMat[0][k] = x[3]*x[k];
47  }
48  BIAS::Matrix<double> Outer = E2*BMat;
49  BIAS::Matrix<double> SubMatrix = pCurrentObject->globalM2_*x[3] + Outer;
50 
51  // enforce all rows to be orthogonal
52  fvec[0] = SubMatrix.GetRow(0)*SubMatrix.GetRow(1);
53  fvec[1] = SubMatrix.GetRow(1)*SubMatrix.GetRow(2);
54  fvec[2] = SubMatrix.GetRow(2)*SubMatrix.GetRow(0);
55  // enforce all rows to be of unit length
56  fvec[3] = fabs(1.0-(SubMatrix.GetRow(0) * SubMatrix.GetRow(0)));
57  fvec[3] += fabs(1.0-(SubMatrix.GetRow(1) * SubMatrix.GetRow(1)));
58  fvec[3] += fabs(1.0-(SubMatrix.GetRow(2) * SubMatrix.GetRow(2)));
59  return 0;
60 }
61 
62 
64 {
65  NewDebugLevel("BIAS_FMATRIXDEBUG");
66  NewDebugLevel("BIAS_PMATRIXDEBUG");
67  NewDebugLevel("BIAS_FQuasiEuklid");
68 }
69 
70 int PMatrixEstimation::ComputeFromFDirect(BIAS::FMatrix &F, const double& BaselineMagnitude,
71  BIAS::PMatrix &P1, BIAS::PMatrix &P2) {
72 
73  HomgPoint2D Epipole1, Epipole2;
74  if (F.GetEpipoles(Epipole1, Epipole2)<0)
75  return -1;
76 
77  Epipole2.Normalize();
78  if (BaselineMagnitude<0.0)
79  Epipole2 *= -1.0;
80 
81  // initially set p2 to be the identity in its left 3x3 i.e. no rotation
82  // translation of P2 is set to Epipole2
83  InitP1P2Trans(P1, P2, Epipole2);
84 
85  //
86  RMatrix R;
87  ComputeRotation(F, Epipole1, Epipole2, R);
88  R = R.Transpose();
89 
90  // copy R into P2
91  for (unsigned int i = 0; i < 3; i++)
92  for (unsigned int j = 0; j < 3; j++)
93  P2[i][j] = R[i][j];
94 
95  // sanity check: has R rank 3 ?
97  Vector< double> S = RSVD.GetS();
98 
99  // catch division by zero problem in next check
100  if (S[0]<1e-10)
101  return -1;
102  // sanity check on rank 3 of R
103  if (S[2]/S[0]<1e-5)
104  return -1;
105 
106  // if (P2_base.NormFrobenius()<1e-10) return -1;
107 
110 
111  // assume p1.c==0:
112  double myscale = fabs(P2.GetC().NormL2() / BaselineMagnitude);
113  P2[0][3] /= myscale;
114  P2[1][3] /= myscale;
115  P2[2][3] /= myscale;
117  return 0;
118 }
119 
121  BIAS::HomgPoint2D &Epipole2, BIAS::RMatrix &R) {
122 
123  // set rotation part as described in Foerstner
124  Matrix3x3<double> ee = Epipole2.OuterProduct(Epipole1);
125  Matrix3x3<double> e, eF;
126  e.SetAsCrossProductMatrix(Epipole2);
127  eF=e*F;
128 
129  eF *= ee.NormFrobenius();
130  ee *= eF.NormFrobenius()/sqrt(2.0);
131 
132  R = eF+ee;
133 
134  // enforce right-handed rotation !
135  R /= (R.GetDeterminant() < 0.0) ? -sqrt(R[2][0]*R[2][0]+R[2][1]*R[2][1] + R[2][2]*R[2][2])
136  : sqrt(R[2][0]*R[2][0]+R[2][1]*R[2][1] + R[2][2] *R[2][2]);
137 
138  // check for positive optical axis of the second cemara because the first
139  // cameras axis is (0 , 0 , 1) otherwise rotate around baseline (epipole)
140  if (R[2][2] < 0.0) {
141  RMatrix rot(Epipole2, M_PI);
142  R = rot*R;
143  }
144  R = R.Transpose();
145 }
146 
149 
150  Vector3<double> Epipole2 = P2*P1.GetC();
151  Epipole2.MultiplyIP(Epipole2.NormL2());
152 
153  // compute homography for F
154  Matrix3x3<double> H, H1, H2;
155  for (unsigned int i = 0; i < 3; i++)
156  for (unsigned int j = 0; j < 3; j++) {
157  H1[i][j] = P1[i][j];
158  H2[i][j] = P2[i][j];
159  }
160  Matrix3x3<double> H1i;
161  int ires = H1.GetInverse(H1i);
162  if (ires!=0)
163  BIASERR("error: Unable to invert matrix "<<H1<<std::endl);
164  H = H2*H1i;
165  H2.SetAsCrossProductMatrix(Epipole2);
166  H1 = H2*H;
167  FMatrix F(H1);
168 
169  HomgPoint2D e1, e2;
170  F.GetEpipoles(e1, e2);
171  ComputeRotation(F, e1, e2, R);
172 
173  // compute center
174  for (unsigned int j = 0; j < 3; j++)
175  Epipole2[j] = P2[j][3];
176 
177  C = R.Transpose()*Epipole2;
178  C *= -1.0;
179 
180 }
181 
183  BIAS::PMatrix &P1, BIAS::PMatrix &P2) {
184 
185  Matrix<double> SubMatrix;
186  Vector<double> C(4);
187  Matrix3x3<double> M2Matrix;
188 
189  BCDOUT(BIAS_FMATRIXDEBUG, "F = " << F);
190 
191  HomgPoint2D Epipole1, Epipole2;
192  F.GetEpipoles(Epipole1, Epipole2);
193 
194  Epipole2.Normalize();
195  Epipole2 *= BaselineMagnitude;
196 
197  BCDOUT(BIAS_FQuasiEuklid, "Epipole 1 = " << Epipole1 << " Epipole2 = " << Epipole2);
198 
199  // initially set p2 to be the identity in its left 3x3 i.e. no rotation
200  InitP1P2Trans(P1, P2, Epipole2);
201  BCDOUT(BIAS_FQuasiEuklid, "After InitP1P2Trans P2= "<<P2);
202 
203  // find the decomposition of p2, and the closest p2 to the current setting.
204  //FindClosestP2(F, P1, P2, M2Matrix, C, Epipole2);
205  FindClosestP2(F, P2, M2Matrix, C, Epipole2);
206  BCDOUT(BIAS_FQuasiEuklid, "After FindClosestP2 P2 = "<< P2);
207 
208  // now want to adjust the three DOF in b_trivec to make (m2+e2 b^T) as
209  // close to orthogonal as possible.
210 
211  // memcpy (pm_m2_matrix, m2_matrix, sizeof (pm_m2_matrix));
212  // fm_compute_epipoles (f_matrix, &epipole1_trivec,
213  // &pm_epipole2_trivec);
214 
215 
216  // set stop criterion for powell:
217  double dMaxError = 1e-10;
218 
219  //these variables are now threadsave as members and accessible via
220  // pointer to class in Powell error function
221  globalEpipole2_ = Epipole2;
222  globalM2_ = (Matrix<double>)M2Matrix;
223 
224  // set current value as start value
225  Vector<double> CStart = C;
226 
227  int iError=0;
228  // minimize error funtion DistanceFromRotation4Var on P using Powell
229  if ((iError=Powell(&DistanceFromRotation4Var, this, CStart, C, dMaxError))<0) {
230  BIASERR("Minimization did not succeed, error code is "<<iError);
231  }
232  BCDOUT(BIAS_FQuasiEuklid, "C =" << C);
233 
234  //ho_trivec_outer_product (&pm_epipole2_trivec, &b_trivec, outer_matrix);
235  Matrix<double> E2(3, 1), BMat(1, 3);
236  for (int k=0; k< 3; k++) {
237  E2[k][0] = Epipole2[k];
238  BMat[0][k] = C[k];
239  }
240  Matrix<double> Outer = E2*BMat;
241  BCDOUT(BIAS_FQuasiEuklid, "M2Matrix = " << M2Matrix);
242  BCDOUT(BIAS_FQuasiEuklid, "Outer = " << Outer);
243 
244  SubMatrix = (Matrix<double>)(M2Matrix + (Matrix3x3<double>)Outer);
245  BCDOUT(BIAS_FQuasiEuklid, "SubMatrix = " << SubMatrix);
246 
247  // copy left part of P from submatrix
248  for (int row = 0; row < 3; row++)
249  for (int col = 0; col < 3; col++) {
250  P2[row][col] = SubMatrix [row][col];
251  }
252  BCDOUT(BIAS_FQuasiEuklid, "P2 = " << P2);
253 
254 }
255 
256 int PErrorFunction(void *p, int m, int n,const double *x, double *fvec, int iflag) {
257 
258  PMatrixEstimation *pCurrentPEstimation= (PMatrixEstimation *)p;
259 
260  // rebuild Kmatrix
262  K.SetFx(x[0]);
263  K.SetFy(x[0]);
264 
265  K.SetHx(((double)pCurrentPEstimation->width_-1.0)/2.0);
266  K.SetHy(((double)pCurrentPEstimation->height_-1.0)/2.0);
267  K[2][2] = 1.0;
268 
269  // rebuild epipole'
270  Vector3<double> t;
271  t[0] = 1;
272  t[1] = x[1];
273  t[2] = x[2];
274 
275  t = t.CoordSphereToEuclidean();
276 
277  // rebuild Rmatrix
279  R.SetXYZ(x[3], x[4], x[5]);
280 
281  // get correspondences
282  const unsigned int uiDataSize = pCurrentPEstimation->p1_->size();
283  const std::vector<BIAS::HomgPoint2D> &p1 = *pCurrentPEstimation->p1_;
284  const std::vector<BIAS::HomgPoint2D> &p2 = *pCurrentPEstimation->p2_;
285 
286  // rebuild F matrix
287  FMatrix F;
288  K = K.Invert();
290 
291  pCurrentPEstimation->lastError_ = 0;
292  for (unsigned int j=0; j<uiDataSize; j++) {
293  fvec[j] = F.GetEpipolarErrorHomogenized(p1[j], p2[j]);
294  pCurrentPEstimation->lastError_ += fvec[j];
295  }
296  (pCurrentPEstimation->errorSum_).push_back(pCurrentPEstimation->lastError_);
297  pCurrentPEstimation->lastError_ /= uiDataSize;
298  return 0;
299 }
300 
301 int PMatrixEstimation::AutoCalib(const BIAS::FMatrix &F, const int width, const int height,
302  const std::vector<BIAS::HomgPoint2D> &p1, const std::vector<BIAS::HomgPoint2D> &p2,
303  BIAS::PMatrix &P1, BIAS::PMatrix &P2) {
304 
305  // prepare private vars for Levenberg-Marquardt algorithm (are equal for all trials)
306  width_ = width;
307  height_ = height;
308 
309  // we need to call an external function from levenberg-marquardt,
310  // prepare data structs
311  // warning: this section is not thread safe !
312  p1_ = &p1;
313  p2_ = &p2;
314 
315  // prepare initial K matrix with width + height as initial guess
317  // camera matrix for both cameras
318  K.SetFx(((double)width + (double)height));
319  K.SetFy(((double)width + (double)height));
320  std::vector<double> focalLengths;
321 
322  focalLengths.push_back(((double)width + (double)height)*2.0);
323  //focalLengths.push_back((double)width + (double)height);
324 // for (int foc = 2; foc < BIAS_MAXNUMAUTOCALIBITERS; foc++) {
325 
326  for (int foc = 1; foc < BIAS_MAXNUMAUTOCALIBITERS; foc++) {
327  if(focalLengths[foc-1]-50 < 100) break;
328  focalLengths.push_back(focalLengths[foc-1]-50);
329  }
330  // in image coordinates
331  double mx = ((double)width - 1.0) / 2.0;
332  double my = ((double)height - 1.0) / 2.0;
333  K.SetHx(mx);
334  K.SetHy(my);
335  K.SetSkew(0.0);
336 
337  K[2][2] = 1;
338 
339  std::vector<PMatrix> P1Results;
340  std::vector<PMatrix> P2Results;
341  std::vector<double> smallestError;
342 
343  // Call to private AutoCalib
344  int res = 0;
345  for (unsigned int calibIters = 0; calibIters < focalLengths.size(); calibIters++) {
346  K.SetFx(focalLengths[calibIters]);
347  K.SetFy(focalLengths[calibIters]);
348  res = AutoCalib_(F, p1.size(), K, P1, P2);
349  std::cout << "result of AutoCalib_ " << res << " focal length guess " << focalLengths[calibIters] << " est focal length " << K.GetFx() << " error " << lastError_ << std::endl;
350  if (res == 0) {
351  P1Results.push_back(P1);
352  P2Results.push_back(P2);
353  smallestError.push_back(lastError_);
354  }
355  }
356 
357  // find best results and fix baseline direction
358  if (P1Results.size() >= 1) {
359 
360  P1 = P1Results[0];
361  P2 = P2Results[0];
362  // find two closest focal lengths
363  double errorS = DBL_MAX;
364 
365  for (unsigned int i = 0; i < P1Results.size(); i++) {
366  if (errorS > smallestError[i]) {
367  errorS = smallestError[i];
368  P1 = P1Results[i];
369  P2 = P2Results[i];
370  } // end if shortestDist
371  } // end for i
372 
374  RMatrix R = P2.GetR();
375  Vector3<double> C = P2.GetC();
376  K = P2.GetK();
377 
378  // check if baseline points into the right direction, check if "other" rotation yields more
379  // points in front of the camera
380  RMatrix RTmp = R;
381  Vector3<double> CTmp = C;
382  EMatrix E;
383  E.InitFromF(F, K, K);
384  E.GetRotationTranslation(RTmp, CTmp, p1, p2);
385 
386  P2.SetIdentity();
387  P2.Compose(K, RTmp, CTmp);
388 
389  } else { // else not even one valid result, indicate error
390  P1.SetIdentity();
391  P2.SetIdentity();
392  return -1;
393  }
394 
395 // write errors into a file
396 // std::fstream filestr;
397 // filestr.open ("errors.txt", std::fstream::in | std::fstream::out | std::fstream::app);
398 // double lowest = DBL_MAX;
399 // int lowestIndex;
400 // for(unsigned int i = 0; i < errorAll_.size(); i++){
401 // filestr << focalLengths[i] << " " << (errorAll_[i]).back();
402 // lowest = DBL_MAX;
403 // for(unsigned int j = 0; j < (errorAll_[i]).size(); j++){
404 // if((errorAll_[i])[j] < lowest){
405 // lowest = (errorAll_[i])[j];
406 // lowestIndex = j;
407 // }
408 // }
409 // filestr << " " << lowest << std::endl;
410 // }
411 //
412 // filestr.close();
413 
414  return 0;
415 }
416 
417 int PMatrixEstimation::AutoCalib_(const BIAS::FMatrix &F, const long int numCorrs, BIAS::KMatrix &K,
418  BIAS::PMatrix &P1, BIAS::PMatrix &P2) {
419 
420  // save original focal length
421  double focalLength_saved = K.GetFx();
422  double princPointX_saved = K.GetHx();
423  double princPointY_saved = K.GetHy();
424 
425 // int numParams = 7;
426 // to do: remove when done testing
427  long int numParams = 6;
428 
429  EMatrix E;
430  E.InitFromF(F, K, K);
431 
432 // std::cout << "AutoCalib_ K " << K << std::endl;
433 // std::cout << "AutoCalib_ F " << 1/F[2][2] * F << std::endl;
434 
435  // use foerstner method for rotation estimation
436  double baselineMagnitude = 1.0;
437  ComputeFromFDirect(E, baselineMagnitude, P1, P2);
438 
439 // std::cout << "AutoCalib_ P1 and P2 " << P1 << " " << P2 << std::endl;
440 
441  // decompose P2 in order to gain parameters for Levenberg-Marquardt algorithm
443 
444  RMatrix R;
445  for (int i = 0; i < 3; i++) {
446  for (int j = 0; j < 3; j++) {
447  R[i][j] = P2[i][j];
448  }
449  }
450  R = R.Transpose();
451  Vector3<double> t = P2.GetCol(3);
452 
453 
454  // save initial R and t for later
455  RMatrix R_saved = R;
456  Vector3<double> t_saved = t;
457 
458 // std::cout << "epipole " << t << std::endl;
459 
460  t = t.CoordEuclideanToSphere();
461 
462  double phiX, phiY, phiZ;
463  R.GetRotationAnglesXYZ(phiX, phiY, phiZ);
464 
465 // std::cout << "AutoCalib_ Rotation angles " << phiX*180/M_PI << " " << phiY*180/M_PI << " " << phiZ*180/M_PI << std::endl;
466 //
467 // std::cout << "autoCalib_ rotation matrix " << R << std::endl;
468 
469 
470 
471  // assuming focal length is equal for both directions
472  double focalLength = K.GetFx();
473 
474  // build vector containing parameters to be optimized
475  Vector<double> FParamsStart(numParams), FParamsResult(numParams);
476 
477  // TODO remove when done testing
478 // FParamsStart[0] = t[1];
479 // FParamsStart[1] = t[2];
480 // FParamsStart[2] = phiX;
481 // FParamsStart[3] = phiY;
482 // FParamsStart[4] = phiZ;
483 
484  FParamsStart[0] = focalLength;
485  FParamsStart[1] = t[1];
486  FParamsStart[2] = t[2];
487  FParamsStart[3] = phiX;
488  FParamsStart[4] = phiY;
489  FParamsStart[5] = phiZ;
490 
491 
492  long int res;
493  errorSum_.clear();
494  if ((res = LevenbergMarquardt(&PErrorFunction, this,
495  numCorrs, numParams, FParamsStart, FParamsResult,
496  MINPACK_DEF_TOLERANCE))!=0) {
497  BIASERR("Error in Levenberg-Marquardt-Optimization: "<<res);
498  }
499 
500  // rebuild, K, e, and R
501  K.SetIdentity();
502  K.SetHx(princPointX_saved);
503  K.SetHy(princPointY_saved);
504  // set only in case res == 5
505  K.SetFx(focalLength_saved);
506  K.SetFy(focalLength_saved);
507 
508  if(res == 5) return -1;
509 
510  errorAll_.push_back(errorSum_);
511 
512  K.SetFx(FParamsResult[0]);
513  K.SetFy(FParamsResult[0]);
514 // std::cout << "K still whole ? " << K << std::endl;
515 
516  // Check if estimated focal length is valid
517 
518  if(K.GetFx() < 100) return -2;
519  if(K.GetFx() > 10000) return -2;
520 // double testFocalLength = FParamsResult[0]/focalLength_saved;
521 // if ((testFocalLength >= 10) || res == 5) {
522 // return -1;
523 // }
524 // if (FParamsResult[0]<=0.0) {
525 // return -2;
526 // }
527 
528  // reconstruct t
529 // t[0] = 1;
530 // t[1] = FParamsResult[0];
531 // t[2] = FParamsResult[1];
532  // TODO remove when done testing
533  t[0] = 1;
534  t[1] = FParamsResult[1];
535  t[2] = FParamsResult[2];
536 
537  t = t.CoordSphereToEuclidean();
538 
539  t = t.Normalize();
540 
541  // reconstruct R
542  R.SetIdentity();
543 // R.SetXYZ(FParamsResult[2], FParamsResult[3], FParamsResult[4]);
544  R.SetXYZ(FParamsResult[3], FParamsResult[4], FParamsResult[5]);
545 
546  //reconstruct P1 and P2 with new Kmatrix
547  P1.SetIdentity();
548  P1 = K * P1;
550  // rebuild P2
551  P2.SetIdentity();
552  P2.Compose(K, R, (-1.0)*R*t);
553 
554  // std::cout << "P2 after successful autocalib_ " << P2 << std::endl;
555  return 0;
556 }
557 
558 
559 
561  // BCDOUT(BIAS_FMATRIXDEBUG,"In InitP1P2Trans E2 = " << Epipole2);
562  P1.set_identity();
563  P2.set_identity();
564 
565  P2[0][3] = Epipole2[0];
566  P2[1][3] = Epipole2[1];
567  P2[2][3] = Epipole2[2];
568 }
569 
570 /*---------------------------------------------------------------------------
571  given approximate P2, compute the nearest value of P2 which is exactly
572  compatible with P1 and F, using the method in the IJCV paper. variable names
573  are from the paper too.
574  ----------------------------------------------------------------------------*/
576 //BIAS::PMatrix &P1,
577  BIAS::PMatrix &P2, Matrix3x3<double> &M2Matrix, Vector<double> &C, HomgPoint2D& Epipole2) {
578 
579  BCDOUT(BIAS_FMATRIXDEBUG, "F = " << F);
580  Matrix3x3<double> SkewMatrix, SubMatrix;
581 
582  double DotProduct=0.0, Magnitude;
583 
584  Matrix<double> A(9, 4);
585  Vector<double> B(9);
586 
587  F.DecomposetoSR(SkewMatrix, M2Matrix);
588 
589  BCDOUT(BIAS_PMATRIXDEBUG, "M2Matrix = " << M2Matrix);
590 
591  A[0][0] = M2Matrix [0][0];
592  A[0][1] = Epipole2[0];
593  A[0][2] = 0;
594  A[0][3] = 0;
595  B[0] = P2[0][0];
596 
597  A[1][0] = M2Matrix[0][1];
598  A[1][1] = 0;
599  A[1][2] = Epipole2[0];
600  A[1][3] = 0;
601  B[1] = P2[0][1];
602 
603  A[2][0] = M2Matrix[0][2];
604  A[2][1] = 0;
605  A[2][2] = 0;
606  A[2][3] = Epipole2[0];
607  B[2] = P2[0][2];
608 
609  A[3][0] = M2Matrix[1][0];
610  A[3][1] = Epipole2[1];
611  A[3][2] = 0;
612  A[3][3] = 0;
613  B[3] = P2[1][0];
614 
615  A[4][0] = M2Matrix[1][1];
616  A[4][1] = 0;
617  A[4][2] = Epipole2[1];
618  A[4][3] = 0;
619  B[4] = P2[1][1];
620 
621  A[5][0] = M2Matrix[1][2];
622  A[5][1] = 0;
623  A[5][2] = 0;
624  A[5][3] = Epipole2[1];
625  B[5] = P2[1][2];
626 
627  A[6][0] = M2Matrix[2][0];
628  A[6][1] = Epipole2[2];
629  A[6][2] = 0;
630  A[6][3] = 0;
631  B[6] = P2[2][0];
632 
633  A[7][0] = M2Matrix[2][1];
634  A[7][1] = 0;
635  A[7][2] = Epipole2[2];
636  A[7][3] = 0;
637  B[7] = P2[2][1];
638 
639  A[8][0] = M2Matrix[2][2];
640  A[8][1] = 0;
641  A[8][2] = 0;
642  A[8][3] = Epipole2[2];
643  B[8] = P2[2][2];
644 
645  BCDOUT(BIAS_PMATRIXDEBUG, "A = " << A);
646  BCDOUT(BIAS_PMATRIXDEBUG, "B = " << B);
647 
648  //ma2_solve_equation_svd (a_matrix, x_vector, b_vector);
649  Matrix<double> AT = A.Transpose();
650  BCDOUT(BIAS_PMATRIXDEBUG, "AT = " << AT);
651  Vector<double> ATB = AT*B;
652  BCDOUT(BIAS_PMATRIXDEBUG, "ATB = " << ATB);
653  Matrix<double> ATA = AT*A;
654  BCDOUT(BIAS_PMATRIXDEBUG, "ATA = " << ATA);
655 
657  BCDOUT(BIAS_PMATRIXDEBUG, "Lapack_LU_linear_solve X = " << X);
658  M2Matrix *= X[0];
659  BCDOUT(BIAS_PMATRIXDEBUG, "M2Matrix = " << M2Matrix);
660 
661  // ho_trivec_outer_product (&epipole2_trivec, b_trivec_ptr, outer_matrix);
662  Matrix<double> E2(3, 1), vMat(1, 3);
663  for (int k=0; k< 3; k++) {
664  E2[k][0] = Epipole2[k];
665  vMat[0][k] = X[k+1];
666  C[k] = X[k+1];
667  }
668  C[3]=1;
669 
670  Matrix<double> Outer=E2*vMat;
671  SubMatrix = Outer + (Matrix<double>)M2Matrix;
672 
673  Vector3<double> Col(P2[0][3], P2[1][3], P2[2][3]);
674 
675  Magnitude = Col.NormL2();
676  DotProduct = Col * Epipole2;
677 
678  if (DotProduct > 0)
679  Epipole2 *= Magnitude;
680  else
681  Epipole2 *= -Magnitude;
682 
683  P2[0][0] = SubMatrix[0][0];
684  P2[0][1] = SubMatrix[0][1];
685  P2[0][2] = SubMatrix[0][2];
686  P2[0][3] = Epipole2[0];
687  P2[1][0] = SubMatrix[1][0];
688  P2[1][1] = SubMatrix[1][1];
689  P2[1][2] = SubMatrix[1][2];
690  P2[1][3] = Epipole2[1];
691  P2[2][0] = SubMatrix[2][0];
692  P2[2][1] = SubMatrix[2][1];
693  P2[2][2] = SubMatrix[2][2];
694  P2[2][3] = Epipole2[2];
695 
696 }
697 
698 
699 
int AutoCalib_(const BIAS::FMatrix &F, const long int numCorrs, BIAS::KMatrix &K, BIAS::PMatrix &P1, BIAS::PMatrix &P2)
private function, that can determine focal length using different initial guesses for AutoCalib ...
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.
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Definition: SVD.hh:92
std::vector< std::vector< double > > errorAll_
BIAS::Vector3< T > CoordEuclideanToSphere() const
coordinate transform.
Definition: Vector3.cpp:113
int GetRotationTranslation(RMatrix &R, Vector3< double > &C, const std::vector< HomgPoint2D > &inlier1, const std::vector< HomgPoint2D > &inlier2)
find R and C(direction), such that maximum number of 3d points triangulated from correspondences inli...
Definition: EMatrix.cpp:64
void FindClosestP2(BIAS::FMatrix &F, BIAS::PMatrix &P2, Matrix3x3< double > &M2Matrix, Vector< double > &C, HomgPoint2D &Epipole2)
given approximate P2, compute the nearest value of P2 which is exactly compatible with P1 and F ...
Matrix< T > Transpose() const
transpose function, storing data destination matrix
Definition: Matrix.hh:823
int AutoCalib(const BIAS::FMatrix &F, const int width, const int height, const std::vector< BIAS::HomgPoint2D > &p1, const std::vector< BIAS::HomgPoint2D > &p2, BIAS::PMatrix &P1, BIAS::PMatrix &P2)
given an FMatrix, width and height of the images, and the 2D-correspondences of two images...
void OuterProduct(const Vector3< T > &v, Matrix3x3< T > &res) const
outer product, constructs a matrix.
Definition: Vector3.cpp:151
void SetSkew(const KMATRIX_TYPE &val)
Definition: KMatrix.cpp:81
Vector< T > GetCol(const int &col) const
return a copy of column &quot;col&quot;, zero based counting
Definition: Matrix.cpp:252
static void ComputeRotationCenter(BIAS::PMatrix P1, BIAS::PMatrix P2, BIAS::RMatrix &R, BIAS::Vector3< double > &C)
int GetR(Matrix3x3< double > &R)
Definition: PMatrix.cpp:204
class representing an Essential matrix
Definition: EMatrix.hh:52
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
void ComputeFromFQuasiEuklid(BIAS::FMatrix &F, 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...
BIAS::Vector< double > Lapack_LU_linear_solve(const BIAS::Matrix< double > &A, const BIAS::Vector< double > &b)
solve linear equations using LU factorization
Definition: Lapack.cpp:269
double lastError_
remember error of PErrorFunc
void DecomposetoSR(BIAS::Matrix3x3< double > &skew_matrix, BIAS::Matrix3x3< double > &rank3_matrix)
Decomposes f matrix to product (skew)(rank3)
Definition: FMatrix.cpp:106
3D rotation matrix
Definition: RMatrix.hh:49
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
KMATRIX_TYPE GetHy() const
Definition: KMatrix.cpp:86
double NormFrobenius() const
Definition: Matrix3x3.hh:446
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
int GetInverse(Matrix3x3< T > &inv) const
Matrix inversion: inverts this and stores resulty in argument inv.
Definition: Matrix3x3.cpp:373
std::vector< BIAS::HomgPoint2D > const * p1_
pointer to vector of points in image1 (hack for Levenberg Marquardt)
std::vector< double > errorSum_
void InitP1P2Trans(BIAS::PMatrix &P1, BIAS::PMatrix &P2, BIAS::HomgPoint2D &Epipole2)
set P1 to identity, set P2 to identity with last column epipole2
class representing a Fundamental matrix
Definition: FMatrix.hh:46
void InvalidateDecomposition()
to re-Decompose_() after filling with data use this.
Definition: PMatrix.hh:499
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
Vector< T > GetRow(const int &row) const
return a copy of row &quot;row&quot; of this matrix, zero based counting
Definition: Matrix.cpp:233
const Vector< double > & GetS() const
return S which is a vector of the singular values of A in descending order.
Definition: SVD.hh:167
long int NewDebugLevel(const std::string &name)
creates a new debuglevel
Definition: Debug.hh:474
KMATRIX_TYPE GetFx() const
Definition: KMatrix.cpp:74
void set_identity()
Convert the PMatrixBase to &#39;identity&#39; matrix, overriding the Matrix3x4 method: 1 0 0 0 0 1 0 0 0 0 1 ...
Definition: PMatrixBase.hh:212
void MultiplyIP(const T &scalar)
Multiplication (in place) of an scalar.
Definition: Vector3.hh:326
KMATRIX_TYPE GetHx() const
Definition: KMatrix.cpp:83
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...
BIAS::Vector3< T > CoordSphereToEuclidean() const
coordinate transfrom.
Definition: Vector3.cpp:78
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
std::vector< BIAS::HomgPoint2D > const * p2_
pointer to vector of points in image2 (hack for Levenberg Marquardt)
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
long int Powell(minpack_func_nn fun, void *p, Vector< double > &InitialGuess, Vector< double > &Result, double Tolerance)
Solve a system f(x) = 0 of n non-linear equations with n unknowns using the Powell hybrid method...
Definition: Minpack.cpp:35
static void ComputeRotation(BIAS::FMatrix &F, BIAS::HomgPoint2D &Epipole1, BIAS::HomgPoint2D &Epipole2, BIAS::RMatrix &R)
describes a projective 3D -&gt; 2D mapping in homogenous coordinates
Definition: PMatrix.hh:88
void SetAsCrossProductMatrix(const Vector3< T > &vec)
Sets matrix from vector as cross product matrix of this vector.
Definition: Matrix3x3.cpp:275
void SetHx(const KMATRIX_TYPE &val)
Definition: KMatrix.cpp:84
KMatrix Invert() const
returns analyticaly inverted matrix
Definition: KMatrix.cpp:31
PMatrixEstimation()
Standard constructor does nothing.
Vector3< T > & Normalize()
normalize this vector to length 1
Definition: Vector3.hh:663
int width_
image width (hack for Levenberg Marquardt)
int height_
image height (hack for Levenberg Marquardt)
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
Definition: Vector3.hh:633
BIAS::Matrix< double > globalM2_
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
void SetIdentity()
set the elements of this matrix to the identity matrix (possibly overriding the inherited method) ...
Definition: Matrix3x3.hh:429
int GetK(KMatrix &K)
calibration matrix
Definition: PMatrix.cpp:220
BIAS::HomgPoint2D globalEpipole2_