36 #include <Eigen/Geometry>
47 std::vector<EssentialMatrixFivePointEstimator::M_t>
49 const std::vector<Y_t>& points2) {
50 CHECK_EQ(points1.size(), points2.size());
54 Eigen::Matrix<double, Eigen::Dynamic, 9> Q(points1.size(), 9);
55 for (
size_t i = 0; i < points1.size(); ++i) {
56 const double x1_0 = points1[i](0);
57 const double x1_1 = points1[i](1);
58 const double x2_0 = points2[i](0);
59 const double x2_1 = points2[i](1);
60 Q(i, 0) = x1_0 * x2_0;
61 Q(i, 1) = x1_1 * x2_0;
63 Q(i, 3) = x1_0 * x2_1;
64 Q(i, 4) = x1_1 * x2_1;
72 const Eigen::JacobiSVD<Eigen::Matrix<double, Eigen::Dynamic, 9>> svd(
73 Q, Eigen::ComputeFullV);
74 const Eigen::Matrix<double, 9, 4> E = svd.matrixV().block<9, 4>(0, 5);
78 Eigen::Matrix<double, 10, 20> A;
80 Eigen::Matrix<double, 10, 10> AA =
81 A.block<10, 10>(0, 0).partialPivLu().solve(A.block<10, 10>(0, 10));
86 Eigen::Matrix<double, 13, 3> B;
87 for (
size_t i = 0; i < 3; ++i) {
91 B.block<3, 1>(1, i) = AA.block<1, 3>(i * 2 + 4, 0);
92 B.block<3, 1>(5, i) = AA.block<1, 3>(i * 2 + 4, 3);
93 B.block<4, 1>(9, i) = AA.block<1, 4>(i * 2 + 4, 6);
94 B.block<3, 1>(0, i) -= AA.block<1, 3>(i * 2 + 5, 0);
95 B.block<3, 1>(4, i) -= AA.block<1, 3>(i * 2 + 5, 3);
96 B.block<4, 1>(8, i) -= AA.block<1, 4>(i * 2 + 5, 6);
100 Eigen::Matrix<double, 11, 1>
coeffs;
103 Eigen::VectorXd roots_real;
104 Eigen::VectorXd roots_imag;
109 std::vector<M_t> models;
110 models.reserve(roots_real.size());
113 const double kMaxRootImag = 1
e-10;
114 if (std::abs(roots_imag(i)) > kMaxRootImag) {
118 const double z1 = roots_real(i);
119 const double z2 = z1 * z1;
120 const double z3 = z2 * z1;
121 const double z4 = z3 * z1;
124 for (
size_t j = 0; j < 3; ++j) {
125 Bz(j, 0) = B(0, j) * z3 + B(1, j) * z2 + B(2, j) * z1 + B(3, j);
126 Bz(j, 1) = B(4, j) * z3 + B(5, j) * z2 + B(6, j) * z1 + B(7, j);
127 Bz(j, 2) = B(8, j) * z4 + B(9, j) * z3 + B(10, j) * z2 + B(11, j) * z1 +
131 const Eigen::JacobiSVD<Eigen::Matrix3d> svd(Bz, Eigen::ComputeFullV);
132 const Eigen::Vector3d
X = svd.matrixV().block<3, 1>(0, 2);
134 const double kMaxX3 = 1
e-10;
135 if (std::abs(
X(2)) < kMaxX3) {
139 Eigen::MatrixXd essential_vec = E.col(0) * (
X(0) /
X(2)) +
140 E.col(1) * (
X(1) /
X(2)) + E.col(2) * z1 +
142 essential_vec /= essential_vec.norm();
144 const Eigen::Matrix3d essential_matrix =
145 Eigen::Map<Eigen::Matrix<double, 3, 3, Eigen::RowMajor>>(
146 essential_vec.data());
147 models.push_back(essential_matrix);
154 const std::vector<X_t>& points1,
const std::vector<Y_t>& points2,
155 const M_t& E, std::vector<double>* residuals) {
159 std::vector<EssentialMatrixEightPointEstimator::M_t>
161 const std::vector<Y_t>& points2) {
162 CHECK_EQ(points1.size(), points2.size());
165 std::vector<X_t> normed_points1;
166 std::vector<Y_t> normed_points2;
167 Eigen::Matrix3d points1_norm_matrix;
168 Eigen::Matrix3d points2_norm_matrix;
173 Eigen::Matrix<double, Eigen::Dynamic, 9> cmatrix(points1.size(), 9);
174 for (
size_t i = 0; i < points1.size(); ++i) {
175 cmatrix.block<1, 3>(i, 0) = normed_points1[i].homogeneous();
176 cmatrix.block<1, 3>(i, 0) *= normed_points2[i].
x();
177 cmatrix.block<1, 3>(i, 3) = normed_points1[i].homogeneous();
178 cmatrix.block<1, 3>(i, 3) *= normed_points2[i].
y();
179 cmatrix.block<1, 3>(i, 6) = normed_points1[i].homogeneous();
183 Eigen::JacobiSVD<Eigen::Matrix<double, Eigen::Dynamic, 9>> cmatrix_svd(
184 cmatrix, Eigen::ComputeFullV);
185 const Eigen::VectorXd ematrix_nullspace = cmatrix_svd.matrixV().col(8);
186 const Eigen::Map<const Eigen::Matrix3d> ematrix_t(ematrix_nullspace.data());
189 const Eigen::Matrix3d E_raw = points2_norm_matrix.transpose() *
190 ematrix_t.transpose() * points1_norm_matrix;
194 Eigen::JacobiSVD<Eigen::Matrix3d> E_raw_svd(
195 E_raw, Eigen::ComputeFullU | Eigen::ComputeFullV);
196 Eigen::Vector3d singular_values = E_raw_svd.singularValues();
197 singular_values(0) = (singular_values(0) + singular_values(1)) / 2.0;
198 singular_values(1) = singular_values(0);
199 singular_values(2) = 0.0;
200 const Eigen::Matrix3d E = E_raw_svd.matrixU() * singular_values.asDiagonal() *
201 E_raw_svd.matrixV().transpose();
203 const std::vector<M_t> models = {E};
208 const std::vector<X_t>& points1,
const std::vector<Y_t>& points2,
209 const M_t& E, std::vector<double>* residuals) {
static void Residuals(const std::vector< X_t > &points1, const std::vector< Y_t > &points2, const M_t &E, std::vector< double > *residuals)
static std::vector< M_t > Estimate(const std::vector< X_t > &points1, const std::vector< Y_t > &points2)
static void Residuals(const std::vector< X_t > &points1, const std::vector< Y_t > &points2, const M_t &E, std::vector< double > *residuals)
static std::vector< M_t > Estimate(const std::vector< X_t > &points1, const std::vector< Y_t > &points2)
bool FindPolynomialRootsCompanionMatrix(const Eigen::VectorXd &coeffs_all, Eigen::VectorXd *real, Eigen::VectorXd *imag)
void CenterAndNormalizeImagePoints(const std::vector< Eigen::Vector2d > &points, std::vector< Eigen::Vector2d > *normed_points, Eigen::Matrix3d *matrix)
void ComputeSquaredSampsonError(const std::vector< Eigen::Vector2d > &points1, const std::vector< Eigen::Vector2d > &points2, const Eigen::Matrix3d &E, std::vector< double > *residuals)
Eigen::MatrixXd::Index Index