【问题标题】:To calculate world coordinates from screen coordinates with OpenCV使用 OpenCV 从屏幕坐标计算世界坐标
【发布时间】:2012-08-14 00:27:40
【问题描述】:

我已经用 OpenCV 计算了相机的内在和外在参数。 现在,我想根据屏幕坐标 (u,v) 计算世界坐标 (x,y,z)。

我该怎么做?

注意在我使用 kinect 时,我已经知道 z 坐标了。

非常感谢任何帮助。谢谢!

【问题讨论】:

  • 所以你是说你有Xscreen、Yscreen和Zworld?你想要 Xworld、Yworld、Zworld?

标签: opencv kinect camera-calibration calibration


【解决方案1】:

首先要了解如何计算它,如果您阅读一些有关针孔相机模型和简单透视投影的内容,将会对您有所帮助。如需快速浏览,请查看this。我会尝试更新更多内容。

所以,让我们从描述相机工作原理的相反开始:将世界坐标系中的 3d 点投影到图像中的 2d 点。根据相机型号:

P_screen = I * P_world

或(使用齐次坐标)

| x_screen | = I * | x_world |
| y_screen |       | y_world |
|    1     |       | z_world |
                   |    1    |

在哪里

I = | f_x    0    c_x    0 | 
    |  0    f_y   c_y    0 |
    |  0     0     1     0 |

是 3x4 内在矩阵,f 是焦点,c 是投影中心。

如果你解决了上面的系统,你会得到:

x_screen = (x_world/z_world)*f_x + c_x
y_screen = (y_world/z_world)*f_y + c_y

但是,你想做相反的事情,所以你的答案是:

x_world = (x_screen - c_x) * z_world / f_x
y_world = (y_screen - c_y) * z_world / f_y

z_world 是 Kinect 返回给您的深度,您从内在校准中知道 f 和 c,因此对于每个像素,您应用上述内容来获取实际的世界坐标。

编辑1(为什么上面对应世界坐标以及我们在校准过程中得到的外在坐标是什么):

首先,检查this one,它很好地解释了各种坐标系。

您的 3d 坐标系是:对象 ---> 世界 ---> 相机。有一个转换将您从对象坐标系带到世界,另一个将您从世界带到相机(您所指的外在因素)。通常你会假设:

  • Object 系统与 World 系统对应,
  • 或者,Camera 系统对应于 World 系统

1.使用 Kinect 捕捉对象时

当您使用 Kinect 捕捉物体时,传感器返回给您的是与相机的距离。这意味着 z 坐标已经在相机坐标中。通过使用上述等式转换 x 和 y,您可以得到 相机坐标 中的点。

现在,世界坐标系由您定义。一种常见的方法是假设相机位于世界坐标系的 (0,0,0) 处。因此,在这种情况下,外部矩阵实际上对应于单位矩阵,而您找到的相机坐标对应于 世界坐标

旁注: 因为 Kinect 返回的是相机坐标中的 z,所以也不需要从物体坐标系到世界坐标系的转换。例如,假设您有一个不同的相机来捕捉面部,并且对于每个点,它都会返回与鼻子的距离(您认为它是对象坐标系的中心)。在这种情况下,由于返回的值将在对象坐标系中,我们确实需要一个旋转和平移矩阵来将它们带到相机坐标系中。

2。校准相机时

我想您正在使用具有各种姿势的校准板使用 OpenCV 校准相机。通常的方法是假设棋盘实际上是稳定的,并且相机正在移动而不是相反(两种情况下的变换是相同的)。 这意味着现在世界坐标系对应于对象坐标系。这样,对于每一帧,我们都会找到棋盘角并为其分配 3d 坐标,执行以下操作:

std::vector<cv::Point3f> objectCorners;

for (int i=0; i<noOfCornersInHeight; i++) 
{
    for (int j=0; j<noOfCornersInWidth; j++) 
    {
        objectCorners.push_back(cv::Point3f(float(i*squareSize),float(j*squareSize), 0.0f));
    }
} 

其中noOfCornersInWidthnoOfCornersInHeightsquareSize 取决于您的校准板。例如,如果 noOfCornersInWidth = 4、noOfCornersInHeight = 3 和 squareSize = 100,我们得到 3d 点

(0  ,0,0)  (0  ,100,0)  (0  ,200,0)    (0  ,300,0)
(100,0,0)  (100,100,0)  (100,200,0)    (100,300,0)
(200,0,0)  (200,100,0)  (200,200,0)    (200,300,0)

所以,这里我们的坐标实际上是在对象坐标系中。 (我们任意假设棋盘的左上角为(0,0,0),其余角的坐标均以此为准)。所以在这里我们确实需要旋转和变换矩阵来把我们从物体(世界)带到相机系统。这些是 OpenCV 为每一帧返回的外在参数。

总结一下Kinect案例:

  • 相机和世界坐标系统被认为是相同的,因此不需要外部因素。
  • 不需要对象到世界(相机)的转换,因为 Kinect 返回值已经在相机系统中。

编辑 2(在使用的坐标系上):

这是一个约定,我认为它还取决于您使用的驱动程序以及您返回的数据类型。检查例如thatthatthat one

旁注: 如果您将点云可视化并稍作练习,将会对您有很大帮助。您可以将您的点保存为 3d 对象格式(例如 plyobj),然后将其导入到类似 Meshlab 的程序中(非常易于使用)。

【讨论】:

  • 非常感谢。现在使用以下外部参数可以通过坐标世界中CAM的坐标吗?
  • 校准我有以下的外部参数(对于板的单个安装):1.7261576010447846e-01 3.1158880577193560e-01 1.2720406228471280e-02 -1.1592911113815259e + 02 -2.2406582979927950e + 02 8.1420941356557194e +02
  • 你在校准过程中发现了那些外在参数,对吧?当您使用 Kinect 进行捕获时,您是否在相同位置捕获相同的板?
  • 当我使用 kinect 进行捕获时,我使用相同的板但位置不同,然后我获得与使用的图像数量一样多的行(有 6 个值)。例如,我已经获得了这些外在参数(3用于旋转和翻译的3),用于棋盘的单一安装+02。
  • 我要问的是,那些是校准期间或捕获期间的外在因素(如果位置不同)?抱歉,我从您上面的评论中无法理解。
【解决方案2】:

编辑2(在使用的坐标系上):

这是一个约定,我认为它还取决于您使用的驱动程序以及您返回的数据类型。例如,检查那个,那个和那个。

例如,如果您使用 microsoft sdk: 那么 Z 不是到相机的距离,而是到相机的“平面”距离。这可能会更改相应的公式。

【讨论】:

    猜你喜欢
    • 2018-01-29
    • 2017-12-11
    • 1970-01-01
    • 2017-05-26
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 2014-12-26
    相关资源
    最近更新 更多