c++ - 如何将OpenCV摄像机旋转 vector 转换为OpenGL旋转 vector ?

标签 c++ opencv opengl

我有一个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 ,因此您需要:
  • 决定矩阵是OpenGL还是OpenCV格式;如果是OpenGL,请对其进行转置。
  • 调用Rodrigues()获得 vector 。
  • 取 vector 长度(以弧度为单位的旋转 Angular ),然后乘以180 / pi以得到度。
  • 调用glRotate(vector.x,vector.y,vector.z,度)执行旋转。

  • 由于两个系统都是右撇子,因此无需考虑坐标系的差异。结果将在适合初始矩阵的坐标系中。

    关于c++ - 如何将OpenCV摄像机旋转 vector 转换为OpenGL旋转 vector ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49219595/

    相关文章:

    opencv - Haar Cascade 是 OpenCV 中唯一可用的图像识别技术吗

    c++ - 这些哪个更快?

    opengl - COLLADA是无效格式吗?

    c++ - 构造函数返回什么?

    c++ - C++ 中的临时变量、引用和三元运算符

    c++ - 减少非虚拟多态类中基派生委托(delegate)的样板

    c++ - MFC 使一个类同时扩展 CView 和 CDockablePane

    c++ - at() 和 row().col() 之间的区别

    python - 使用 python 和 opencv 保存视频时出错

    c++ - MSVC __debugbreak()与openGL错误回调一起使用时不产生调用栈