41 const std::vector<X_t>& points1,
const std::vector<Y_t>& points2) {
42 CHECK_EQ(points1.size(), points2.size());
43 CHECK_GE(points1.size(), 3);
47 Eigen::MatrixXd C(2 * points1.size(), 6);
49 Eigen::VectorXd b(2 * points1.size(), 1);
51 for (
size_t i = 0; i < points1.size(); ++i) {
52 const Eigen::Vector2d& x1 = points1[i];
53 const Eigen::Vector2d& x2 = points2[i];
60 C(2 * i + 1, 3) = x1(0);
61 C(2 * i + 1, 4) = x1(1);
62 C(2 * i + 1, 5) = 1.0f;
66 const Eigen::VectorXd nullspace =
67 C.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
69 Eigen::Map<const Eigen::Matrix<double, 3, 2>> A_t(nullspace.data());
71 const std::vector<M_t> models = {A_t.transpose()};
76 const std::vector<Y_t>& points2,
78 std::vector<double>* residuals) {
79 CHECK_EQ(points1.size(), points2.size());
81 residuals->resize(points1.size());
86 const double A_00 = A(0, 0);
87 const double A_01 = A(0, 1);
88 const double A_02 = A(0, 2);
89 const double A_10 = A(1, 0);
90 const double A_11 = A(1, 1);
91 const double A_12 = A(1, 2);
93 for (
size_t i = 0; i < points1.size(); ++i) {
94 const double s_0 = points1[i](0);
95 const double s_1 = points1[i](1);
96 const double d_0 = points2[i](0);
97 const double d_1 = points2[i](1);
99 const double pd_0 = A_00 * s_0 + A_01 * s_1 + A_02;
100 const double pd_1 = A_10 * s_0 + A_11 * s_1 + A_12;
102 const double dd_0 = d_0 - pd_0;
103 const double dd_1 = d_1 - pd_1;
105 (*residuals)[i] = dd_0 * dd_0 + dd_1 * dd_1;