如何将OpenCV相机旋转矢量转换为OpenGL旋转矢量?

时间:2018-03-11 11:41:07

标签: c++ opencv opengl

我有一个相机旋转矩阵3x3,然后我使用Rodrigues函数从旋转矩阵中获取旋转矢量,但它给出的结果如rotVec = (0.02,0.32.-0.01),但OpenGL glRotate函数需要度measurment。我认为rotVec = (0.02,0.32.-0.01)是正常的,我应该将每个元素乘以360来获得学位。但OpenCV和OpenGL之间也存在坐标系差异。如何在OpenGL坐标系中获得以度为单位的旋转矢量?

1 个答案:

答案 0 :(得分:0)

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,并使用{直接与OpenGL MODELVIEW转换连接{ {1}}。 (glMultMatrix(xform.t().val)创建转置,t()是指向16个浮点数的转置数组的指针。)

如果你这样做,它可能仍然无法工作,因为在用于摄像机校准的OpenCV 3D坐标系中,+ X在右边,+ Y在下,而+ Z在摄像机前面。在“普通”OpenGL坐标系中,+ X在右侧,+ Y在向上,+ Z在摄像机后面(也就是说,只有负Z坐标可见)。两者都是右手系统,通过围绕X的180度旋转相关联。因此,您可以在OpenGL MODELVIEW堆栈的底部插入这样的旋转。然后,您可以将OpenCV 3D坐标直接传递给OpenGL。

(如果您想要使用OpenCV相机校准,例如正确对齐的增强现实,那么您还需要使用相机的内在矩阵仔细设置投影矩阵。但这是一个单独的问题......)

但是由于你的实际问题是如何在OpenGL坐标系中获得以度为单位的旋转矢量,那么你需要:

  • 决定矩阵是OpenGL还是OpenCV格式;如果是OpenGL,则转置它。
  • 调用Rodrigues()来获取向量。
  • 取矢量长度,即弧度的旋转角度,乘以180 / pi得到度数。
  • 调用glRotate(vector.x,vector.y,vector.z,degrees)来执行旋转。

不应考虑坐标系差异,因为两个系统都是右撇子。结果将在适合初始矩阵的坐标系中。