11 #include <Eigen/Geometry>
32 template <
int kDim,
bool kEstimateScale = true>
35 typedef Eigen::Matrix<double, kDim, 1>
X_t;
36 typedef Eigen::Matrix<double, kDim, 1>
Y_t;
37 typedef Eigen::Matrix<double, kDim, kDim + 1>
M_t;
50 static std::vector<M_t>
Estimate(
const std::vector<X_t>& src,
51 const std::vector<Y_t>& dst);
64 static void Residuals(
const std::vector<X_t>& src,
65 const std::vector<Y_t>& dst,
67 std::vector<double>* residuals);
74 template <
int kDim,
bool kEstimateScale>
75 std::vector<typename SimilarityTransformEstimator<kDim, kEstimateScale>::M_t>
77 const std::vector<X_t>& src,
const std::vector<Y_t>& dst) {
78 CHECK_EQ(src.size(), dst.size());
80 Eigen::Matrix<double, kDim, Eigen::Dynamic> src_mat(kDim, src.size());
81 Eigen::Matrix<double, kDim, Eigen::Dynamic> dst_mat(kDim, dst.size());
82 for (
size_t i = 0; i < src.size(); ++i) {
83 src_mat.col(i) = src[i];
84 dst_mat.col(i) = dst[i];
87 const auto model = Eigen::umeyama(src_mat, dst_mat, kEstimateScale)
88 .topLeftCorner(kDim, kDim + 1);
90 if (model.array().isNaN().any()) {
91 return std::vector<M_t>{};
97 template <
int kDim,
bool kEstimateScale>
99 const std::vector<X_t>& src,
100 const std::vector<Y_t>& dst,
102 std::vector<double>* residuals) {
103 CHECK_EQ(src.size(), dst.size());
105 residuals->resize(src.size());
107 for (
size_t i = 0; i < src.size(); ++i) {
108 const Y_t dst_transformed = matrix * src[i].homogeneous();
109 (*residuals)[i] = (dst[i] - dst_transformed).squaredNorm();