| 191 | } |
| 192 | |
| 193 | void sim3_solver::compute_Sim3(const Mat33_t &pts_1, const Mat33_t &pts_2, |
| 194 | Mat33_t &rot_12, Vec3_t &trans_12, float &scale_12, |
| 195 | Mat33_t &rot_21, Vec3_t &trans_21, float &scale_21) |
| 196 | { |
| 197 | // Based on "Closed-form solution of absolute orientation using unit quaternions" |
| 198 | // http://people.csail.mit.edu/bkph/papers/Absolute_Orientation.pdf |
| 199 | |
| 200 | // Find the centroid of each point set |
| 201 | const Vec3_t centroid_1 = pts_1.rowwise().mean(); |
| 202 | const Vec3_t centroid_2 = pts_2.rowwise().mean(); |
| 203 | |
| 204 | // Move the center of the distribution to centroid |
| 205 | Mat33_t ave_pts_1 = pts_1; |
| 206 | ave_pts_1.colwise() -= centroid_1; |
| 207 | Mat33_t ave_pts_2 = pts_2; |
| 208 | ave_pts_2.colwise() -= centroid_2; |
| 209 | |
| 210 | // 4.A Matrix of Sums of Products |
| 211 | |
| 212 | // Find the matrix M |
| 213 | const Mat33_t M = ave_pts_1 * ave_pts_2.transpose(); |
| 214 | |
| 215 | // Find the matrix N |
| 216 | const double &Sxx = M(0, 0); |
| 217 | const double &Syx = M(1, 0); |
| 218 | const double &Szx = M(2, 0); |
| 219 | const double &Sxy = M(0, 1); |
| 220 | const double &Syy = M(1, 1); |
| 221 | const double &Szy = M(2, 1); |
| 222 | const double &Sxz = M(0, 2); |
| 223 | const double &Syz = M(1, 2); |
| 224 | const double &Szz = M(2, 2); |
| 225 | Eigen::Matrix4d N; |
| 226 | N << (Sxx + Syy + Szz), (Syz - Szy), (Szx - Sxz), (Sxy - Syx), |
| 227 | (Syz - Szy), (Sxx - Syy - Szz), (Sxy + Syx), (Szx + Sxz), |
| 228 | (Szx - Sxz), (Sxy + Syx), (-Sxx + Syy - Szz), (Syz + Szy), |
| 229 | (Sxy - Syx), (Szx + Sxz), (Syz + Szy), (-Sxx - Syy + Szz); |
| 230 | |
| 231 | // 4.B Eigenvector Maximizes Matrix Product |
| 232 | |
| 233 | // Eigenvalue decomposition of N |
| 234 | Eigen::EigenSolver<Mat44_t> eigensolver(N); |
| 235 | |
| 236 | // Find the maximum eigenvalue |
| 237 | const auto &eigenvalues = eigensolver.eigenvalues(); |
| 238 | int max_idx = -1; |
| 239 | double max_eigenvalue = -INFINITY; |
| 240 | for (int idx = 0; idx < 4; ++idx) |
| 241 | { |
| 242 | if (max_eigenvalue <= eigenvalues(idx, 0).real()) |
| 243 | { |
| 244 | max_eigenvalue = eigenvalues(idx, 0).real(); |
| 245 | max_idx = idx; |
| 246 | } |
| 247 | } |
| 248 | const auto max_eigenvector = eigensolver.eigenvectors().col(max_idx); |
| 249 | |
| 250 | // Since it is a complex number, only the real number is extracted. |
nothing calls this directly
no test coverage detected