File indexing completed on 2025-11-04 10:10:25
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 #ifndef EIGEN_UMEYAMA_H
0011 #define EIGEN_UMEYAMA_H
0012 
0013 
0014 
0015 
0016 
0017 
0018 
0019 namespace Eigen { 
0020 
0021 #ifndef EIGEN_PARSED_BY_DOXYGEN
0022 
0023 
0024 
0025 
0026 namespace internal {
0027 
0028 
0029 
0030 
0031 template<typename MatrixType, typename OtherMatrixType>
0032 struct umeyama_transform_matrix_type
0033 {
0034   enum {
0035     MinRowsAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(MatrixType::RowsAtCompileTime, OtherMatrixType::RowsAtCompileTime),
0036 
0037     
0038     
0039     HomogeneousDimension = int(MinRowsAtCompileTime) == Dynamic ? Dynamic : int(MinRowsAtCompileTime)+1
0040   };
0041 
0042   typedef Matrix<typename traits<MatrixType>::Scalar,
0043     HomogeneousDimension,
0044     HomogeneousDimension,
0045     AutoAlign | (traits<MatrixType>::Flags & RowMajorBit ? RowMajor : ColMajor),
0046     HomogeneousDimension,
0047     HomogeneousDimension
0048   > type;
0049 };
0050 
0051 }
0052 
0053 #endif
0054 
0055 
0056 
0057 
0058 
0059 
0060 
0061 
0062 
0063 
0064 
0065 
0066 
0067 
0068 
0069 
0070 
0071 
0072 
0073 
0074 
0075 
0076 
0077 
0078 
0079 
0080 
0081 
0082 
0083 
0084 
0085 
0086 
0087 
0088 
0089 
0090 
0091 
0092 
0093 template <typename Derived, typename OtherDerived>
0094 typename internal::umeyama_transform_matrix_type<Derived, OtherDerived>::type
0095 umeyama(const MatrixBase<Derived>& src, const MatrixBase<OtherDerived>& dst, bool with_scaling = true)
0096 {
0097   typedef typename internal::umeyama_transform_matrix_type<Derived, OtherDerived>::type TransformationMatrixType;
0098   typedef typename internal::traits<TransformationMatrixType>::Scalar Scalar;
0099   typedef typename NumTraits<Scalar>::Real RealScalar;
0100 
0101   EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL)
0102   EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename internal::traits<OtherDerived>::Scalar>::value),
0103     YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
0104 
0105   enum { Dimension = EIGEN_SIZE_MIN_PREFER_DYNAMIC(Derived::RowsAtCompileTime, OtherDerived::RowsAtCompileTime) };
0106 
0107   typedef Matrix<Scalar, Dimension, 1> VectorType;
0108   typedef Matrix<Scalar, Dimension, Dimension> MatrixType;
0109   typedef typename internal::plain_matrix_type_row_major<Derived>::type RowMajorMatrixType;
0110 
0111   const Index m = src.rows(); 
0112   const Index n = src.cols(); 
0113 
0114   
0115   const RealScalar one_over_n = RealScalar(1) / static_cast<RealScalar>(n);
0116 
0117   
0118   const VectorType src_mean = src.rowwise().sum() * one_over_n;
0119   const VectorType dst_mean = dst.rowwise().sum() * one_over_n;
0120 
0121   
0122   const RowMajorMatrixType src_demean = src.colwise() - src_mean;
0123   const RowMajorMatrixType dst_demean = dst.colwise() - dst_mean;
0124 
0125   
0126   const Scalar src_var = src_demean.rowwise().squaredNorm().sum() * one_over_n;
0127 
0128   
0129   const MatrixType sigma = one_over_n * dst_demean * src_demean.transpose();
0130 
0131   JacobiSVD<MatrixType> svd(sigma, ComputeFullU | ComputeFullV);
0132 
0133   
0134   TransformationMatrixType Rt = TransformationMatrixType::Identity(m+1,m+1);
0135 
0136   
0137   VectorType S = VectorType::Ones(m);
0138 
0139   if  ( svd.matrixU().determinant() * svd.matrixV().determinant() < 0 )
0140     S(m-1) = -1;
0141 
0142   
0143   Rt.block(0,0,m,m).noalias() = svd.matrixU() * S.asDiagonal() * svd.matrixV().transpose();
0144 
0145   if (with_scaling)
0146   {
0147     
0148     const Scalar c = Scalar(1)/src_var * svd.singularValues().dot(S);
0149 
0150     
0151     Rt.col(m).head(m) = dst_mean;
0152     Rt.col(m).head(m).noalias() -= c*Rt.topLeftCorner(m,m)*src_mean;
0153     Rt.block(0,0,m,m) *= c;
0154   }
0155   else
0156   {
0157     Rt.col(m).head(m) = dst_mean;
0158     Rt.col(m).head(m).noalias() -= Rt.topLeftCorner(m,m)*src_mean;
0159   }
0160 
0161   return Rt;
0162 }
0163 
0164 } 
0165 
0166 #endif