36 #include <Eigen/Dense>
45 double ComputeOppositeOfMinor(
const Eigen::Matrix3d& matrix,
const size_t row,
47 const size_t col1 = col == 0 ? 1 : 0;
48 const size_t col2 = col == 2 ? 1 : 2;
49 const size_t row1 = row == 0 ? 1 : 0;
50 const size_t row2 = row == 2 ? 1 : 2;
51 return (matrix(row1, col2) * matrix(row2, col1) -
52 matrix(row1, col1) * matrix(row2, col2));
55 Eigen::Matrix3d ComputeHomographyRotation(
const Eigen::Matrix3d& H_normalized,
56 const Eigen::Vector3d& tstar,
57 const Eigen::Vector3d& n,
60 (Eigen::Matrix3d::Identity() - (2.0 / v) * tstar * n.transpose());
66 const Eigen::Matrix3d& K1,
67 const Eigen::Matrix3d& K2,
68 std::vector<Eigen::Matrix3d>* R,
69 std::vector<Eigen::Vector3d>* t,
70 std::vector<Eigen::Vector3d>* n) {
72 Eigen::Matrix3d H_normalized = K2.inverse() * H * K1;
75 Eigen::JacobiSVD<Eigen::Matrix3d> hmatrix_norm_svd(H_normalized);
76 H_normalized.array() /= hmatrix_norm_svd.singularValues()[1];
89 if (H_normalized.determinant() < 0) {
90 H_normalized.array() *= -1.0;
93 const Eigen::Matrix3d S =
94 H_normalized.transpose() * H_normalized - Eigen::Matrix3d::Identity();
97 const double kMinInfinityNorm = 1
e-3;
98 if (S.lpNorm<Eigen::Infinity>() < kMinInfinityNorm) {
100 *t = {Eigen::Vector3d::Zero()};
101 *n = {Eigen::Vector3d::Zero()};
105 const double M00 = ComputeOppositeOfMinor(S, 0, 0);
106 const double M11 = ComputeOppositeOfMinor(S, 1, 1);
107 const double M22 = ComputeOppositeOfMinor(S, 2, 2);
109 const double rtM00 = std::sqrt(M00);
110 const double rtM11 = std::sqrt(M11);
111 const double rtM22 = std::sqrt(M22);
113 const double M01 = ComputeOppositeOfMinor(S, 0, 1);
114 const double M12 = ComputeOppositeOfMinor(S, 1, 2);
115 const double M02 = ComputeOppositeOfMinor(S, 0, 2);
121 const double nS00 = std::abs(S(0, 0));
122 const double nS11 = std::abs(S(1, 1));
123 const double nS22 = std::abs(S(2, 2));
125 const std::array<double, 3> nS{{nS00, nS11, nS22}};
127 std::distance(nS.begin(), std::max_element(nS.begin(), nS.end()));
134 np1[1] = S(0, 1) + rtM22;
135 np2[1] = S(0, 1) - rtM22;
136 np1[2] = S(0, 2) + e12 * rtM11;
137 np2[2] = S(0, 2) - e12 * rtM11;
138 }
else if (idx == 1) {
139 np1[0] = S(0, 1) + rtM22;
140 np2[0] = S(0, 1) - rtM22;
143 np1[2] = S(1, 2) - e02 * rtM00;
144 np2[2] = S(1, 2) + e02 * rtM00;
145 }
else if (idx == 2) {
146 np1[0] = S(0, 2) + e01 * rtM11;
147 np2[0] = S(0, 2) - e01 * rtM11;
148 np1[1] = S(1, 2) + rtM00;
149 np2[1] = S(1, 2) - rtM00;
154 const double traceS = S.trace();
155 const double v = 2.0 * std::sqrt(1.0 + traceS - M00 - M11 - M22);
158 const double r_2 = 2 + traceS + v;
159 const double nt_2 = 2 + traceS - v;
161 const double r = std::sqrt(r_2);
162 const double n_t = std::sqrt(nt_2);
164 const Eigen::Vector3d n1 = np1.normalized();
165 const Eigen::Vector3d n2 = np2.normalized();
167 const double half_nt = 0.5 * n_t;
168 const double esii_t_r = ESii * r;
170 const Eigen::Vector3d t1_star = half_nt * (esii_t_r * n2 - n_t * n1);
171 const Eigen::Vector3d t2_star = half_nt * (esii_t_r * n1 - n_t * n2);
173 const Eigen::Matrix3d R1 =
174 ComputeHomographyRotation(H_normalized, t1_star, n1, v);
175 const Eigen::Vector3d t1 = R1 * t1_star;
177 const Eigen::Matrix3d R2 =
178 ComputeHomographyRotation(H_normalized, t2_star, n2, v);
179 const Eigen::Vector3d t2 = R2 * t2_star;
181 *R = {R1, R1, R2, R2};
182 *t = {t1, -t1, t2, -t2};
183 *n = {-n1, n1, -n2, n2};
187 const Eigen::Matrix3d& K1,
188 const Eigen::Matrix3d& K2,
189 const std::vector<Eigen::Vector2d>& points1,
190 const std::vector<Eigen::Vector2d>& points2,
191 Eigen::Matrix3d* R, Eigen::Vector3d* t,
193 std::vector<Eigen::Vector3d>* points3D) {
194 CHECK_EQ(points1.size(), points2.size());
196 std::vector<Eigen::Matrix3d> R_cmbs;
197 std::vector<Eigen::Vector3d> t_cmbs;
198 std::vector<Eigen::Vector3d> n_cmbs;
202 for (
size_t i = 0; i < R_cmbs.size(); ++i) {
203 std::vector<Eigen::Vector3d> points3D_cmb;
204 CheckCheirality(R_cmbs[i], t_cmbs[i], points1, points2, &points3D_cmb);
205 if (points3D_cmb.size() >= points3D->size()) {
209 *points3D = points3D_cmb;
215 const Eigen::Matrix3d& K2,
216 const Eigen::Matrix3d& R,
217 const Eigen::Vector3d& t,
218 const Eigen::Vector3d& n,
221 return K2 * (R - t * n.normalized().transpose() / d) * K1.inverse();
static double distance(T *pot1, T *pot2)
void PoseFromHomographyMatrix(const Eigen::Matrix3d &H, const Eigen::Matrix3d &K1, const Eigen::Matrix3d &K2, const std::vector< Eigen::Vector2d > &points1, const std::vector< Eigen::Vector2d > &points2, Eigen::Matrix3d *R, Eigen::Vector3d *t, Eigen::Vector3d *n, std::vector< Eigen::Vector3d > *points3D)
int SignOfNumber(const T val)
Eigen::Matrix3d HomographyMatrixFromPose(const Eigen::Matrix3d &K1, const Eigen::Matrix3d &K2, const Eigen::Matrix3d &R, const Eigen::Vector3d &t, const Eigen::Vector3d &n, const double d)
void DecomposeHomographyMatrix(const Eigen::Matrix3d &H, const Eigen::Matrix3d &K1, const Eigen::Matrix3d &K2, std::vector< Eigen::Matrix3d > *R, std::vector< Eigen::Vector3d > *t, std::vector< Eigen::Vector3d > *n)
bool CheckCheirality(const Eigen::Matrix3d &R, const Eigen::Vector3d &t, const std::vector< Eigen::Vector2d > &points1, const std::vector< Eigen::Vector2d > &points2, std::vector< Eigen::Vector3d > *points3D)