我正在使用solvePnP,我得到了一个翻译向量。现在我需要将一些欧拉角与solvePnP的结果进行比较。我想/需要将欧拉角转换为“罗德里格斯”;
来自solvePnP的平移向量是否等于欧拉角。翻译矩阵是唯一与罗德里格斯有关的东西吗?还是有与 3 个欧拉角完全不同的特殊罗德里格斯角?两者之间的数学如何?有没有我找不到的 OpenCV 函数?
首先,忘记平移向量,因为它与旋转无关:平移移动物体,旋转改变它们的方向。
Rodrigues 参数也称为轴角旋转。它们由 4 个数字组成[theta, x, y, z]
,这意味着您必须围绕单位向量描述的轴旋转一个角度“theta” v=[x, y, z]
。查看cv::Rodrigues函数参考,似乎 OpenCV 使用 Rodrigues 符号的“紧凑”表示作为具有 3 个元素的向量rod2=[a, b, c]
,其中:
theta
是输入向量的模块theta = sqrt(a^2 + b^2 + c^2)
v
是归一化的输入向量:v = rod2/theta = [a/theta, b/theta, c/theta]
因此,solvePnP 中的 Rodrigues 向量与欧拉角符号甚至没有一点关系,欧拉角符号表示围绕 X、Y 和 Z 轴组合的三个连续旋转。
如何比较两个旋转?这是一个很好的问题。Euler 和 Rodrigues 表示都有奇点和其他问题。例如,如果您比较两个欧拉燕鸥或两个罗德里格斯参数,它们可能看起来完全不同,但实际上表示几乎相同的旋转。如果您只需要检查两个旋转是否相同(或近似),您可以按照下一个方法:
添加到@dunadar 的出色答案:
Rodrigues
转换rvec
为旋转矩阵 R(反之亦然)。您可以直接使用 R,就像使用由欧拉角构造的旋转矩阵一样,通过将点积与您正在旋转的(平移)向量进行运算:v_rotate = R*v
您可以将 Rodrigues 旋转矩阵转换为欧拉角,但有多种解决方案。原因是欧拉旋转的顺序(俯仰、偏航、滚动)很重要,因此有不止一种方法可以表示罗德里格斯旋转。见: http: //www.staff.city.ac.uk/~sbbh653/publications/euler.pdf
添加更具体的答案以补充此处的其他答案。如果你想要一个方向向量而不是欧拉角,这个过程确实可以通过矩阵乘法来简化,这里有一个快速的解决方案:
// The output is a direction vector in OpenGL coordinate system:
// +X is Right on the screen, +Y is Up, +Z is INTO the screen
static Vector3 ToDirectionVectorGL(const Mat& rodrigues1x3) noexcept
{
Mat rotation3x3;
cv::Rodrigues(rodrigues1x3, rotation3x3);
// direction OUT of the screen in CV coordinate system, because we care
// about objects facing towards us - you can change this to anything
// OpenCV coordsys: +X is Right on the screen, +Y is Down on the screen,
// +Z is INTO the screen
Vec3d axis{ 0, 0, -1 };
Mat direction = rotation3x3 * Mat(axis, false);
// normalize to a unit vector
double dirX = direction.at<double>(0);
double dirY = direction.at<double>(1);
double dirZ = direction.at<double>(2);
double len = sqrt(dirX*dirX + dirY*dirY + dirZ*dirZ);
dirX /= len;
dirY /= len;
dirZ /= len;
// Convert from OpenCV to OpenGL 3D coordinate system
return { float(dirX), float(-dirY), float(dirZ) };
}
如果您将其用于头部姿势估计,请确保在 {0,0,0} 周围正确形成 Rodrigues 1x3 旋转,否则您可能会得到奇怪的结果。