c++ - 在二维图像上绘制欧拉角旋转模型

标签 c++ opencv euler-angles

我目前正在尝试在2d图像(没有opengl或3d图形窗口)中绘制欧拉角的3d表示。图像输出可能类似于以下内容。

本质上,我正在寻找可以采用旋转矩阵或一组欧拉角,然后将其输出到2d图像上的研究或算法,如上。这将在使用OpenCV的C++应用程序中实现。它将用于根据对象的状态在OpenCV窗口上输出注释信息。

我想我已经过分考虑了,因为我应该能够从旋转矩阵分解单位 vector ,然后提取它们的x,y分量并在(0,0)的笛卡尔空间中画一条线。我的想法正确吗?

编辑:我正在寻找一个正交投影。您可以假定上面的图像具有正确的相机/视角。

任何帮助,将不胜感激。

谢谢,

编辑:现在可以在我的仓库中找到示例源代码。
header :https://bitbucket.org/jluzwick/tennisspindetector/src/6261524425e8d80772a58fdda76921edb53b4d18/include/projection_matrix.h?at=master

类定义:https://bitbucket.org/jluzwick/tennisspindetector/src/6261524425e8d80772a58fdda76921edb53b4d18/src/projection_matrix.cpp?at=master

这不是最好的代码,但是它可以工作并显示了获得公认答案中描述的投影矩阵所需的步骤。

另外,这里是实际中的投影矩阵的youtube vid(以及缩放和平移):http://www.youtube.com/watch?v=mSgTFBFb_68

最佳答案

这是我的两分钱。希望能帮助到你。

如果我理解正确,则需要旋转3D坐标系,然后将其正交投影到给定的2D平面上(相对于原始的未旋转的3D坐标系定义了2D平面)。

“旋转和投影坐标的3D系统”是“旋转三个3D基本 vector 并将它们正交投影到2D平面上,以便它们相对于该平面的2D基础成为2D vector ”。让原始的3D vector 不作底漆,然后对所得的2D vector 作底漆。令 {e1,e2,e3} = {e1..3} 为3D正交基础(已给出),而 {e1',e2'} = {e1..2'} 为2D正交基础(我们必须定义)。本质上,我们需要找到 PR * v = v'的运算符 PR

尽管我们可以谈论很多关于线性代数,算子和矩阵表示的文章,但发布的时间可能太长了。这么说就足够了:

  • 对于3D旋转和3D-> 2D投影运算符,都有真实的矩阵表示(线性变换; 2D是3D的子空间)。
  • 这是因此应用的两个转换,即 PR * v = P * R * v = v',因此我们需要找到旋转矩阵 R 和投影矩阵 P 。显然,在使用 R 旋转 v 之后,我们可以使用 P 投影结果 vector vR
  • 您已经有了旋转矩阵 R ,因此我们认为它是给定的3x3矩阵。因此,为简单起见,我们将讨论投影 vector vR = R * v
  • 投影矩阵 P 是一个2x3矩阵,第i列是第i个3D基础 vector ei {e1..2'} 基础上的投影。

  • 让我们找到 P 投影矩阵,例如3D vector vR 在2D平面上线性变换为2D vector v',其正交基础为 {e1..2'}

    2D平面可以通过垂直于它的 vector 轻松定义。例如,从OP中的图形看,我们的2D平面(纸的平面)似乎具有法线单位 vector n = 1 / sqrt(3)*(1,1,1)。我们需要在此定义的2D平面中找到2D基础。由于位于我们2D平面中的任何两个线性独立 vector 都将形成这样的基础,因此这里有无数个这样的基础。从问题的几何形状出发,为了简单起见,让我们施加两个附加条件:首先,基础应该是正交的;第二,基础应该是正交的。其次,应该具有视觉吸引力(尽管这在一定程度上是主观的)。可以很容易地看出,通过设置 e1'=(1,0)'= x'-轴(从左到右的水平,正方向)和 e2'=( 0,1)'= y'-轴(从下到上的垂直正方向)。

    现在让我们在 {e1..3} 3D基础中找到这个 {e1',e2'} 2D基础。
  • 让我们在原始基础上将 e1' e2'表示为 e1“ e2” 。请注意,在我们的情况下, e1“没有 e3 -component( z -component),并使用 n点e1” = 0 的事实,我们得到 e1'=(1,0) '-> e1“=(-1 / sqrt(2),1 / sqrt(2),0)以 {e1..3} 为基础的。这里,表示点积。
  • 然后 e2“= n交叉e1” =(-1 / sqrt(6),-1 / sqrt(6),2 / sqrt(6))。在此,交叉表示叉积。

  • 然后,由 n = 1 / sqrt(3)*(1,1,1)定义的2D平面的2x3投影矩阵 P 由下式给出:
    ( -1/sqrt(2)    1/sqrt(2)        0     )
    ( -1/sqrt(6)   -1/sqrt(6)    2/sqrt(6) )
    

    其中将第一,第二和第三列 {e1..3} 3D基础转换为我们的2D基础 {e1..2'} ,即 e1 =(1,0,0)3D基础的具有坐标(-1 / sqrt(2),-1 / sqrt(6))(以2D为基础),依此类推。

    为了验证结果,我们可以检查一些明显的情况:
  • n 与我们的2D平面正交,因此应该没有投影。实际上, P * n = P *(1,1,1)= 0
  • e1 e2 e3 应该转换为 {e1..2'} 中的表示形式,即 P 矩阵中的对应列。实际上, P * e1 = P *(1,0,0)=(-1 / sqrt(2),-1 / sqrt(6))等。

  • 最后确定问题。现在,我们为任意选择的2D平面从3D到2D构造了一个投影矩阵 P 。现在,我们可以将先前通过旋转矩阵 R 旋转过的任何 vector 投影到此平面上。例如,旋转的原始基础 {R * e1,R * e2,R * e3} 。此外,我们可以将给定的 P R 相乘,以获得旋转投影变换矩阵 PR = P * R

    附言C++实现留给家庭作业;)。

    关于c++ - 在二维图像上绘制欧拉角旋转模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18303966/

    相关文章:

    python - 将黑框添加到列表中的图像

    c# - 找到两个法向量之间的 x,y,z 旋转

    c++ - 欧拉角到四元数然后四元数到欧拉角

    c++ - cout 的缓冲区如何工作?

    c++ - OpenGL:对象边缘的颜色值

    android - 错误:错误:找不到(3,10) 'opencv2/opencv.hpp'文件

    python - 我可以在 OpenCV 中将 ffmpeg 的 "stream copy"与 VideoWriter 类一起使用吗?

    c++ - 在 X、Y 和 Z(平移)值中补偿俯仰、滚动和偏航

    c++ - 包括 std::forward 会产生错误,但它的遗漏会编译。为什么?

    c++ - C++实现合并排序的运行时错误