【问题标题】:Translation and Rotation vectors from view matrix (and back)来自视图矩阵(和返回)的平移和旋转向量
【发布时间】:2013-11-28 15:19:28
【问题描述】:

问题

我有一个相机的视图矩阵(作为 4x4 矩阵),我想从中提取旋转和平移向量,然后返回(从 rot 和 transl 向量到视图矩阵)。

我找到了一些论坛可以做到这一点,但它们不起作用。

我该怎么做?

背景

对于增强现实应用程序,我根据失真参数和solvePnP 计算视图矩阵。该方法有效:我在图像平面中找到了一些点(通过单击它们),并且通过了解现实世界中的点,我可以估计相机位置。

点击过程有一些错误(点击不准确),所以我想通过手动修改平移和旋转向量来优化相机位置。

所以我正在寻找一种方法从矩阵中获取向量,然后从向量返回到矩阵。

测试

我现在做的是:

void matrix2vector(cv::Mat n) { // n is the pose matrix
    this->position[0] = n.at<float>(3);
    this->position[1] = n.at<float>(7);
    this->position[2] = n.at<float>(11);

    float rx, ry, rz;
    rx = atan2(n.at<float>(9), n.at<float>(10));
    ry = atan2(-n.at<float>(8), 
               sqrt( n.at<float>(9)*n.at<float>(9) + n.at<float>(10)*n.at<float>(10) ));
    rz = atan2(n.at<float>(4), n.at<float>(0));
    this->angle[0] = rx * RAD2DEG;
    this->angle[1] = ry * RAD2DEG;
    this->angle[2] = rz * RAD2DEG;
}

void vector2matrix() {
    _viewMatrix =  cv::Mat::eye(4, 4, CV_32F);
    rotateX(_viewMatrix, _viewMatrix, -angle[0]);
    rotateY(_viewMatrix, _viewMatrix, -angle[1]);
    rotateZ(_viewMatrix, _viewMatrix, -angle[2]);
    _viewMatrix.at<float>(3) = position[0];
    _viewMatrix.at<float>(7) = position[1];
    _viewMatrix.at<float>(11) = position[2];
}

旋转方法在​​哪里:

inline
void rotateX(cv::Mat &src, cv::Mat &dst, float angleDegree) {
    dst = src.clone();

    float c = cosf(angleDegree * DEG2RAD);
    float s = sinf(angleDegree * DEG2RAD);
    float m4 = src.at<float>(4),
          m5 = src.at<float>(5),
          m6 = src.at<float>(6),
          m7 = src.at<float>(7),
          m8 = src.at<float>(8),
          m9 = src.at<float>(9),
          m10= src.at<float>(10),
          m11= src.at<float>(11);

    dst.at<float>(4) = m4 * c + m8 *-s;
    dst.at<float>(5) = m5 * c + m9 *-s;
    dst.at<float>(6) = m6 * c + m10*-s;
    dst.at<float>(7) = m7 * c + m11*-s;
    dst.at<float>(8) = m4 * s + m8 * c;
    dst.at<float>(9) = m5 * s + m9 * c;
    dst.at<float>(10)= m6 * s + m10* c;
    dst.at<float>(11)= m7 * s + m11* c;
}

inline
void rotateY(cv::Mat &src, cv::Mat &dst, float angleDegree)
{
    float c = cosf(angleDegree * DEG2RAD);
    float s = sinf(angleDegree * DEG2RAD);
    float m0 = src.at<float>(0),
          m1 = src.at<float>(1),
          m2 = src.at<float>(2),
          m3 = src.at<float>(3),
          m8 = src.at<float>(8),
          m9 = src.at<float>(9),
          m10= src.at<float>(10),
          m11= src.at<float>(11);

    dst.at<float>(0) = m0 * c + m8 * s;
    dst.at<float>(1) = m1 * c + m9 * s;
    dst.at<float>(2) = m2 * c + m10* s;
    dst.at<float>(3) = m3 * c + m11* s;
    dst.at<float>(8) = m0 *-s + m8 * c;
    dst.at<float>(9) = m1 *-s + m9 * c;
    dst.at<float>(10)= m2 *-s + m10* c;
    dst.at<float>(11)= m3 *-s + m11* c;
}

inline
void rotateZ(cv::Mat &src, cv::Mat &dst, float angleDegree)
{
    float c = cosf(angleDegree * DEG2RAD);
    float s = sinf(angleDegree * DEG2RAD);
    float m0 = src.at<float>(0),
          m1 = src.at<float>(1),
          m2 = src.at<float>(2),
          m3 = src.at<float>(3),
          m4 = src.at<float>(4),
          m5 = src.at<float>(5),
          m6 = src.at<float>(6),
          m7 = src.at<float>(7);

    dst.at<float>(0) = m0 * c + m4 *-s;
    dst.at<float>(1) = m1 * c + m5 *-s;
    dst.at<float>(2) = m2 * c + m6 *-s;
    dst.at<float>(3) = m3 * c + m7 *-s;
    dst.at<float>(4) = m0 * s + m4 * c;
    dst.at<float>(5) = m1 * s + m5 * c;
    dst.at<float>(6) = m2 * s + m6 * c;
    dst.at<float>(7) = m3 * s + m7 * c;
}

【问题讨论】:

    标签: opencv matrix coordinate-systems


    【解决方案1】:

    答案取决于您是使用列向量还是行向量来通过矩阵转换向量。假设您有一个矩阵M 和一个向量v,并且您将其转换为v' = Mv,则您使用的是列向量。相反,如果您有 v' = vM,则您正在使用行向量。

    要找到翻译,只需检查向量[0 0 0 1] 的结束位置。如果您使用的是列向量,您会发现矩阵的 最后一列 是翻译所在的位置。最后一列的前三个元素将是平移向量 (x,y,z)。同样,在行向量中,您会发现矩阵的 最后一行 是平移所在的位置。矩阵最后一行的前三个元素将是平移向量 (x,y,z)。

    对于旋转,请尝试将您的矩阵乘以向量 [1 0 0 0]。这将告诉您“x 轴”映射到的位置。对于[0 1 0 0](y 轴)和[0 0 1 0](z 轴)也是如此。无论您使用的是列向量还是行向量,相关条目都是 4x4 矩阵左上角的 3x3 子矩阵。行向量和列向量之间唯一变化的是映射轴是子矩阵中的列向量还是行向量。

    希望对您有所帮助。

    【讨论】:

    • 糟糕——现在您发布了一堆我第一次查看问题时不存在的代码。希望这个答案仍然相关。
    • (无论如何我都在使用列向量!)
    • 不是很清楚的旋转..你能解释得更好一点吗?
    • @nkint 你能告诉我更多关于你想要达到的目标吗?如果你“知道”轮换,你希望它采取什么形式?
    • @nkint 另外,请记住,欧拉角(您所要求的)通常不是唯一的,并且分解取决于您执行旋转的顺序。这是因为旋转不是可交换的,因此取决于顺序。根据您的情况,最好坚持使用 3x3 旋转矩阵,如果您希望“调整它”,只需将其乘以您设计的附加旋转矩阵(绕 X 轴旋转 10 度)即可执行调整。
    猜你喜欢
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    • 2012-05-05
    • 2013-12-06
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 2014-08-24
    相关资源
    最近更新 更多