Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 罗德里格斯成了尤兰格,反之亦然_C++_Opencv_Rotation - Fatal编程技术网

C++ 罗德里格斯成了尤兰格,反之亦然

C++ 罗德里格斯成了尤兰格,反之亦然,c++,opencv,rotation,C++,Opencv,Rotation,我正在使用solvePnP,我得到了一个翻译向量。 现在我需要将一些欧拉角与solvePnP的结果进行比较。 我想/需要把欧拉角转换成“罗德里格斯” 来自solvePnP的平移向量等于euler角。 翻译矩阵是唯一与罗德里格斯有关的东西吗? 或者是否存在与3个欧拉角完全不同的特殊罗德里格斯角? 两者之间的数学关系如何? 是否有我找不到的OpenCV函数 首先,忘记平移向量,因为它与旋转无关:平移移动物体,旋转改变它们的方向 罗德里格斯参数也称为。它们由4个数字组成,这意味着你必须围绕单位向量v=

我正在使用solvePnP,我得到了一个翻译向量。 现在我需要将一些欧拉角与solvePnP的结果进行比较。 我想/需要把欧拉角转换成“罗德里格斯”

来自solvePnP的平移向量等于euler角。 翻译矩阵是唯一与罗德里格斯有关的东西吗? 或者是否存在与3个欧拉角完全不同的特殊罗德里格斯角? 两者之间的数学关系如何?
是否有我找不到的OpenCV函数

首先,忘记平移向量,因为它与旋转无关:平移移动物体,旋转改变它们的方向

罗德里格斯参数也称为。它们由4个数字组成,这意味着你必须围绕单位向量v=[x,y,z]描述的轴旋转一个角度“θ”。 从函数引用来看,OpenCV似乎使用罗德里格斯符号的“紧凑”表示法作为向量,包含3个元素
rod2=[a,b,c]
,其中:

  • 旋转角度θ是输入向量θ=sqrt(a^2+b^2+c^2)的模
  • 旋转轴
    v
    是标准化的输入向量:
    v=rod2/theta=[a/theta,b/theta,c/theta]
因此,solvePnP中的Rodrigues向量与符号没有任何关系,表示围绕X、Y和Z轴组合的三个连续旋转

如何比较两种旋转?这是一个好问题。欧拉和罗德里格斯的表述都有奇点和其他问题。例如,如果比较两个Euler Tern或两个Rodrigues参数,它们看起来可能完全不同,但实际上表示几乎相同的旋转。 如果您只需要检查两个旋转是否相同(或近似值),可以采用下一种方法:

  • 将两个旋转变换为矩阵表示法(四元数也有效)
    • OpenCV罗德里格斯矢量可以使用函数转换为矩阵
    • 要将Euler转换为矩阵,我建议您查看euclideanspace.com的
  • 将一个旋转与另一个旋转“相减”,即将一个旋转与另一个旋转的倒数连接起来
    • 使用旋转矩阵,将一个矩阵乘以另一个矩阵的转置(逆旋转)。零旋转是单位矩阵
    • 使用四元数,将一个数乘以另一个数的复共轭数(最后三个分量求反)
  • 检查结果是否接近空旋转:
    • 零旋转矩阵是恒等式
    • 空四元数在第一个分量中有1或-1

  • 除了@dunadar的优秀答案之外:

    Rodrigues
    rvec
    转换为旋转矩阵R(反之亦然)。可以直接使用R,就像使用由Euler角构造的旋转矩阵一样,通过将点积与正在旋转的(平移)向量相结合:
    v_rotate=R*v


    可以将Rodrigues旋转矩阵转换为Euler角度,但有多种解决方案。原因是欧拉旋转的顺序(俯仰、偏航、横摇)很重要,所以有多种方式来表示罗德里格斯旋转。请参阅:

    在此处添加更具体的答案以补充其他答案。如果你想要一个方向向量而不是欧拉角,这个过程确实可以通过矩阵乘法来简化,这里有一个快速的解决方案:

    // 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) };
    }
    
    //输出是OpenGL坐标系中的方向向量:
    //+X正好在屏幕上,+Y向上,+Z进入屏幕
    静态矢量3到方向矢量GL(const Mat&Rodrigues13X3)无例外
    {
    垫旋转3x3;
    cv::罗德里格斯(罗德里格斯13x3,旋转3x3);
    //在CV坐标系中的屏幕外方向,因为我们关心
    //关于面向我们的对象-您可以将其更改为任何内容
    //OpenCV coordsys:+X显示在屏幕上,+Y显示在屏幕上,
    //+Z进入屏幕
    Vec3d轴{0,0,-1};
    垫方向=旋转3x3*垫(轴,假);
    //规格化为单位向量
    双dirX=方向。在(0);
    双方向=方向。在(1);
    双dirZ=方向,在(2)处;
    双透镜=sqrt(dirX*dirX+dirY*dirY+dirZ*dirZ);
    dirX/=len;
    dirY/=len;
    dirZ/=len;
    //从OpenCV到OpenGL三维坐标系的转换
    返回{float(dirX),float(-dirY),float(dirZ)};
    }
    

    如果您将其用于头部姿势估计,请确保罗德里格斯1x3旋转在{0,0,0}周围正确形成,否则您可能会得到奇怪的结果。

    这是实现R->euler(用小数字处理精度问题)的更好参考。你救了我一天!!!theta=sqrt(a^2+b^2+c^2)和v=rod2/theta=[a/theta,b/theta,c/theta]正是我想要的函数。。。谢谢