当前位置:   article > 正文

SVD分解计算空间相似变换旋转和平移矩阵_eigen 利用svd求解旋转矩阵

eigen 利用svd求解旋转矩阵
  1. //opencv 实现
  2. void caculateRT(const std::vector<cv::Point3d>& pts1, const std::vector<cv::Point3d>& pts2, cv::Mat& R, cv::Mat& T)
  3. {
  4. //1、求中心点
  5. cv::Point3d p1, p2;
  6. int N = pts1.size();
  7. for (int i = 0; i < N; i++)
  8. {
  9. p1 += pts1[i];
  10. p2 += pts2[i];
  11. }
  12. p1 = cv::Point3d(cv::Vec3d(p1) / N);
  13. p2 = cv::Point3d(cv::Vec3d(p2) / N);
  14. //2、去中心坐标
  15. cv::Mat srcMat(3, N, CV_64FC1);
  16. cv::Mat dstMat(3, N, CV_64FC1);
  17. for (int i = 0; i < N; ++i)
  18. {
  19. cv::Point3d q1 = pts1[i] - p1;
  20. srcMat.at<double>(0, i) = q1.x;
  21. srcMat.at<double>(1, i) = q1.y;
  22. srcMat.at<double>(2, i) = q1.z;
  23. cv::Point3d q2 = pts2[i] - p2;
  24. dstMat.at<double>(0, i) = q2.x;
  25. dstMat.at<double>(1, i) = q2.y;
  26. dstMat.at<double>(2, i) = q2.z;
  27. }
  28. cv::Mat matS = srcMat * dstMat.t();
  29. cv::Mat matU, matW, matVT;
  30. cv::SVDecomp(matS, matW, matU, matVT);
  31. cv::Mat matTemp = matU * matVT;
  32. double det = cv::determinant(matTemp);
  33. double datM[] = { 1, 0, 0, 0, 1, 0, 0, 0, det };
  34. cv::Mat matM(3, 3, CV_64FC1, datM);
  35. R = matVT.t() * matM * matU.t();
  36. cv::Mat matP1 = (cv::Mat_<double>(3, 1) << p1.x, p1.y, p1.z);
  37. cv::Mat matP2 = (cv::Mat_<double>(3, 1) << p2.x, p2.y, p2.z);
  38. T = matP2 - R * matP1;
  39. }
  1. // Eigen库实现
  2. void caculateRT(const std::vector<cv::Point3d>& pts1, const std::vector<cv::Point3d>& pts2, cv::Mat& R, cv::Mat& T)
  3. {
  4. //【1】 求中心点
  5. cv::Point3d p1, p2;
  6. int N = pts1.size();
  7. for (int i = 0; i < N; i++)
  8. {
  9. p1 += pts1[i];
  10. p2 += pts2[i];
  11. }
  12. p1 = cv::Point3d(cv::Vec3d(p1) / N);
  13. p2 = cv::Point3d(cv::Vec3d(p2) / N);
  14. // 【2】得到去中心坐标
  15. std::vector<cv::Point3d> q1(N), q2(N);
  16. for (int i = 0; i < N; i++)
  17. {
  18. q1[i] = pts1[i] - p1;
  19. q2[i] = pts2[i] - p2;
  20. }
  21. //【3】计算需要进行奇异值分解的 W = sum(qi * qi’转置) compute q1*q2^T
  22. Eigen::Matrix3d W = Eigen::Matrix3d::Zero();
  23. for (int i = 0; i < N; i++)
  24. W += Eigen::Vector3d(q1[i].x, q1[i].y, q1[i].z) * Eigen::Vector3d(q2[i].x, q2[i].y, q2[i].z).transpose();
  25. // 【4】对 W 进行SVD 奇异值分解
  26. Eigen::JacobiSVD<Eigen::Matrix3d> svd(W, Eigen::ComputeFullU | Eigen::ComputeFullV);
  27. Eigen::Matrix3d U = svd.matrixU();
  28. Eigen::Matrix3d V = svd.matrixV();
  29. // 【5】计算旋转 和平移矩阵 R 和 t, R= V *M* UT
  30. double det = (U*V.transpose()).determinant();
  31. Eigen::Matrix3d M;
  32. M << 1, 0, 0, 0, 1, 0, 0, 0, det;
  33. Eigen::Matrix3d R_ = V * M* (U.transpose());
  34. // t = p' - R * p
  35. Eigen::Vector3d t_ = Eigen::Vector3d(p2.x, p2.y, p2.z) - R_ * Eigen::Vector3d(p1.x, p1.y, p1.z);
  36. // 【6】格式转换 convert to cv::Mat
  37. R = (cv::Mat_<double>(3, 3) <<
  38. R_(0, 0), R_(0, 1), R_(0, 2),
  39. R_(1, 0), R_(1, 1), R_(1, 2),
  40. R_(2, 0), R_(2, 1), R_(2, 2)
  41. );
  42. T = (cv::Mat_<double>(3, 1) << t_(0, 0), t_(1, 0), t_(2, 0));
  43. }

参考:

https://blog.csdn.net/kewei9/article/details/74157236?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-3

https://blog.csdn.net/xiaoxiaowenqiang/article/details/78996104?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-3

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/78170
推荐阅读
相关标签
  

闽ICP备14008679号