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>
37 int DistanceFromRotation4Var(
void *p,
int n,
const double *x,
double *fvec,
int iflag) {
39 BIASERR(
"Caller supplied invalid n="<< (n));
44 for (
int k=0; k< 3; k++) {
46 BMat[0][k] = x[3]*x[k];
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)));
78 if (BaselineMagnitude<0.0)
91 for (
unsigned int i = 0; i < 3; i++)
92 for (
unsigned int j = 0; j < 3; j++)
112 double myscale = fabs(P2.
GetC().NormL2() / BaselineMagnitude);
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]);
155 for (
unsigned int i = 0; i < 3; i++)
156 for (
unsigned int j = 0; j < 3; j++) {
163 BIASERR(
"error: Unable to invert matrix "<<H1<<std::endl);
174 for (
unsigned int j = 0; j < 3; j++)
175 Epipole2[j] = P2[j][3];
189 BCDOUT(BIAS_FMATRIXDEBUG,
"F = " << F);
195 Epipole2 *= BaselineMagnitude;
197 BCDOUT(BIAS_FQuasiEuklid,
"Epipole 1 = " << Epipole1 <<
" Epipole2 = " << Epipole2);
201 BCDOUT(BIAS_FQuasiEuklid,
"After InitP1P2Trans P2= "<<P2);
206 BCDOUT(BIAS_FQuasiEuklid,
"After FindClosestP2 P2 = "<< P2);
217 double dMaxError = 1e-10;
229 if ((iError=
Powell(&DistanceFromRotation4Var,
this, CStart, C, dMaxError))<0) {
230 BIASERR(
"Minimization did not succeed, error code is "<<iError);
232 BCDOUT(BIAS_FQuasiEuklid,
"C =" << C);
236 for (
int k=0; k< 3; k++) {
237 E2[k][0] = Epipole2[k];
241 BCDOUT(BIAS_FQuasiEuklid,
"M2Matrix = " << M2Matrix);
242 BCDOUT(BIAS_FQuasiEuklid,
"Outer = " << Outer);
245 BCDOUT(BIAS_FQuasiEuklid,
"SubMatrix = " << SubMatrix);
248 for (
int row = 0; row < 3; row++)
249 for (
int col = 0; col < 3; col++) {
250 P2[row][col] = SubMatrix [row][col];
252 BCDOUT(BIAS_FQuasiEuklid,
"P2 = " << P2);
256 int PErrorFunction(
void *p,
int m,
int n,
const double *x,
double *fvec,
int iflag) {
265 K.
SetHx(((
double)pCurrentPEstimation->
width_-1.0)/2.0);
266 K.
SetHy(((
double)pCurrentPEstimation->
height_-1.0)/2.0);
279 R.
SetXYZ(x[3], x[4], x[5]);
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_;
292 for (
unsigned int j=0; j<uiDataSize; j++) {
297 pCurrentPEstimation->
lastError_ /= uiDataSize;
302 const std::vector<BIAS::HomgPoint2D> &p1,
const std::vector<BIAS::HomgPoint2D> &p2,
318 K.
SetFx(((
double)width + (
double)height));
319 K.
SetFy(((
double)width + (
double)height));
320 std::vector<double> focalLengths;
322 focalLengths.push_back(((
double)width + (
double)height)*2.0);
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);
331 double mx = ((double)width - 1.0) / 2.0;
332 double my = ((double)height - 1.0) / 2.0;
339 std::vector<PMatrix> P1Results;
340 std::vector<PMatrix> P2Results;
341 std::vector<double> smallestError;
345 for (
unsigned int calibIters = 0; calibIters < focalLengths.size(); calibIters++) {
346 K.
SetFx(focalLengths[calibIters]);
347 K.
SetFy(focalLengths[calibIters]);
349 std::cout <<
"result of AutoCalib_ " << res <<
" focal length guess " << focalLengths[calibIters] <<
" est focal length " << K.
GetFx() <<
" error " <<
lastError_ << std::endl;
351 P1Results.push_back(P1);
352 P2Results.push_back(P2);
358 if (P1Results.size() >= 1) {
363 double errorS = DBL_MAX;
365 for (
unsigned int i = 0; i < P1Results.size(); i++) {
366 if (errorS > smallestError[i]) {
367 errorS = smallestError[i];
421 double focalLength_saved = K.
GetFx();
422 double princPointX_saved = K.
GetHx();
423 double princPointY_saved = K.
GetHy();
427 long int numParams = 6;
436 double baselineMagnitude = 1.0;
445 for (
int i = 0; i < 3; i++) {
446 for (
int j = 0; j < 3; j++) {
462 double phiX, phiY, phiZ;
472 double focalLength = K.
GetFx();
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;
495 numCorrs, numParams, FParamsStart, FParamsResult,
496 MINPACK_DEF_TOLERANCE))!=0) {
497 BIASERR(
"Error in Levenberg-Marquardt-Optimization: "<<res);
502 K.
SetHx(princPointX_saved);
503 K.
SetHy(princPointY_saved);
505 K.
SetFx(focalLength_saved);
506 K.
SetFy(focalLength_saved);
508 if(res == 5)
return -1;
512 K.
SetFx(FParamsResult[0]);
513 K.
SetFy(FParamsResult[0]);
518 if(K.
GetFx() < 100)
return -2;
519 if(K.
GetFx() > 10000)
return -2;
534 t[1] = FParamsResult[1];
535 t[2] = FParamsResult[2];
544 R.
SetXYZ(FParamsResult[3], FParamsResult[4], FParamsResult[5]);
565 P2[0][3] = Epipole2[0];
566 P2[1][3] = Epipole2[1];
567 P2[2][3] = Epipole2[2];
579 BCDOUT(BIAS_FMATRIXDEBUG,
"F = " << F);
582 double DotProduct=0.0, Magnitude;
589 BCDOUT(BIAS_PMATRIXDEBUG,
"M2Matrix = " << M2Matrix);
591 A[0][0] = M2Matrix [0][0];
592 A[0][1] = Epipole2[0];
597 A[1][0] = M2Matrix[0][1];
599 A[1][2] = Epipole2[0];
603 A[2][0] = M2Matrix[0][2];
606 A[2][3] = Epipole2[0];
609 A[3][0] = M2Matrix[1][0];
610 A[3][1] = Epipole2[1];
615 A[4][0] = M2Matrix[1][1];
617 A[4][2] = Epipole2[1];
621 A[5][0] = M2Matrix[1][2];
624 A[5][3] = Epipole2[1];
627 A[6][0] = M2Matrix[2][0];
628 A[6][1] = Epipole2[2];
633 A[7][0] = M2Matrix[2][1];
635 A[7][2] = Epipole2[2];
639 A[8][0] = M2Matrix[2][2];
642 A[8][3] = Epipole2[2];
645 BCDOUT(BIAS_PMATRIXDEBUG,
"A = " << A);
646 BCDOUT(BIAS_PMATRIXDEBUG,
"B = " << B);
650 BCDOUT(BIAS_PMATRIXDEBUG,
"AT = " << AT);
652 BCDOUT(BIAS_PMATRIXDEBUG,
"ATB = " << ATB);
654 BCDOUT(BIAS_PMATRIXDEBUG,
"ATA = " << ATA);
657 BCDOUT(BIAS_PMATRIXDEBUG,
"Lapack_LU_linear_solve X = " << X);
659 BCDOUT(BIAS_PMATRIXDEBUG,
"M2Matrix = " << M2Matrix);
663 for (
int k=0; k< 3; k++) {
664 E2[k][0] = Epipole2[k];
675 Magnitude = Col.NormL2();
676 DotProduct = Col * Epipole2;
679 Epipole2 *= Magnitude;
681 Epipole2 *= -Magnitude;
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];
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.
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...
std::vector< std::vector< double > > errorAll_
BIAS::Vector3< T > CoordEuclideanToSphere() const
coordinate transform.
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...
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
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.
void SetSkew(const KMATRIX_TYPE &val)
Vector< T > GetCol(const int &col) const
return a copy of column "col", zero based counting
static void ComputeRotationCenter(BIAS::PMatrix P1, BIAS::PMatrix P2, BIAS::RMatrix &R, BIAS::Vector3< double > &C)
int GetR(Matrix3x3< double > &R)
class representing an Essential matrix
Matrix< T > GetSkewSymmetricMatrix() const
constructs a skew symmetric 3x3 matrix from (*this), which can be used instead of the cross product ...
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
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)
double GetEpipolarErrorHomogenized(const BIAS::HomgPoint2D &P1, const BIAS::HomgPoint2D &P2) const
computes error in epipolar geometry for the given correspondence P1;P2
KMATRIX_TYPE GetHy() const
double NormFrobenius() const
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 (!)...
int GetInverse(Matrix3x3< T > &inv) const
Matrix inversion: inverts this and stores resulty in argument inv.
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
void InvalidateDecomposition()
to re-Decompose_() after filling with data use this.
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...
Vector< T > GetRow(const int &row) const
return a copy of row "row" of this matrix, zero based counting
const Vector< double > & GetS() const
return S which is a vector of the singular values of A in descending order.
long int NewDebugLevel(const std::string &name)
creates a new debuglevel
KMATRIX_TYPE GetFx() const
void set_identity()
Convert the PMatrixBase to 'identity' matrix, overriding the Matrix3x4 method: 1 0 0 0 0 1 0 0 0 0 1 ...
void MultiplyIP(const T &scalar)
Multiplication (in place) of an scalar.
KMATRIX_TYPE GetHx() const
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...
compute standard P1/P2 from F.
void SetFx(const KMATRIX_TYPE &val)
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.
int GetC(Vector3< double > &C)
computes translation vector origin world coo -> origin camera coo (center), uses decomposition, which is cached
Matrix3x3< T > Transpose() const
returns transposed matrix tested 12.06.2002
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)
void SetFy(const KMATRIX_TYPE &val)
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
T GetDeterminant() const
returns the Determinant |A| of this
int GetEpipoles(HomgPoint2D &Epipole1, HomgPoint2D &Epipole2) const
Computes the epipoles from this F Matrix.
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...
static void ComputeRotation(BIAS::FMatrix &F, BIAS::HomgPoint2D &Epipole1, BIAS::HomgPoint2D &Epipole2, BIAS::RMatrix &R)
describes a projective 3D -> 2D mapping in homogenous coordinates
void SetAsCrossProductMatrix(const Vector3< T > &vec)
Sets matrix from vector as cross product matrix of this vector.
void SetHx(const KMATRIX_TYPE &val)
KMatrix Invert() const
returns analyticaly inverted matrix
PMatrixEstimation()
Standard constructor does nothing.
Vector3< T > & Normalize()
normalize this vector to length 1
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)
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' | -K R' C ] with R' = transpose(R) ...
void SetIdentity()
set the elements of this matrix to the identity matrix (possibly overriding the inherited method) ...
int GetK(KMatrix &K)
calibration matrix
BIAS::HomgPoint2D globalEpipole2_