首先要了解如何计算它,如果您阅读一些有关针孔相机模型和简单透视投影的内容,将会对您有所帮助。如需快速浏览,请查看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));
}
}
其中noOfCornersInWidth、noOfCornersInHeight 和squareSize 取决于您的校准板。例如,如果 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(在使用的坐标系上):
这是一个约定,我认为它还取决于您使用的驱动程序以及您返回的数据类型。检查例如that、that 和that one。
旁注: 如果您将点云可视化并稍作练习,将会对您有很大帮助。您可以将您的点保存为 3d 对象格式(例如 ply 或 obj),然后将其导入到类似 Meshlab 的程序中(非常易于使用)。