使用立体相机与物体的距离

时间:2011-06-05 07:45:12

标签: opencv camera distance stereo-3d stereoscopy

有没有办法用立体相机计算到特定物体的距离? 是否存在使用视差或角度来获得距离的等式或其他东西?

3 个答案:

答案 0 :(得分:34)

注意:此处描述的所有内容都可以在相关校准和立体视觉章节的学习OpenCV一书中找到。您应该阅读这些章节以更好地理解以下步骤。

一种不要求您自己测量所有相机内在函数和外在函数的方法是使用openCVs校准函数。相机内在函数(镜头失真/歪斜等)可以使用cv :: calibrateCamera计算,而extrinsics(左右相机之间的关系)可以使用cv :: stereoCalibrate计算。这些函数在像素坐标中采用多个点并尝试将它们映射到现实世界对象坐标。 CV有一个简洁的方法来获得这些点,打印出一个黑白棋盘并使用cv :: findChessboardCorners / cv :: cornerSubPix函数来提取它们。大约10-15个图像对的棋盘应该做。

校准功能计算的矩阵可以保存到光盘中,因此每次启动应用程序时都不必重复此过程。你可以在这里获得一些整洁的矩阵,允许你创建一个整流图(cv :: stereoRectify / cv :: initUndistortRectifyMap),以后可以使用cv :: remap将其应用于你的图像。你还得到一个称为Q的整齐矩阵,它是一个差异到深度的矩阵。

纠正图像的原因是,一旦完成一对图像的处理(假设校准正确),可以在同一行中找到一个图像中的每个像素/对象在另一张图片中。

根据您在图像中寻找的功能类型,您可以从这里开始使用几种方法。一种方法是使用CV立体声对应函数,例如立体块匹配或半全局块匹配。这将为您提供整个图像的视差图,可以使用Q矩阵(cv :: reprojectImageTo3D)将其转换为3D点。

这种情况的失败是,除非图像中有很多纹理信息,否则CV在构建密集视差图时并不是非常擅长(你会在它找不到正确差异的地方找到差距)给定像素),所以另一种方法是找到你想要匹配的点。假设您在左侧图像中找到x = 40,y = 110的特征/对象,在右图像中找到x = 22(因为图像已被纠正,它们应具有相同的y值)。差异计算为d = 40-22 = 18。

构造一个cv :: Point3f(x,y,d),在我们的例子中(40,110,18)。以相同的方式查找其他有趣的点,然后将所有点发送到cv :: perspectiveTransform(使用Q矩阵作为变换矩阵,本质上此函数是cv :: reprojectImageTo3D但是对于稀疏视差图)并且输出将是点XYZ坐标系,左侧摄像头位于中心位置。

答案 1 :(得分:6)

我还在努力,所以我不会发布完整的源代码。但我会给你一个概念性的解决方案。

您需要以下数据作为输入(对于两个相机):

  • 相机位置
  • 相机感兴趣点(相机正在寻找的点)
  • 相机分辨率(水平和垂直)
  • 相机视角(水平和垂直)

您可以自己测量最后一张,将相机放在一张纸上并绘制两条线并测量这些线之间的角度。

相机不必以任何方式对齐,您只需要能够在两个相机中看到您的物体。

现在计算从每个相机到物体的矢量。你有来自每个相机的物体的(X,Y)像素坐标,你需要计算一个矢量(X,Y,Z)。请注意,在简单的情况下,在相机中间可以看到对象,解决方案就是(camera.PointOfInterest - camera.Position)。

一旦你有两个向量指向你的目标,这些向量定义的线应该在理想世界的一个点上交叉。在现实世界中,他们不会因为测量误差小和相机分辨率有限。因此,请使用下面的链接计算两条线之间的距离矢量。

Distance between two lines

在该链接中:P0是您的第一个凸轮位置,Q0是您的第二个凸轮位置,u和v是从摄像机位置开始并指向目标的矢量。

你对实际距离不感兴趣,他们想要计算。你需要向量Wc - 我们可以假设对象在Wc的中间。一旦你在3D空间中拥有物体的位置,你也可以得到你想要的任何距离。

我会尽快发布完整的源代码。

答案 2 :(得分:2)

我有用于检测人脸的源代码,不仅返回深度,还返回真实世界坐标,左相机(或右相机,我记不起)是原点。它改编自“学习OpenCV”的源代码,并参考一些网站以使其正常工作。结果通常非常准确。