这个模块包括:
- 在多目视觉几何中,关于双目和多目几何约束的求解方案
- 一般的框架“kernel”,可以包含求解方案,进行鲁棒估计
2-view solvers
提供以下几何约束估计的solver:
- 仿射,
- 单应,
- 基本矩阵,
- 7 点算法 ,
- 8 点算法 (Direct Linear Transform) .
- 本质矩阵,
- 8 点算法 (Direct Linear Transform),
- 5 点算法 + 已知内参.
//affine
Mat x1(2, 4);
x1 << 0, 1, 2, 5,
0, 1, 2, 3;
double angle = 45.0;
Mat3 rot;
rot << cos(angle), sin(angle), -2,
-sin(angle), cos(angle), 5,
0, 0, 1;
Mat x2 = x1;
// Transform point from ground truth matrix
for (int i = 0; i < x2.cols(); ++i) {
x2.block<2,1>(0,i) = rot.block<2,2>(0,0) * x1.col(i);// rot
x2.block<2,1>(0,i) += rot.block<2,1>(0,2); // translation
}
Mat3 affine_mat;
Affine2DFromCorrespondencesLinear(x1, x2, &affine_mat);
//
N-View geometry estimation
- 三角重构
- 2 to n view (Direct Linear Transform),
- 2 to n view (Iterated least square).
- Rotation averaging(全局求解旋转)
- L2 (sparse) ,
- L1 (sparse) .
- Translation averaging
- L2 Chordal ,
- SoftL1 ‘approximation of the LInf method of .
//triangulation
const NViewDataSet d = NRealisticCamerasRing(2, 12); //2个相机,12个3D点
for (int i = 0; i < d._X.cols(); ++i) {
const Vec3 X_gt = d._X.col(i);
Vec3 X_estimated;
const Vec2 x1 = d._x[0].col(i);
const Vec2 x2 = d._x[1].col(i);
TriangulateDLT(d.P(0), x1.homogeneous(), d.P(1), x2.homogeneous(), &X_estimated);
//多目三角重构
const int nviews = 5;
const int npoints = 6;
const NViewDataSet d = NRealisticCamerasRing(nviews, npoints);
// Collect P matrices together.
std::vector<Mat34> Ps(nviews);
for (int j = 0; j < nviews; ++j) {
Ps[j] = d.P(j);
}
for (int i = 0; i < npoints; ++i) {
// Collect the image of point i in each frame.
Mat3X xs(3, nviews);
for (int j = 0; j < nviews; ++j) {
xs.col(j) = d._x[j].col(i).homogeneous();
}
Vec4 X;
TriangulateNView(xs, Ps, &X);
//TriangulateNViewAlgebraic(xs, Ps, &X)
// Check reprojection error. Should be nearly zero.
for (int j = 0; j < nviews; ++j) {
const Vec3 x_reprojected = Ps[j]*X;
const double error = (x_reprojected.hnormalized() - xs.col(j).hnormalized()).norm();
EXPECT_NEAR(error, 0.0, 1e-9);
}
//rotation averaging
const Mat3 rotx = RotationAroundX(0.3);
const Mat3 Approximative_rotx = rotation_averaging::l2::ClosestSVDRotationMatrix(rotx);
const Mat3 R01 = RotationAroundZ(2.*M_PI/3.0); //120 degree
const Mat3 R12 = RotationAroundZ(2.*M_PI/3.0); //120 degree
const Mat3 R20 = RotationAroundZ(2.*M_PI/3.0); //120 degree
std::vector<RelativeRotation > vec_relativeRotEstimate;
vec_relativeRotEstimate.push_back( RelativeRotation(0,1, R01));
vec_relativeRotEstimate.push_back( RelativeRotation(1,2, R12));
vec_relativeRotEstimate.push_back( RelativeRotation(2,0, R20));
//- Solve the global rotation estimation problem :
std::vector<Mat3> vec_globalR;
L2RotationAveraging(3, vec_relativeRotEstimate, vec_globalR);
//l1: GlobalRotationsRobust(vec_relativeRotEstimate, vec_globalR, nMainViewID, 0.0f, &vec_inliers)
//可以判断出外点。需要注意R可能会相差一个‘-’号。这不影响最小化一致性
Mat3 R;
Vec3 t, t0 = Vec3::Zero(), t1 = Vec3::Zero();
RelativeCameraMotion(vec_globalR[0], t0, vec_globalR[1], t1, &R, &t); //R==R01
//translation averaging
已知3D点,求P
- 6pt Direct Linear Transform [HZ],
- 3pt with intrinsic EPnP [Ke],
- 3pt with intrinsic P3P [Kneip].
Kernel concept
利用了RANSAC(随机采样一致)的思想。kernel包括:
- 数据
- solver
- 度量函数
c++技巧
//输出vector
std::copy(vec_inliers.begin(), vec_inliers.end(), std::ostream_iterator<bool>(std::cout, " "));
std::cout << std::endl;
//交换vector
vec_relativeRotEstimate.swap(vec_relativeRotEstimateTemp);