使用视差图进行距离测量

4

我曾经从事使用OpenCP和Python进行三维重建和距离测量的工作。我生成了左相机的视差图,然后使用以下公式来获取距离:

D=(f*b/disp)

其中f是焦距,b是两个相机之间的距离,disp是视差图矩阵。

我的问题是:

我得到的数字,它们是否应该是图片中每个点的距离?

使用此方法,我能获得的最大距离是多少(例如,在我的项目中,我得到的最大数字是110)?

img_L = cv2.pyrDown( cv2.imread(Li) )
img_R = cv2.pyrDown( cv2.imread(Ri) )
'''h, w = img_L.shape[:2]
diff=(6,6,6)
mask=np.zeros((h+2,w+2),np.uint8)
window_size = 3
min_disp = 16
num_disp = 112-min_disp
stereo = cv2.StereoSGBM(minDisparity = min_disp,
    numDisparities = num_disp,
    SADWindowSize = window_size,
    uniquenessRatio = 10,
    speckleWindowSize = 100,
    speckleRange = 32,
    disp12MaxDiff = 1,
    P1 = 8*3*window_size**2,
    P2 = 32*3*window_size**2,
    fullDP = False
)
print "computing disparity..."
disp = stereo.compute(img_L, img_R).astype(np.float32) / 16.0

print "generating 3d point cloud..."
h, w = img_L.shape[:2]
f = 0.8*w                          # guess for focal length
points = cv2.reprojectImageTo3D(disp, Mat)
colors = cv2.cvtColor(img_L, cv2.COLOR_BGR2RGB)
mask = disp > disp.min()
cv2.imshow('left', img_L)
disparity=(disp-min_disp)/num_disp
cv2.imshow('disparity',disparity )
b=6.50
D=b*f/disp
cv2.waitKey()
cv.DestroyAllWindows()
return D
1个回答

5
使用此公式得到的值D是您提供视差的每个点的深度。 深度距离是两个略微不同的概念。如果您使用相机的标准坐标系(即Z轴沿着光轴,X和Y轴在图像X和Y轴的方向上),那么3D点M = (X, Y, Z)与光心的距离为sqrt(X²+Y²+Z²),深度为Z。公式中的D是深度,而不是距离。
如果您想从深度值中检索3D点M = (X, Y, Z),则需要知道相机矩阵KM = D * inv(K) * [u; v; 1],其中(u, v)是该点的图像坐标。 编辑:关于您的第二个问题,您可以使用此方法获得的最大深度与最小视差有关(而不是最大视差,因为disp在分母上)。由于视差估计是量化的(逐像素完成),因此无法将深度估计到无穷大。

@ AldurDisciple 怎么会这样?!!!因为根据这个页面http://disparity.wikidot.com/ D是距离,如果按照你所说的,我应该使用哪个相机矩阵(因为我正在使用两个相机进行立体视觉),如何获取该点的图像坐标? - LaMorena
@user3433195 他们称之为“距离”,但实际上是深度。另外,为什么不使用 reprojectImageTo3D (链接)? - BConic
@AlderDisciple 我用了它,我在上面添加了代码。 - LaMorena
我也在尝试从深度图计算实际距离。想要确认如何获取Mat。为什么要将焦距乘以宽度?如何获取相机矩阵K:如上所述,M = D * inv(K) * [u; v; 1] 用于计算实际距离。 - Akash

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