胶片坐标到世界坐标

时间:2016-12-01 04:52:15

标签: c++ opencv opengl 3d computer-vision

我正在使用OpenCV3.1和OpenGL从匹配功能构建3D点云。

我实施了1)相机校准(因此我有相机的内在矩阵)2)特征提取(因此我在像素坐标中有2D点)。 我经历了几个网站,但通常所有人都提出了将3D对象点转换为像素点的流程,但我正在做完全后退投影。这是ppt,它解释得很好。

我已经从像素坐标(x,y)实现了电影坐标(u,v)(借助于内在矩阵)。任何人都可以阐明我如何渲染" Z"胶片坐标(x,y)的相机坐标(X,Y,Z)。

请指导我如何利用OpenCV中所需目标的功能,如solvePnP,recoverPose,findFundamentalMat,findEssentialMat。

2 个答案:

答案 0 :(得分:2)

如果你只拥有来自该单个摄像机位置的2D图像,则不能。

理论上,您可以使用启发式方法来推断Z堆叠。但是在数学上你的问题是在定义的,并且确实有无数多个不同的Z坐标来评估你的约束。你必须提供一些额外的信息。例如,您可以将相机移动几帧(谷歌“运动结构”),或者您可以使用多个相机或使用具有深度传感器的相机,并为您提供完整的XYZ元组(Kinect或类似)。

由于评论而更新:

对于2D图像中的每个像素,都会投射到无数个点。其技术术语称为 a ray 。如果您有两个大约相同空间体积的2D图像,则每个图像的光线集(每个像素一个)与对应于另一个图像的光线集相交。也就是说,如果确定图像#1中像素的光线,则会映射到图像#2中该光线所覆盖的像素线。选择图像#2中该行的特定像素将为您提供该点的XYZ元组。

由于您在图像之间沿着某个轴θ旋转了某个角度a,因此您实际上可以使用大量图像。您所要做的就是通过额外的转换(inverse(translate(-a)·rotate(θ)·translate(a))来获取相机位置。

然后执行以下操作:选择要开始的图像。对于您感兴趣的特定像素,确定它对应的光线。为此,简单地假设像素的两个Z值。 0和1工作得很好。将它们转换回对象的空间,然后将它们投影到您选择使用的下一个相机的视图空间中;结果将是图像平面中的两个点(可能超出实际图像的限制,但这不是问题)。这两个点在第二个图像中定义一条线。找到与您选择的第一个图像上的像素匹配的那条线上的像素,并将其投影回到第一个图像所做的空间。由于数值舍入误差,你不会得到3D空间中光线的完美交集,因此找到光线彼此最接近的点(这涉及求解二次多项式,这是微不足道的)。

要选择要在图像之间匹配的像素,可以使用视频压缩或类似功能中使用的某些特征运动跟踪算法。基本思想是,对于每个像素,其周围环境的相关性与前一图像中的相同区域一起执行。相关峰值在哪里,它可能从哪里移入。

通过这种像素跟踪,您可以导出对象的结构。这基本上就是来自运动的结构。

答案 1 :(得分:1)

在固定旋转平台上使用单个摄像头和旋转对象的情况下,我将执行以下操作:

setup

每台摄像机的分辨率为xs,ys,视场 FOV 由两个角度 FOVx,FOVy 定义,因此请检查或测量您的摄像机数据表。通过该距离和垂直距离(z,您可以将任何像素位置(x,y)转换为相对于相机(x',y',z')的3D坐标。因此,首先将像素位置转换为角度:

ax = (x - (xs/2)) * FOVx / xs 
ay = (y - (ys/2)) * FOVy / ys 

然后在3D中计算笛卡尔位置:

x' = distance * tan(ax)
y' = distance * tan(ay)
z' = distance

那很好,但是根据通用图像,我们不知道distance。幸运的是,在这种设置下,如果我们将对象旋转,则如果与摄影机垂直的平面相交,则任何凸边都会在侧面形成最大ax角。因此,检查几帧,如果检测到最大的ax,则可以假定其位于distance处的对象的边缘(或凸块)。

如果您还知道平台(相对于相机)的旋转角度ang,则可以通过围绕y使用rotation公式来计算未旋转位置轴(链接中的Ay矩阵)和相对于相机的已知平台中心位置(对于不旋转,仅减去部分)...正如我提到的,所有这些只是简单的几何。

简而言之:

  1. 获取校准数据

    FOVx,FOVy,xs,ys,距离。某些相机数据表仅包含FOVx,但是如果像素为矩形,则可以根据以下分辨率计算FOVy

    FOVx/FOVy = xs/ys
    

    当心使用多分辨率相机模式时,每种分辨率的FOV可能不同!!

  2. 针对每一帧提取视频中对象的轮廓

    您可以减去背景图像以简化检测

  3. 获取每帧的平台角度

    因此可以使用 IRC 数据或将已知标记放置在转盘上并进行检测/内插...

  4. 检测到最多ax

    只需检查轮廓的x坐标(分别针对图像的每一条y线),如果检测到峰,则将其 3D 位置添加到模型中。假设旋转矩形框。它的某些框架可能看起来像这样:

    max ax

    因此,检查所有帧上的一条水平线,找到最大值ax。为了提高精度,您可以通过旋转平台直至“精确”发现峰值来进行闭环调节。分别对所有水平线执行此操作。

    顺便说一句。。如果您没有检测到ax在几个框架上都没有变化,这意味着半径相同的圆形...因此,您可以处理ax这样的每个框架最大。

易于使用,可生成3D点云。您可以按平台角度对其进行排序,以简化向网格的转换...该角度也可以用作纹理坐标...

但不要忘记,您会丢失一些隐藏在轮廓中的凹形细节!!!

如果这种方法还不够,您可以使用相同的设置进行立体3D重建。因为每次旋转都表现为新的(已知)相机位置。