#include "Geometry/v3d_metricbundle.h"
#if defined(V3DLIB_ENABLE_SUITESPARSE)
namespace
{
typedef V3D::InlineMatrix<double, 2, 4> Matrix2x4d;
typedef V3D::InlineMatrix<double, 4, 2> Matrix4x2d;
typedef V3D::InlineMatrix<double, 2, 6> Matrix2x6d;
}
namespace V3D
{
void
MetricBundleOptimizerBase::updateParametersA(VectorArray<double> const& deltaAi)
{
Vector3d T, omega;
Matrix3x3d R0, dR;
for (int i = _nNonvaryingA; i < _nParametersA; ++i)
{
T = _cams[i].getTranslation();
T[0] += deltaAi[i][0];
T[1] += deltaAi[i][1];
T[2] += deltaAi[i][2];
_cams[i].setTranslation(T);
R0 = _cams[i].getRotation();
omega[0] = deltaAi[i][3];
omega[1] = deltaAi[i][4];
omega[2] = deltaAi[i][5];
createRotationMatrixRodriguez(omega, dR);
_cams[i].setRotation(dR * R0);
} }
void
MetricBundleOptimizerBase::updateParametersB(VectorArray<double> const& deltaBj)
{
for (int j = _nNonvaryingB; j < _nParametersB; ++j)
{
_Xs[j][0] += deltaBj[j][0];
_Xs[j][1] += deltaBj[j][1];
_Xs[j][2] += deltaBj[j][2];
}
}
void
MetricBundleOptimizerBase::poseDerivatives(int i, int j, Vector3d& XX,
Matrix3x6d& d_dRT, Matrix3x3d& d_dX) const
{
XX = _cams[i].transformPointIntoCameraSpace(_Xs[j]);
Matrix3x3d J;
makeCrossProductMatrix(XX - _cams[i].getTranslation(), J);
scaleMatrixIP(-1.0, J);
makeIdentityMatrix(d_dRT);
copyMatrixSlice(J, 0, 0, 3, 3, d_dRT, 0, 3);
copyMatrix(_cams[i].getRotation(), d_dX);
}
void
StdMetricBundleOptimizer::fillJacobians(Matrix<double>& Ak,
Matrix<double>& Bk,
Matrix<double>& Ck,
int i, int j, int k)
{
Vector3d XX;
Matrix3x6d d_dRT;
Matrix3x3d d_dX;
this->poseDerivatives(i, j, XX, d_dRT, d_dX);
double const f = _cams[i].getFocalLength();
double const ar = _cams[i].getAspectRatio();
Matrix2x3d dp_dX;
double const bx = f / (XX[2] * XX[2]);
double const by = ar * bx;
dp_dX[0][0] = bx * XX[2]; dp_dX[0][1] = 0; dp_dX[0][2] = -bx * XX[0];
dp_dX[1][0] = 0; dp_dX[1][1] = by * XX[2]; dp_dX[1][2] = -by * XX[1];
multiply_A_B(dp_dX, d_dRT, Ak);
multiply_A_B(dp_dX, d_dX, Bk);
}
void
CommonInternalsMetricBundleOptimizer::fillJacobians(Matrix<double>& Ak,
Matrix<double>& Bk,
Matrix<double>& Ck,
int i, int j, int k)
{
double const focalLength = _K[0][0];
Vector3d XX;
Matrix3x6d dXX_dRT;
Matrix3x3d dXX_dX;
this->poseDerivatives(i, j, XX, dXX_dRT, dXX_dX);
Vector2d xu; xu[0] = XX[0] / XX[2];
xu[1] = XX[1] / XX[2];
Vector2d const xd = _distortion(xu);
Matrix2x2d dp_dxd;
dp_dxd[0][0] = focalLength; dp_dxd[0][1] = 0;
dp_dxd[1][0] = 0; dp_dxd[1][1] = _cachedAspectRatio * focalLength;
{
Matrix2x3d dxu_dXX;
dxu_dXX[0][0] = 1.0f / XX[2]; dxu_dXX[0][1] = 0; dxu_dXX[0][2] = -XX[0]/(XX[2]*XX[2]);
dxu_dXX[1][0] = 0; dxu_dXX[1][1] = 1.0f / XX[2]; dxu_dXX[1][2] = -XX[1]/(XX[2]*XX[2]);
Matrix2x2d dxd_dxu = _distortion.derivativeWrtUndistortedPoint(xu);
Matrix2x2d dp_dxu = dp_dxd * dxd_dxu;
Matrix2x3d dp_dXX = dp_dxu * dxu_dXX;
multiply_A_B(dp_dXX, dXX_dRT, Ak);
multiply_A_B(dp_dXX, dXX_dX, Bk);
}
switch (_mode)
{
case FULL_BUNDLE_FOCAL_AND_RADIAL_K1:
{
Ck[0][0] = xd[0];
Ck[1][0] = xd[1];
Matrix2x2d dxd_dk1k2 = _distortion.derivativeWrtRadialParameters(xu);
Matrix2x2d d_dk1k2 = dp_dxd * dxd_dk1k2;
Ck[0][1] = d_dk1k2[0][0];
Ck[1][1] = d_dk1k2[1][0];
break;
}
case FULL_BUNDLE_FOCAL_AND_RADIAL:
{
Ck[0][0] = xd[0];
Ck[1][0] = xd[1];
Matrix2x2d dxd_dk1k2 = _distortion.derivativeWrtRadialParameters(xu);
Matrix2x2d d_dk1k2 = dp_dxd * dxd_dk1k2;
copyMatrixSlice(d_dk1k2, 0, 0, 2, 2, Ck, 0, 1);
break;
}
case FULL_BUNDLE_RADIAL_TANGENTIAL:
{
Matrix2x2d dxd_dp1p2 = _distortion.derivativeWrtTangentialParameters(xu);
Matrix2x2d d_dp1p2 = dp_dxd * dxd_dp1p2;
copyMatrixSlice(d_dp1p2, 0, 0, 2, 2, Ck, 0, 5);
}
case FULL_BUNDLE_RADIAL:
{
Matrix2x2d dxd_dk1k2 = _distortion.derivativeWrtRadialParameters(xu);
Matrix2x2d d_dk1k2 = dp_dxd * dxd_dk1k2;
copyMatrixSlice(d_dk1k2, 0, 0, 2, 2, Ck, 0, 3);
}
case FULL_BUNDLE_FOCAL_LENGTH_PP:
{
Ck[0][1] = 1; Ck[0][2] = 0;
Ck[1][1] = 0; Ck[1][2] = 1;
}
case FULL_BUNDLE_FOCAL_LENGTH:
{
Ck[0][0] = xd[0];
Ck[1][0] = xd[1];
}
case FULL_BUNDLE_METRIC:
{
}
} }
void
CommonInternalsMetricBundleOptimizer::updateParametersC(Vector<double> const& deltaC)
{
switch (_mode)
{
case FULL_BUNDLE_FOCAL_AND_RADIAL_K1:
{
_K[0][0] += deltaC[0];
_K[1][1] = _cachedAspectRatio * _K[0][0];
_distortion.k1 += deltaC[1];
break;
}
case FULL_BUNDLE_FOCAL_AND_RADIAL:
{
_K[0][0] += deltaC[0];
_K[1][1] = _cachedAspectRatio * _K[0][0];
_distortion.k1 += deltaC[1];
_distortion.k2 += deltaC[2];
break;
}
case FULL_BUNDLE_RADIAL_TANGENTIAL:
{
_distortion.p1 += deltaC[5];
_distortion.p2 += deltaC[6];
}
case FULL_BUNDLE_RADIAL:
{
_distortion.k1 += deltaC[3];
_distortion.k2 += deltaC[4];
}
case FULL_BUNDLE_FOCAL_LENGTH_PP:
{
_K[0][2] += deltaC[1];
_K[1][2] += deltaC[2];
}
case FULL_BUNDLE_FOCAL_LENGTH:
{
_K[0][0] += deltaC[0];
_K[1][1] = _cachedAspectRatio * _K[0][0];
}
case FULL_BUNDLE_METRIC:
{
}
} }
void
VaryingInternalsMetricBundleOptimizer::fillJacobians(Matrix<double>& Ak,
Matrix<double>& Bk,
Matrix<double>& Ck,
int i, int j, int k)
{
Vector3d XX;
Matrix3x6d dXX_dRT;
Matrix3x3d dXX_dX;
this->poseDerivatives(i, j, XX, dXX_dRT, dXX_dX);
Vector2d xu; xu[0] = XX[0] / XX[2];
xu[1] = XX[1] / XX[2];
Vector2d const xd = _distortions[i](xu);
double const focalLength = _cams[i].getFocalLength();
double const aspectRatio = _cams[i].getAspectRatio();
Matrix2x2d dp_dxd;
dp_dxd[0][0] = focalLength; dp_dxd[0][1] = 0;
dp_dxd[1][0] = 0; dp_dxd[1][1] = aspectRatio * focalLength;
{
Matrix2x3d dxu_dXX;
dxu_dXX[0][0] = 1.0f / XX[2]; dxu_dXX[0][1] = 0; dxu_dXX[0][2] = -XX[0]/(XX[2]*XX[2]);
dxu_dXX[1][0] = 0; dxu_dXX[1][1] = 1.0f / XX[2]; dxu_dXX[1][2] = -XX[1]/(XX[2]*XX[2]);
Matrix2x2d dxd_dxu = _distortions[i].derivativeWrtUndistortedPoint(xu);
Matrix2x2d dp_dxu = dp_dxd * dxd_dxu;
Matrix2x3d dp_dXX = dp_dxu * dxu_dXX;
Matrix2x6d dp_dRT;
multiply_A_B(dp_dXX, dXX_dRT, dp_dRT);
copyMatrixSlice(dp_dRT, 0, 0, 2, 6, Ak, 0, 0);
multiply_A_B(dp_dXX, dXX_dX, Bk);
}
switch (_mode)
{
case FULL_BUNDLE_RADIAL_TANGENTIAL:
{
Matrix2x2d dxd_dp1p2 = _distortions[i].derivativeWrtTangentialParameters(xu);
Matrix2x2d d_dp1p2 = dp_dxd * dxd_dp1p2;
copyMatrixSlice(d_dp1p2, 0, 0, 2, 2, Ak, 0, 11);
}
case FULL_BUNDLE_RADIAL:
{
Matrix2x2d dxd_dk1k2 = _distortions[i].derivativeWrtRadialParameters(xu);
Matrix2x2d d_dk1k2 = dp_dxd * dxd_dk1k2;
copyMatrixSlice(d_dk1k2, 0, 0, 2, 2, Ak, 0, 9);
}
case FULL_BUNDLE_FOCAL_LENGTH_PP:
{
Ak[0][7] = 1; Ak[0][8] = 0;
Ak[1][7] = 0; Ak[1][8] = 1;
}
case FULL_BUNDLE_FOCAL_LENGTH:
{
Ak[0][6] = xd[0];
Ak[1][6] = xd[1];
}
case FULL_BUNDLE_METRIC:
{
}
} }
void
VaryingInternalsMetricBundleOptimizer::updateParametersA(VectorArray<double> const& deltaAi)
{
Vector3d T, omega;
Matrix3x3d R0, dR, K;
for (int i = _nNonvaryingA; i < _nParametersA; ++i)
{
Vector<double> const& deltaA = deltaAi[i];
T = _cams[i].getTranslation();
T[0] += deltaA[0];
T[1] += deltaA[1];
T[2] += deltaA[2];
_cams[i].setTranslation(T);
R0 = _cams[i].getRotation();
omega[0] = deltaA[3];
omega[1] = deltaA[4];
omega[2] = deltaA[5];
createRotationMatrixRodriguez(omega, dR);
_cams[i].setRotation(dR * R0);
K = _cams[i].getIntrinsic();
switch (_mode)
{
case FULL_BUNDLE_RADIAL_TANGENTIAL:
{
_distortions[i].p1 += deltaA[11];
_distortions[i].p2 += deltaA[12];
}
case FULL_BUNDLE_RADIAL:
{
_distortions[i].k1 += deltaA[9];
_distortions[i].k2 += deltaA[10];
}
case FULL_BUNDLE_FOCAL_LENGTH_PP:
{
K[0][2] += deltaA[7];
K[1][2] += deltaA[8];
}
case FULL_BUNDLE_FOCAL_LENGTH:
{
double const ar = K[1][1] / K[0][0];
K[0][0] += deltaA[6];
K[1][1] = ar * K[0][0];
}
case FULL_BUNDLE_METRIC:
{
}
} _cams[i].setIntrinsic(K);
} }
}
#endif