电影坐标到世界坐标
Film coordinate to world coordinate
我正在使用 OpenCV3.1 和 OpenGL 通过特征匹配构建 3D 点云。
我已经实施了 1) 相机校准(因此我有相机的固有矩阵)2) 特征提取(因此我在像素坐标中有 2D 点)。
我浏览了几个网站,但通常都建议将 3D 对象点转换为像素点的流程,但我正在做完全反向投影。这是很好地解释它的ppt。
我已经从像素坐标(x,y)(借助本征矩阵)实现了胶片坐标(u,v)。谁能阐明我如何从胶片坐标 (x,y) 渲染相机坐标 (X,Y,Z) 的 "Z"。
请指导我如何在 OpenCV 中利用函数实现预期目标,例如 solvePnP、recoverPose、findFundamentalMat、findEssentialMat。
你不能,如果你只有来自那个单一相机位置的 2D 图像。
理论上您可以使用试探法来推断 Z 堆叠。但是从数学上讲,您的问题定义不足,并且实际上有无数种不同的 Z 坐标可以评估您的约束。你必须提供一些额外的信息。例如,您可以在多个帧上移动相机(Google“运动结构”),或者您可以使用多个相机或使用具有深度传感器并为您提供完整 XYZ 元组(Kinect 或类似设备)的相机。
因评论而更新:
对于二维图像中的每个像素,都有无数个点投射到它。其技术术语称为 a ray。如果您有两张 space 体积大致相同的二维图像,则每张图像的一组光线(每个像素一个)与对应于另一张图像的一组光线相交。也就是说,如果您确定图像 #1 中某个像素的光线,则它会映射到图像 #2 中该光线覆盖的一行像素。 Select沿图像 #2 中的那条线计算一个特定像素将为您提供该点的 XYZ 元组。
由于您在图像之间沿特定轴 a
将对象旋转特定角度 θ
,因此您实际上有很多图像要处理。您所要做的就是通过额外的转换 (inverse(translate(-a)·rotate(θ)·translate(a)
).
推导相机位置
然后执行以下操作:Select 从一张图片开始。对于您感兴趣的特定像素,确定它对应的光线。为此,只需假设像素有两个 Z 值。 0 和 1 工作得很好。将它们转换回对象的 space,然后将它们投影到您选择使用的下一个相机的视图 space;结果将是图像平面中的两个点(可能超出实际图像的范围,但这不是问题)。这两个点定义了第二个图像中的一条线。沿着那条线找到与您 select 编辑的第一张图像上的像素相匹配的像素,然后像对第一张图像所做的那样将其投影回 space。由于数值舍入误差,您不会在 3D space 中获得完美的光线交点,因此找到光线彼此最近的点(这涉及求解二次多项式,微不足道)。
要select要在图像之间匹配哪个像素,您可以使用一些特征运动跟踪算法,如用于视频压缩或类似算法。基本思想是,对于每个像素,其周围环境与前一图像中的相同区域相关。相关峰值在哪里,它可能从哪里移动到哪里。
有了这个像素跟踪,您就可以推导出物体的结构。这基本上就是运动结构所做的。
在固定旋转平台上使用单个摄像头和旋转物体,我会实现这样的东西:
每个摄像头的分辨率 xs,ys
和视野 FOV 由两个角度定义 FOVx,FOVy 所以要么检查你的相机数据 sheet 或对其进行测量。从该距离和垂直距离 (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
(相对于您的相机)那么您可以使用[=28计算未旋转的位置 =] 围绕 y 轴的公式(link 中的 Ay
矩阵)和相对于相机的已知平台中心位置(只是在未旋转之前减去)...正如我提到的,所有这些只是简单的几何.
简而言之:
获取校准数据
FOVx,FOVy,xs,ys,距离。一些相机数据sheets 只有 FOVx 但如果像素是矩形的,你可以从分辨率计算 FOVy 为
FOVx/FOVy = xs/ys
注意多分辨率相机模式,每种分辨率的 FOV 可能不同!!!
为每一帧提取视频中对象的轮廓
您可以减去背景图像以简化检测
获取每一帧的平台角度
所以要么使用 IRC 数据,要么在旋转盘上放置已知标记,然后 detect/interpolate...
检测ax
最大值
只需检查轮廓的 x 坐标(分别针对图像的每个 y
行),如果检测到峰,则将其 3D 位置添加到您的模型中。假设旋转矩形框。它的某些框架可能如下所示:
因此检查所有帧上的一条水平线并找到最大值 ax
。为了提高准确性,您可以通过转动平台来进行闭环调节,直到找到峰值 "exactly"。分别对所有水平线执行此操作。
btw. 如果你检测到几帧没有 ax
变化,这意味着具有相同半径的圆形......所以你可以处理每个这样的帧ax
最大值。
生成 3D 点云非常简单。您可以按平台角度排序以方便转换为网格...该角度也可以用作纹理坐标...
但不要忘记你会丢失一些隐藏在剪影中的凹面细节!!!
如果此方法不够,您可以使用相同的设置进行 立体 3D 重建 。因为每次旋转都表现为新的(已知)相机位置。
我正在使用 OpenCV3.1 和 OpenGL 通过特征匹配构建 3D 点云。
我已经实施了 1) 相机校准(因此我有相机的固有矩阵)2) 特征提取(因此我在像素坐标中有 2D 点)。 我浏览了几个网站,但通常都建议将 3D 对象点转换为像素点的流程,但我正在做完全反向投影。这是很好地解释它的ppt。
我已经从像素坐标(x,y)(借助本征矩阵)实现了胶片坐标(u,v)。谁能阐明我如何从胶片坐标 (x,y) 渲染相机坐标 (X,Y,Z) 的 "Z"。
请指导我如何在 OpenCV 中利用函数实现预期目标,例如 solvePnP、recoverPose、findFundamentalMat、findEssentialMat。
你不能,如果你只有来自那个单一相机位置的 2D 图像。
理论上您可以使用试探法来推断 Z 堆叠。但是从数学上讲,您的问题定义不足,并且实际上有无数种不同的 Z 坐标可以评估您的约束。你必须提供一些额外的信息。例如,您可以在多个帧上移动相机(Google“运动结构”),或者您可以使用多个相机或使用具有深度传感器并为您提供完整 XYZ 元组(Kinect 或类似设备)的相机。
因评论而更新:
对于二维图像中的每个像素,都有无数个点投射到它。其技术术语称为 a ray。如果您有两张 space 体积大致相同的二维图像,则每张图像的一组光线(每个像素一个)与对应于另一张图像的一组光线相交。也就是说,如果您确定图像 #1 中某个像素的光线,则它会映射到图像 #2 中该光线覆盖的一行像素。 Select沿图像 #2 中的那条线计算一个特定像素将为您提供该点的 XYZ 元组。
由于您在图像之间沿特定轴 a
将对象旋转特定角度 θ
,因此您实际上有很多图像要处理。您所要做的就是通过额外的转换 (inverse(translate(-a)·rotate(θ)·translate(a)
).
然后执行以下操作:Select 从一张图片开始。对于您感兴趣的特定像素,确定它对应的光线。为此,只需假设像素有两个 Z 值。 0 和 1 工作得很好。将它们转换回对象的 space,然后将它们投影到您选择使用的下一个相机的视图 space;结果将是图像平面中的两个点(可能超出实际图像的范围,但这不是问题)。这两个点定义了第二个图像中的一条线。沿着那条线找到与您 select 编辑的第一张图像上的像素相匹配的像素,然后像对第一张图像所做的那样将其投影回 space。由于数值舍入误差,您不会在 3D space 中获得完美的光线交点,因此找到光线彼此最近的点(这涉及求解二次多项式,微不足道)。
要select要在图像之间匹配哪个像素,您可以使用一些特征运动跟踪算法,如用于视频压缩或类似算法。基本思想是,对于每个像素,其周围环境与前一图像中的相同区域相关。相关峰值在哪里,它可能从哪里移动到哪里。
有了这个像素跟踪,您就可以推导出物体的结构。这基本上就是运动结构所做的。
在固定旋转平台上使用单个摄像头和旋转物体,我会实现这样的东西:
每个摄像头的分辨率 xs,ys
和视野 FOV 由两个角度定义 FOVx,FOVy 所以要么检查你的相机数据 sheet 或对其进行测量。从该距离和垂直距离 (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
(相对于您的相机)那么您可以使用[=28计算未旋转的位置 =] 围绕 y 轴的公式(link 中的 Ay
矩阵)和相对于相机的已知平台中心位置(只是在未旋转之前减去)...正如我提到的,所有这些只是简单的几何.
简而言之:
获取校准数据
FOVx,FOVy,xs,ys,距离。一些相机数据sheets 只有 FOVx 但如果像素是矩形的,你可以从分辨率计算 FOVy 为
FOVx/FOVy = xs/ys
注意多分辨率相机模式,每种分辨率的 FOV 可能不同!!!
为每一帧提取视频中对象的轮廓
您可以减去背景图像以简化检测
获取每一帧的平台角度
所以要么使用 IRC 数据,要么在旋转盘上放置已知标记,然后 detect/interpolate...
检测
ax
最大值只需检查轮廓的 x 坐标(分别针对图像的每个
y
行),如果检测到峰,则将其 3D 位置添加到您的模型中。假设旋转矩形框。它的某些框架可能如下所示:因此检查所有帧上的一条水平线并找到最大值
ax
。为了提高准确性,您可以通过转动平台来进行闭环调节,直到找到峰值 "exactly"。分别对所有水平线执行此操作。btw. 如果你检测到几帧没有
ax
变化,这意味着具有相同半径的圆形......所以你可以处理每个这样的帧ax
最大值。
生成 3D 点云非常简单。您可以按平台角度排序以方便转换为网格...该角度也可以用作纹理坐标...
但不要忘记你会丢失一些隐藏在剪影中的凹面细节!!!
如果此方法不够,您可以使用相同的设置进行 立体 3D 重建 。因为每次旋转都表现为新的(已知)相机位置。