使用静态场景中的单个摄像机测量到物体的距离

时间:2016-12-12 13:55:56

标签: image-processing computer-vision

让我们说我在房间内的平地上放置一个小物件。

  • 第一步:从世界坐标系中的已知静态位置拍摄房间地板的照片。
  • 第二步:检测图像中对象的下边缘,并将像素坐标映射到世界坐标系中的对象位置。
  • 第三步:使用卷尺测量与物体的实际距离。

我可以移动小物体,为每个像素坐标重复这三个步骤并创建一个查找表(键:像素坐标;值:距离)。这个程序对我的用例来说足够准确。我知道如果有多个对象(一个对象可以覆盖另一个对象)会有问题。

我的问题:是否有更简单的方法来创建此查找表?意外地将摄像机角度改变几度会破坏艰苦的工作。 ;)

也许可以对世界坐标系中的几个特定像素坐标或位置执行三个步骤,并执行一些"校准"用计算出的参数计算距离?

4 个答案:

答案 0 :(得分:6)

如果地板是平的,那么它的等式就是一个平面,让

a.x + b.y + c.z = 1
摄像机坐标中

(原点是摄像机的光学中心,XY形成焦平面,Z形成观察方向)。

然后,从相机中心到像素坐标(u, v)处的图像上的点的光线由

给出
(u, v, f).t

其中f是焦距。

光线在

时撞击飞机
(a.u + b.v + c.f) t = 1, 

即。在那一点

(u, v, f) / (a.u + b.v + c.f)

最后,从相机到该点的距离是

p = √(u² + v² + f²) / (a.u + b.v + c.f)

这是您需要制表的功能。假设已知f,您可以通过取三个非对齐点来测量未知系数abc,测量图像坐标(u, v)和距离,并解决3x3线性方程组。

从最后一个等式中,您可以估算出图像任意点的距离。

可以通过在已知距离处观察已知尺寸的目标来测量焦距(以像素为单位)。按比例,在图像长度上,距离与尺寸的比率为f

答案 1 :(得分:2)

大多数视觉库(包括opencv)都内置了一些函数,这些函数将从相机参考帧和笛卡尔平面的相关点中获取几个点,并为您生成扭曲矩阵(仿射变换)。 (有些看上去足够包含具有足够输入点的非线性映射,但这会让你回到校准问题的时间)

最后一点:大多数视觉库使用某种类型的网格来校准,即棋盘图案。如果您编写校准以处理这样的工作表,那么您只需要测量到1个目标对象的距离,因为工作表将计算转换,而目标只会提供世界偏移。

答案 2 :(得分:2)

我相信你所追求的是一种投射转换。以下链接应指导您完全满足您的需求。

Demonstration of calculating a projective transformation在Math SE上进行适当的数学排版。

虽然您可以手动解决这个问题并将其写入您的代码中...我强烈建议您使用矩阵数学库,甚至编写自己的矩阵数学函数,然后再手动计算方程式,因为您必须解决它们象征性地把它变成代码,这将是非常广泛的,容易被误算。

以下是一些可以帮助您澄清的提示(将其应用于您的问题):

-Your矩阵(源)是根据相机图像中的4个xy点(像素位置)构建的。

- 您的B矩阵(目的地)是根据您在现实世界中的测量结果建立的。

- 为了快速重新校准,我建议在地面上标记点,以便能够快速将立方体放置在4个位置(并随后获得相机中更改的像素位置),而无需重新测量。

- 您只需要在校准期间执行步骤1-5(一次),之后只要您想知道某物的位置,只需获取图像中的坐标,然后通过步骤6和步骤7运行它们。

- 您希望您的校准点尽可能远离彼此(在合理范围内,因为在消失点情况下的极端距离,您开始迅速失去像素密度,因此源图像精度)。确保没有3个点是共线的(简单地说,在现实世界中几乎在你的相机fov的整个范围内使你的4点近似正方形)

ps我很抱歉没有在这里写出来,但他们有精彩的数学编辑,看起来更干净!

将此方法应用于此情况的最后步骤:

为了执行此校准,您必须设置全局原位(可能最容易在地板上任意执行此操作并测量相对于该点的相机位置)。从这个位置开始,您需要在地板的x和y坐标上测量物体与该位置的距离。虽然更紧凑的校准装置会给你带来更多的错误,但最简单的解决办法可能只是制作尺寸标注的纸张(我正在考虑打印纸或大板或其他东西)。这将更容易的原因是它将内置轴(即两个边将是正交的,您将只使用对象的四个角并在校准中使用固定距离)。 EX:对于一张纸你的分数是(0,0),(0,8.5),(11,8.5),(11,0)

因此,使用这些点和你得到的像素将创建你的变换矩阵,但这仍然只是给你一个很难测量的轴上的全局x,y位置(它们可能是偏斜的,取决于你的测量方式/校准)。因此,您需要计算相机偏移量:

现实世界中的对象(来自上面的步骤):x1,y1 相机坐标(Xc,Yc)

dist = sqrt(pow(x1-Xc,2)+ pow(y1-Yc,2))

如果尝试用手从全局原点测量相机的位置太麻烦,您可以改为测量到2个不同点的距离,并将这些值输入上面的等式来计算相机偏移,你会然后在你想要获得最终距离的任何时候存储和使用。

答案 3 :(得分:1)

正如之前的答案中已经提到的,你需要一个投射变换或简单的单应性。但是,我会从一个更实际的角度考虑它,并试图总结它简短。

所以,考虑到正确的单应性,你可以扭曲你的飞机图像,使它看起来像你从上面拿走它(如here)。更简单的是,您可以将图像的像素坐标转换为平面的世界坐标(在每个像素的变形期间也是如此)。

单应性基本上是一个3x3矩阵,您可以通过将其与矩阵相乘来变换坐标。您现在可以考虑等待3x3矩阵和2D坐标:您需要使用homogeneous coordinates

但是,大多数框架和库都会为您执行此操作。您需要做的是在您的世界平面/地板上找到(至少)四个点(x / y坐标)(最好是矩形的角,与您想要的世界坐标系对齐),拍摄它们的照片,测量像素坐标并将两者传递到所需计算机视觉或数学库的“查找 - 单应函数”。

在OpenCV中findHomographyexample(方法perspectiveTransform然后执行实际转换)。

在Matlab中,您可以使用here中的内容。确保使用投影变换作为变换类型。结果是一个投影tform,可以与this方法结合使用,以便将您的点从一个坐标系转换为另一个坐标系。

为了转换到另一个方向,你只需要反转你的单应性并改用结果。