如何判断图片中物体的(真实世界)距离?

17

我正在用C++构建一个识别程序,为了使其更加稳健,我需要能够找到图像中物体的距离。

比如说,我有一张距离一张8.5 x 11照片22.3英寸的图像。系统正确地识别出了该图片,并在一个尺寸为319像素乘以409像素的框中显示出来。
那么,将实际高度和宽度(AH和AW)与像素高度和宽度(PH和PW)联系起来以获得距离(D)的有效方法是什么?

我假设当我实际使用这个方程时,PH和PW将与D成反比例关系,而AH和AW是常数(因为所识别的物体总是用户可以指定宽度和高度的对象)。


7
这里涉及到更多的变量。使用的相机视角(焦距)是多少?图像中有效像素的数量和长宽比如何?图像是否被裁剪了?它是否处于锐利对焦状态?(改变对焦会稍微影响视角)。我相信根据视角、像素密度和距离可以得出一个公式。此外,请注意,当照片/物体靠近相机时,即使距离 D 有微小差别,也可能造成覆盖的像素数相对较大的差异。 - Raze
请注意,如果被拍摄的物体是8' x 11'的平面,则距离中心22'的相机将距离角落23'。说相机距离这样的物体22.3'远是超出现实精度的。 - MSalters
@MSalters:对我来说,将沿着相机轴的距离称为“距离”,并尽可能准确地测量它,这似乎是非常合理的。 - jilles de wit
唯一缺失的变量是视角。如果您知道这个变量,您可以使用我下面的答案来计算距离。 - jilles de wit
3个回答

5
我不知道你是否在某个时候更改了问题,但我的第一个答案对于你想要的内容来说相当复杂。你可能可以做一些更简单的事情。
1)长而复杂的解决方案(更普遍的问题)
首先,您需要知道物体的大小。
您可以查看计算机视觉算法。如果您知道对象(其尺寸和形状),则主要问题是姿态估计问题(即找到相机相对于对象的位置),从中可以找到距离。您可以查看[1] [2](例如,如果您感兴趣,可以找到其他文章),或搜索POSIT、SoftPOSIT。您可以将问题表述为优化问题:找到姿态以最小化实际图像与期望图像(给定估计姿态的对象的投影)之间的“差异”。这种差异通常是当前参数下每个图像点Ni和相应对象(3D)点Mi的投影P(Mi)之间的(平方)距离之和。
从中,您可以提取出距离。
为此,您需要校准相机(粗略地找到像素位置和视角之间的关系)。

现在你可能不想亲自编写所有内容,你可以使用计算机视觉库,如OpenCV、Gandalf [3]等。

现在你可能想做一些更简单(并且近似)的事情。如果你能找到两个在相同“深度”(Z)下距离摄像机的点之间的图像距离,你可以将图像距离d与实际距离D联系起来:d = a D/Z(其中a是与焦距相关的相机参数,可以使用相机校准找到像素数)

2)简短解决方案(适用于您的简单问题)

但这里是(简单、简短的)答案:如果你的图片在与“相机平面”平行的平面上(即完全面对相机),你可以使用:

PH = a AH / Z
PW = a AW / Z

其中Z是图片平面的深度,a是相机的内部参数。

参考针孔相机模型将图像坐标m=(u,v)与世界坐标M=(X,Y,Z)联系起来:

m   ~       K       M

[u]   [ au as u0 ] [X]
[v] ~ [    av v0 ] [Y]
[1]   [        1 ] [Z]

[u] = [ au as ] X/Z + u0
[v]   [    av ] Y/Z + v0

其中“~”表示“与...成比例”,K是相机内参矩阵。您需要进行相机标定以找到K参数。这里我假设au=av=a,as=0。
您可以从这些方程中恢复Z参数(或对两者取平均值)。请注意,Z参数不是物体距离(在物体的不同点上变化),而是物体深度(相机平面和物体平面之间的距离)。但我想这正是您想要的。
[1] 线性N点相机姿态确定,龙泉和钟丹兰
[2] 用于相机姿态确定的完整线性4点算法,Lihong Zhi和Jianliang Tang
[3] http://gandalf-library.sourceforge.net/

2
如果您知道现实世界中物体的大小和相机的视角,并假设您知道水平视角 alpha(*),图像的水平分辨率为 xres,则可以通过以下方式推导出位于图像中间、在图像中宽度为 xp 像素,在现实世界中宽度为 xw 米的物体距离 dw(您的三角学如何?):
# Distance in "pixel space" relates to dinstance in the real word 
# (we take half of xres, xw and xp because we use the half angle of view):
(xp/2)/dp = (xw/2)/dw 
dw = ((xw/2)/(xp/2))*dp = (xw/xp)*dp (1)

# we know xp and xw, we're looking for dw, so we need to calculate dp:
# we can do this because we know xres and alpha 
# (remember, tangent = oposite/adjacent):
tan(alpha) = (xres/2)/dp
dp = (xres/2)/tan(alpha) (2)

# combine (1) and (2):
dw = ((xw/xp)*(xres/2))/tan(alpha)
# pretty print:
dw = (xw*xres)/(xp*2*tan(alpha))

(*) alpha = 相机轴与图像中刚好可见的中间行最左点连线之间的角度。
变量链接: dw = D,xw = AW,xp = PW。

1

这可能不是一个完整的答案,但可以为您指明正确的方向。你见过NASA在太空图片上是如何做的吗?他们在图像上放置了许多小十字架。据我所知,这是他们获得物体深度和大小的公平想法的方式。解决方案可能是在图片中有一个您知道正确大小和深度的物体,然后相对于它计算其他物体的大小和深度。现在是时候进行一些研究了。如果NASA是这样做的,那么值得一试。

我必须说,这是我在stackoverflow上很长时间以来看到的最有趣的问题之一:D。我注意到您只附加了两个与此问题相关的标签。添加更多与图像相关的内容可能会更好地帮助您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接