查找将 3D 局部坐标映射到全局坐标的变换矩阵



我正在为我的深度相机编写校准算法。该相机输出单通道2D图像,其中包含图像中每个物体的距离。

从那张图像中,使用相机和失真矩阵,我能够从相机的角度创建一个3D点云。现在我希望将这些 3D 坐标转换为全局/世界坐标。但是,由于我无法使用棋盘等任何模式来校准相机,因此我需要另一种选择。

所以我在想:如果我提供一些地面点(在相机视角中),我会定义一个我知道应该在全局视角中具有接近零的 Z 坐标的平面。那么,我应该如何继续找到水平化平面的变换矩阵。

本地坐标地平面,顶部有一个对象

我尝试使用OpenCV的solvePnP,但它没有给我正确的转换。我也想到使用OpenCV的estimateAffine3D,但我不知道全局坐标应该映射到哪里,因为提供的地面点不需要放在任何特定的图案/形状上。

提前致谢

您需要的是通常所说的外在校准:将3D相机参考框架与"世界"参考框架联系起来的刚性转换。通常,这是通过查找世界参考系中的已知3D点及其在图像中的相应 2D投影来完成的。这就是SolvePNP所做的。

为了找到两组 3D 点之间的最佳旋转/平移,在最小化均方根误差的意义上,解决方案是:

  1. 理论:https://igl.ethz.ch/projects/ARAP/svd_rot.pdf
  2. 更简单的解释:http://nghiaho.com/?page_id=671
  3. Python 代码(来自更简单的解释网站):http://nghiaho.com/uploads/code/rigid_transform_3D.py_

因此,如果要从照相机参考帧变换3D点,请执行以下操作:

  • 正如您所建议的,定义一些在世界参考系中具有已知位置的 3D 点,例如(但不一定)Z=0。将坐标放在 Nx3 矩阵P中。
  • 获取相机参考系中相应的 3D 点。将它们放入 Nx3 矩阵Q中。
  • 从上面第 3 点中定义的文件中,调用rigid_transform_3D(P, Q)。这将返回一个 3x3 矩阵R和一个 3x1 向量t

然后,对于世界参考系p中的任何3D点,作为3x1向量,可以得到对应的相机点q,其中

q = R.dot(p)+t

编辑:当世界上点的3D位置未指定时回答

事实上,要使此过程起作用,您需要知道(或更好地指定)世界参考系中点的 3D 坐标。如您的评论中所述,您只知道点在平面中,但在该平面中没有它们的坐标。

这是一个可能的解决方案:

  1. 取相机参考系中选定的3D点,我们称之为q'i

  2. 将平面拟合到这些点,例如如 https://www.ilikebigbits.com/2015_03_04_plane_from_points.html 中所述。其结果将是一个法向量n。要完全指定平面,您还需要选择一个点,例如q'i的质心(平均值)。

  3. 由于点肯定不能完全位于平面中,因此请将它们投影到平面上,例如如中所述:如何在 3D 模式下将点投影到平面上?。我们称这些投影点为qi

  4. 此时,您有一组位于完美平面上的 3D 点qi,该平面应与地平面(世界坐标框中的 z=0)非常接近。不过,坐标位于相机参考系中。

  5. 现在我们需要指定该地平面中 x 轴和 y 轴的原点和方向。您似乎对此没有任何标准,因此可以选择任意设置原点,刚好位于相机中心的"下方",并将X轴与相机光轴对齐。为此:

  6. 将点 (0,0,0) 投影到平面中,就像您在步骤 4 中所做的那样。称之为o。将点 (0,0,1) 投影到平面中并调用它。计算向量a-o,对其进行规范化并调用它i

  7. o 是世界参考系的
  8. 原点,i是世界参考系的 X 轴,以相机坐标表示。调用j=nxi( 交叉积)。j是Y轴,我们几乎完成了。

  9. 现在,通过将点 q i 投影到 i 和j上,获得世界参考系中点qi的 X-Y 坐标。也就是说,在每个 q i 和 i 之间做点积以获得 X值,在每个qij之间做点积以获得 Y 值。Z 值均为 0。称这些 X, Y, 0 坐标为pi

  10. 使用 p i 和qi的这些值来估计Rt,如答案的第一部分!

也许有一个更简单的解决方案。另外,我还没有测试过这个,但我认为它应该可以工作。希望这有帮助。

最新更新