将坐标系投影到图像中的倾斜平面上

Project coordinate system onto angled planar surface in image

我想定义一个坐标系,投影到图像中的某个平面上。我只需要一些关于如何实现它的提示和想法,不一定是代码,但一切都会受到赞赏!如果提供代码,在 OpenCV 中最好使用 Python 作为语言。

示例:我有一张 table 的图像,从某些角度看。我使用放置在 table 顶部的棋盘图案拍摄了 N 个校准图像。我们可以想象它是一个平面斯诺克 table。我已经计算了 intrinsic/extrinsic 校准矩阵,一个单应矩阵,我可以将图像投影到我的 table 顶面上——一切都很好。但是现在我想在 table 顶部创建一个坐标系。如果我知道 tabletop 的尺寸是 1 米 x 2 米,我想要一个函数,我可以说:给我图像中对应于点 (x=0.75 米) 的二维像素坐标, y=1.65 米) 在 table 顶面上。我希望原点从 tabletop 的左上角开始,但这应该只是一个翻译问题。我怎样才能让这个坐标系和相应的功能“使用”它?

我提出了两种可能的方法,但两者似乎都非常无效,我相信必须存在一种更有效和更可靠的方法。

1: 从我的校准过程中,我在 table 顶部放置了 N 个不同的校准图案图像。这给了我 N 个局部坐标系,一个用于每个校准模式。由于每个校准图案都留在 table 顶部,因此 x 轴和 y 轴将始终位于同一平面内。使用 this OpenCV 指南,我可以绘制遵循 tabletop 平面的轴,每个点都匹配为棋盘正方形的大小,所以我有一个有效的公制转换米到-像素。最大的问题是,如果棋盘边缘不平行于 table 边缘,那么我的坐标系就会错位。另一个问题是,由于有 N 个小坐标系,我必须选择一个任意坐标系,然后手动找到其对应的平移到左上角 tabletop 位置并围绕原点旋转以重新对齐轴。这使得解决方案非常手动,并且难以动态化。最终最好只定义 4 个手动识别的 table 像素值边缘,然后定义任何需要的派生值,例如单应矩阵、旋转矩阵、平移矩阵等

2: 我可以生成坐标网格的图像,然后将此图像网格投影到我的 table-top 图像上。该技术类似于 this。然后我会扩充我原来的 table-top 图像以包含一个已正确转换的网格(即靠近相机的网格坐标方块大于较远的网格坐标方块)。然而,这并不能使我从绘制的网格中提取坐标。如果我可以投影网格而不是图像,那将是一个非常简单的解决方案。据我在 OpenCV 文档中看到的,这是不可能的。

配方形式:

  • 使用任何必要的方式(例如单击并收集鼠标单击坐标)在图像中识别所需原点的图像位置。

  • 以相同的方式在所需的 X 轴上标识一个点,在所需的 Y 轴上标识一个点。

  • 将这些像素反投影到世界坐标中的光线中,使用校准期间获得的任何一个坐标变换(a.k.a。外部参数)作为“世界”。我们称其相对于相机的旋转矩阵和平移分别为Rc0, Tc0

  • 将射线与XY世界平面(==放置在table上的标定靶平面)相交,得到3D点Ot、Xt、Yt。

  • 计算向量 xt = (Xt - Ot) / np.linalg.norm(Xt - Ot)yt = (Yt - Ot) / np.linalg.norm(Yt - Ot)

  • 使用 Gram 方法将它们正交化:yt = yt - yt.dot(xt) * xt; yt = yt / np.linalg.norm(yt).

  • 计算第三轴:zt = np.cross(xy, yt).

  • 三元组(xt, yt, zt)就是你想要的坐标系,以Ot为中心。矩阵 R0t = np.hstack((xt, yt, zt)) 是从该坐标系到世界坐标系的旋转。

  • 从新帧到相机的坐标变换是Rct = Rc0.dot(R0t), Tt = Ot