OpenCV46: 立体图像的深度图|Depth Map

目标

在本节中,将学习

  • 根据立体图像创建深度图

基础

在上一节中,看到了对极约束和其他相关术语等基本概念。如果有两个场景相同的图像,则可以通过直观的方式从中获取深度信息。下面是一张图片和一些简单的数学公式证明了这种想法。

stereo_depth.jpg

上图包含等效三角形。编写它们的等式将产生以下结果:

d i s p a r i t y = x x = B f Z disparity = x - x' = \frac{Bf}{Z}

x x x x' 是图像平面中与场景点3D相对应的点与其相机中心之间的距离。 B B 是两个摄像机之间的距离(已知), f f 是摄像机的焦距(已知)。简而言之,上述方程式表示场景中某个点的深度与相应图像点及其相机中心的距离差成反比。因此,利用此信息,可以得出图像中所有像素的深度。

因此,可以在两个图像之间先找到对应的匹配项。一旦找到匹配项,就能获得深度(disparity)。

代码

下面的代码片段显示创建视差图的简单过程。

import cv2
import numpy as np
from matplotlib import pyplot as plt

imgL = cv2.imread('tsukuba_l.png', 0)
imgR = cv2.imread('tsukuba_r.png', 0)

stereo = cv2.StereoBM_create(numDisparities=16, blockSize=15)
disparity = stereo.compute(imgL, imgR)
plt.subplot(131)
plt.imshow(imgL, 'gray')
plt.title('imgL')
plt.xticks([])
plt.yticks([])
plt.subplot(132)
plt.imshow(imgR, 'gray')
plt.title('imgR')
plt.xticks([])
plt.yticks([])
plt.subplot(133)
plt.imshow(disparity, 'gray')
plt.title('disparity')
plt.xticks([])
plt.yticks([])

plt.show()
复制代码

下面的图像包含原始图像(左)及其视差图(右)。如图所见,结果受到高度噪声的污染。通过

调整numDisparitiesblockSize的值,可以获得更好的结果。

在这里插入图片描述

当熟悉StereoBM后,可以微调一些参数以获得更好、更平滑的结果。部分参数如下所示:

  • texture_threshold:过滤出没有足够纹理的区域以获得可靠匹配的区域

  • Speckle range 和 size:基于块的匹配器通常会在对象边界附近产生“斑点”,其中匹配窗口捕获一侧的前景和在另一场景中的背景,在此场景中,匹配器还在桌子上找到的小片虚假匹配。要摆脱这些问题,可以使用speckle_sizespeckle_range参数来控制后处理的深度图像。speckle_size是视差斑点下的像素数,speckle_range控制必须被视为相同斑点的一部分最近距离

  • Number of disparities:滑动窗口的像素数。越大表明可见深度的范围就越大,但是需要更多的计算代价,最大视差值与最小视差值之差, 窗口大小必须是16的整数倍,int 型

  • min_disparity:从开始搜索的左像素的x位置开始的偏移量

  • uniqueness_ratio:另一个后过滤步骤。如果最佳匹配视差不足够好于搜索范围中的所有其他视差,则将像素滤出。如果texture_threshold和斑点过滤仍在通过虚假匹配,则可以尝试进行调整

  • prefilter_size和prefilter_cap:预过滤阶段,可标准化图像亮度并增强纹理,以准备块匹配。通常,不需要调整这些参数

附加资源

猜你喜欢

转载自juejin.im/post/7229330390232809530