ORB-SLAM2代码阅读笔记:PnPSolver

2019-08-22  本文已影响0人  liampayne_66d0
    // 遍历每个匹配点中的3D点,然后对每个坐标轴加和
  for(int i = 0; i < number_of_correspondences; i++)
    for(int j = 0; j < 3; j++)
      cws[0][j] += pws[3 * i + j];
  // 再对每个轴上取均值
  for(int j = 0; j < 3; j++)
    cws[0][j] /= number_of_correspondences;
- 其它三个控制点,C1, C2, C3通过PCA分解得到
// 将所有的3D参考点写成矩阵,(number_of_correspondences * 3)的矩阵
  CvMat * PW0 = cvCreateMat(number_of_correspondences, 3, CV_64F);

  double pw0tpw0[3 * 3], dc[3], uct[3 * 3];         // 下面变量的数据区
  CvMat PW0tPW0 = cvMat(3, 3, CV_64F, pw0tpw0);     // 如变量名所示.其实这里使用cv::Mat格式主要是为了进行SVD分解
  CvMat DC      = cvMat(3, 1, CV_64F, dc);          // 分解上面矩阵得到的奇异值组成的矩阵
  CvMat UCt     = cvMat(3, 3, CV_64F, uct);         // 分解上面矩阵得到的左奇异矩阵

  // step 2.1:将存在pws中的参考3D点减去第一个控制点的坐标(相当于把第一个控制点作为原点), 并存入PW0
  for(int i = 0; i < number_of_correspondences; i++)
    for(int j = 0; j < 3; j++)
      PW0->data.db[3 * i + j] = pws[3 * i + j] - cws[0][j];

  // step 2.2:利用SVD分解P'P可以获得P的主分量
  cvMulTransposed(PW0, &PW0tPW0, 1);
  cvSVD(&PW0tPW0,                         // A
        &DC,                              // W
        &UCt,                             // U
        0,                                // V
        CV_SVD_MODIFY_A | CV_SVD_U_T);    // flags

  cvReleaseMat(&PW0);

  // step 2.3:得到C1, C2, C3三个3D控制点,最后加上之前减掉的第一个控制点这个偏移量
  // 讲道理这里的条件不应写成4,而应该是变量 number_of_correspondences 啊
  for(int i = 1; i < 4; i++) {
    // 这里也是只有前三个奇异值 
    double k = sqrt(dc[i - 1] / number_of_correspondences);
    for(int j = 0; j < 3; j++)
      //? 但是这里为什么要乘k?
      cws[i][j] = cws[0][j] + k * uct[3 * (i - 1) + j];

具体推导过程见 https://blog.csdn.net/qq_30356613/article/details/80588134

M推导过程见 https://blog.csdn.net/qq_30356613/article/details/80588134

double PnPsolver::compute_R_and_t(const double * ut, const double * betas,double R[3][3], double t[3])
根据已经得到的控制点在当前相机坐标系下的坐标来恢复出相机的位姿

上一篇 下一篇

猜你喜欢

热点阅读