找到将 3D 局部坐标映射到全局坐标的变换矩阵
Find the Transformation Matrix that maps 3D local coordinates to global coordinates
我正在为我的深度相机编写校准算法。此相机输出单通道二维图像,其中包含图像中每个物体的距离。
根据该图像,并使用相机和畸变矩阵,我能够从相机的角度创建 3D 点云。现在我希望将这些 3D 坐标转换为 global/world 坐标。但是,由于我不能使用像棋盘这样的任何图案来校准相机,所以我需要另一种选择。
所以我在想:如果我提供一些地面点(在相机视角中),我会定义一个我知道在全局视角中 Z 坐标应该接近零的平面。那么,我应该如何着手寻找使平面水平化的变换矩阵。
Local coordinates ground plane, with an object on top
我尝试使用 OpenCV 的 solvePnP,但它没有给我正确的转换。我也想过使用 OpenCV 的 estimateAffine3D,但我不知道全局坐标应该映射到哪里,因为提供的地面点不需要放在任何特定的 pattern/shape.
提前致谢
您需要的是通常所说的 外部 校准:将 3D 相机参考系与 'world' 参考系相关联的刚性变换。通常,这是通过在世界参考系中找到已知的 3D 点及其在图像中对应的 2D 投影来完成的。这就是 SolvePNP 所做的。
要在两组3D点之间找到最好的rotation/translation,在最小化均方根误差的意义上,解法是:
- 理论:https://igl.ethz.ch/projects/ARAP/svd_rot.pdf
- 更简单的解释:http://nghiaho.com/?page_id=671
- 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)。这将 return 一个 3x3 矩阵 R 和一个 3x1 向量 t.
然后,对于世界参考系中的任意3D点p,作为一个3x1向量,可以得到对应的相机点,q 与:
q = R.dot(p)+t
编辑:当世界中点的 3D 位置未指定时回答
确实,要使此过程起作用,您需要知道(或更好地指定)世界参考系中点的 3D 坐标。正如您的评论中所述,您只知道这些点在一个平面中,但在该平面中没有它们的坐标。
这是一个可能的解决方案:
在相机参考系中取选定的3D点,我们称它们为q'i.
将平面拟合到这些点,例如 https://www.ilikebigbits.com/2015_03_04_plane_from_points.html 中所述。其结果将是法向量 n。要完全指定平面,您还需要选择一个点,例如 q'i.[=16= 的质心(平均) ]
由于点肯定不会完全位于平面上,因此将它们投影到平面上,例如:How to project a point onto a plane in 3D?中所述。我们称这些投影点为 qi.
此时你有一组 3D 点,qi,位于一个完美的平面上,它应该与地平面紧密对应(世界坐标系中的 z=0)。不过,坐标位于相机参考系中。
现在我们需要在此地平面中指定原点以及 x 轴和 y 轴的方向。你似乎对此没有任何标准,所以一个选择是任意设置原点 "below" 相机中心,并将 X 轴与相机光轴对齐。为此:
将点 (0,0,0) 投影到平面中,就像您在第 4 步中所做的那样。称其为 o。将点 (0,0,1) 投影到平面中,并将其命名为 a。计算向量 a-o,对其进行归一化并称之为 i.
o是世界参考系的原点,i是世界参考系的X轴帧,在相机坐标系中。调用 j=nxi(叉积)。 j 是 Y 轴,我们快完成了。
现在,通过投影获得世界坐标系中点qi的X-Y坐标在 i 和 j 上。也就是说,在每个 qi 和 i 之间做点积以获得 X 值和每个 qi 和 j 之间的点积以获得 Y 值。 Z值全为0。称这些X,Y,0坐标为pi.
使用 pi 和 qi[ 的这些值=137=] 估计 R 和 t,如答案的第一部分!
也许有更简单的解决方案。另外,我还没有测试过这个,但我认为它应该可以工作。希望这有帮助。
我正在为我的深度相机编写校准算法。此相机输出单通道二维图像,其中包含图像中每个物体的距离。
根据该图像,并使用相机和畸变矩阵,我能够从相机的角度创建 3D 点云。现在我希望将这些 3D 坐标转换为 global/world 坐标。但是,由于我不能使用像棋盘这样的任何图案来校准相机,所以我需要另一种选择。
所以我在想:如果我提供一些地面点(在相机视角中),我会定义一个我知道在全局视角中 Z 坐标应该接近零的平面。那么,我应该如何着手寻找使平面水平化的变换矩阵。
Local coordinates ground plane, with an object on top
我尝试使用 OpenCV 的 solvePnP,但它没有给我正确的转换。我也想过使用 OpenCV 的 estimateAffine3D,但我不知道全局坐标应该映射到哪里,因为提供的地面点不需要放在任何特定的 pattern/shape.
提前致谢
您需要的是通常所说的 外部 校准:将 3D 相机参考系与 'world' 参考系相关联的刚性变换。通常,这是通过在世界参考系中找到已知的 3D 点及其在图像中对应的 2D 投影来完成的。这就是 SolvePNP 所做的。
要在两组3D点之间找到最好的rotation/translation,在最小化均方根误差的意义上,解法是:
- 理论:https://igl.ethz.ch/projects/ARAP/svd_rot.pdf
- 更简单的解释:http://nghiaho.com/?page_id=671
- 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)。这将 return 一个 3x3 矩阵 R 和一个 3x1 向量 t.
然后,对于世界参考系中的任意3D点p,作为一个3x1向量,可以得到对应的相机点,q 与:
q = R.dot(p)+t
编辑:当世界中点的 3D 位置未指定时回答
确实,要使此过程起作用,您需要知道(或更好地指定)世界参考系中点的 3D 坐标。正如您的评论中所述,您只知道这些点在一个平面中,但在该平面中没有它们的坐标。
这是一个可能的解决方案:
在相机参考系中取选定的3D点,我们称它们为q'i.
将平面拟合到这些点,例如 https://www.ilikebigbits.com/2015_03_04_plane_from_points.html 中所述。其结果将是法向量 n。要完全指定平面,您还需要选择一个点,例如 q'i.[=16= 的质心(平均) ]
由于点肯定不会完全位于平面上,因此将它们投影到平面上,例如:How to project a point onto a plane in 3D?中所述。我们称这些投影点为 qi.
此时你有一组 3D 点,qi,位于一个完美的平面上,它应该与地平面紧密对应(世界坐标系中的 z=0)。不过,坐标位于相机参考系中。
现在我们需要在此地平面中指定原点以及 x 轴和 y 轴的方向。你似乎对此没有任何标准,所以一个选择是任意设置原点 "below" 相机中心,并将 X 轴与相机光轴对齐。为此:
将点 (0,0,0) 投影到平面中,就像您在第 4 步中所做的那样。称其为 o。将点 (0,0,1) 投影到平面中,并将其命名为 a。计算向量 a-o,对其进行归一化并称之为 i.
o是世界参考系的原点,i是世界参考系的X轴帧,在相机坐标系中。调用 j=nxi(叉积)。 j 是 Y 轴,我们快完成了。
现在,通过投影获得世界坐标系中点qi的X-Y坐标在 i 和 j 上。也就是说,在每个 qi 和 i 之间做点积以获得 X 值和每个 qi 和 j 之间的点积以获得 Y 值。 Z值全为0。称这些X,Y,0坐标为pi.
使用 pi 和 qi[ 的这些值=137=] 估计 R 和 t,如答案的第一部分!
也许有更简单的解决方案。另外,我还没有测试过这个,但我认为它应该可以工作。希望这有帮助。