使用OpenCV从屏幕坐标计算世界坐标
我用OpenCV计算了相机的内部和外部参数。 现在,我想从屏幕坐标(u,v)计算世界坐标(x,y,z) 我是怎么做到的 注意:当我使用kinect时,我已经知道z坐标使用OpenCV从屏幕坐标计算世界坐标,opencv,kinect,camera-calibration,calibration,Opencv,Kinect,Camera Calibration,Calibration,我用OpenCV计算了相机的内部和外部参数。 现在,我想从屏幕坐标(u,v)计算世界坐标(x,y,z) 我是怎么做到的 注意:当我使用kinect时,我已经知道z坐标 非常感谢您的帮助。谢谢 首先要了解如何计算,如果您阅读一些关于针孔相机模型和简单透视投影的内容,这将对您有所帮助。要快速浏览,请查看。我会尝试更新更多 那么,让我们从描述相机工作原理的相反方向开始:将世界坐标系中的3d点投影到图像中的2d点。根据相机型号: p_屏幕=I*p_世界 或(使用齐次坐标) 在哪里 I = | f_x
非常感谢您的帮助。谢谢 首先要了解如何计算,如果您阅读一些关于针孔相机模型和简单透视投影的内容,这将对您有所帮助。要快速浏览,请查看。我会尝试更新更多 那么,让我们从描述相机工作原理的相反方向开始:将世界坐标系中的3d点投影到图像中的2d点。根据相机型号: p_屏幕=I*p_世界 或(使用齐次坐标) 在哪里
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(为什么上面的内容对应于世界坐标,以及我们在校准过程中得到的外部信息):
首先,检查,它很好地解释了各种坐标系
您的三维坐标系是:对象-->世界-->摄影机。有一个变换将您从对象坐标系带到世界,另一个变换将您从世界带到摄影机(您所指的外部)。通常您会假设:
- 要么对象系统对应于世界系统
- 或者,摄影机系统与世界系统相对应
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));
}
}
因此,这里我们的坐标实际上在对象坐标系中。(我们任意假设电路板的左上角为(0,0,0),其余角的坐标与该坐标一致)。因此,这里我们确实需要旋转和变换矩阵,将我们从对象(世界)带到相机系统。这些是OpenCV为每个帧返回的外部信息
总结一下Kinect的案例:
- 摄影机和世界坐标系被认为是相同的,因此不需要外部系统
- 不需要对象到世界(摄影机)转换,因为Kinect返回值已经在摄影机系统中李>
你是说你有Xscreen,Yscreen和Zworld?你想要Xworld,Yworld,Zworld?非常感谢。现在使用以下外部参数,我可以通过坐标世界中CAM的坐标吗?校准我有以下外部参数(对于单板安装):1.7261576010447846e-01 3.1158880577193560e-01 1.2720406228471280e-02-1.1592911113815259e+02-2.2406582979927950e+02 8.1420941356557194e+02您在校准期间找到了这些外部参数,对吗?使用Kinect进行捕获时,是否在同一位置捕获同一块板?使用Kinect进行捕获时,我使用同一块板,但位置不同,然后获得的行数(6个值)与使用的图像数相同。例如
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));
}
}
(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)