如果“世界坐标”指的是“对象坐标”,则必须对 pnp 算法给出的结果进行逆变换。
有一个反转变换矩阵的技巧,可以让您节省反转操作,这通常是昂贵的,并且解释了 Python 中的代码。给定一个变换[R|t]
,我们有那个inv([R|t]) = [R'|-R'*t]
, where R'
是转置R
。因此,您可以编写代码(未测试):
cv::Mat rvec, tvec;
solvePnP(..., rvec, tvec, ...);
// rvec is 3x1, tvec is 3x1
cv::Mat R;
cv::Rodrigues(rvec, R); // R is 3x3
R = R.t(); // rotation of inverse
tvec = -R * tvec; // translation of inverse
cv::Mat T = cv::Mat::eye(4, 4, R.type()); // T is 4x4
T( cv::Range(0,3), cv::Range(0,3) ) = R * 1; // copies R into T
T( cv::Range(0,3), cv::Range(3,4) ) = tvec * 1; // copies tvec into T
// T is a 4x4 matrix with the pose of the camera in the object frame
Update:以后要用到T
对于 OpenGL,您必须记住 OpenCV 和 OpenGL 之间相机框架的轴不同。
OpenCV 使用计算机视觉中常用的参考:X 指向右侧,Y 指向下方,Z 指向前方(如这个图片)。 OpenGL 中相机的坐标系是:X 指向右侧,Y 指向上方,Z 指向后方(如左手边所示)这个图片)。因此,您需要绕 X 轴旋转 180 度。该旋转矩阵的公式为维基百科.
// T is your 4x4 matrix in the OpenCV frame
cv::Mat RotX = ...; // 4x4 matrix with a 180 deg rotation around X
cv::Mat Tgl = T * RotX; // OpenGL camera in the object frame
这些转换总是令人困惑,我可能在某些步骤上是错误的,所以对此持保留态度。
最后,考虑到 OpenCV 中的矩阵在内存中以行优先顺序存储,而 OpenGL 矩阵以列优先顺序存储。