我有一个3x3的相机旋转矩阵,然后我使用Rodrigues
函数从旋转矩阵获取旋转 vector ,但是它给出的结果类似于rotVec = (0.02,0.32.-0.01)
,但是OpenGL glRotate
函数需要度数。我认为rotVec = (0.02,0.32.-0.01)
是规范化的,我应该将每个元素乘以360以得到度。但是在OpenCV和OpenGL之间也存在坐标系统差异。如何在OpenGL坐标系中获得以度为单位的旋转 vector ?
最佳答案
OpenCV和OpenGL使用不同的3D坐标系和不同的内存中矩阵表示形式。 OpenGL矩阵以列优先顺序存储在内存中。例如:
m[0] m[4] m[8] m[12]=tx
m[1] m[5] m[9] m[13]=ty
m[2] m[6] m[10] m[14]=tz
m[3]=0 m[7]=0 m[11]=0 m[15]=1
与按行优先顺序排列的常规OpenCV矩阵相比,该函数已转置。例如:
m[0] m[1] m[2] m[3]=tx
m[4] m[5] m[6] m[7]=ty
m[8] m[9] m[10] m[11]=tz
m[12]=0 m[13]=0 m[14]=0 m[15]=1
因此,您需要跟踪矩阵是OpenCV还是OpenGL格式。它们可以通过换位(
cv::Mat::t()
运算符)进行转换。因此,与其使用Rodrigues()(假设您的旋转矩阵是
cv::Matx33
),不如将其填充为零平移将其转换为cv::Matx44
,并使用glMultMatrix(xform.t().val)
直接与OpenGL MODELVIEW转换连接。 (t()
创建转置,而.val
是指向16个浮点的转置数组的指针。)如果这样做,它可能仍然无法使用,因为在用于摄像机校准的OpenCV 3D坐标系中,+ X在右边,+ Y在下面,+ Z在摄像机前面。在“常规” OpenGL坐标系中,+ X在右侧,+ Y在上,+ Z在摄影机后面(即,仅负Z坐标可见)。两者都是右手系统,它们围绕X旋转了180度。因此,您可以在OpenGL MODELVIEW堆栈的底部插入这样的旋转。然后,您可以将OpenCV 3D坐标直接传递给OpenGL。
(如果要使用OpenCV摄像机校准,例如为了正确对齐增强现实,则还需要使用摄像机的内在矩阵仔细设置投影矩阵。但这是一个单独的问题...)
但是由于您的实际问题是如何在OpenGL坐标系中获取以度为单位的旋转 vector ,因此您需要:
由于两个系统都是右撇子,因此无需考虑坐标系的差异。结果将在适合初始矩阵的坐标系中。
关于c++ - 如何将OpenCV摄像机旋转 vector 转换为OpenGL旋转 vector ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49219595/