立体图像深度图


基本问题:获取2D图像上的深度信息

我们使用相机进行场景拍摄的过程,是一种将三维空间映射到二维空间的过程,在该过程中我们可能会丢失一些信息,其中最重要的一点就是深度信息。 因此如何保留深度信息是一个值得思考的问题。解决方法很简单,我们可以模拟人眼的工作方式,使用两个摄像机,这种方法被称为立体视觉。


基本概念:对极几何

如果只是用一台摄像机我们不可能知道3D空间中的X点到图像平面的距离,因为OX连线上的每个点投影到图像平面上的点都是相同的。但是如果我们也考虑上右侧图像的话,直线OX上的点将投影到右侧图像上的不同位置。所以根据这两幅图像,我们就可以使用三角测量计算出3D空间中的点到摄像机的距离(深度)。这就是整个思路。


直线OX上的不同点投射到右侧图像上形成的线l′被称为与x点对应的极线。也就是说,我们可以在右侧图像中沿着这条极线找到x点。它可能在这条直线上某个位置(这意味着对两幅图像间匹配特征的二维搜索就转变成了沿着极线的一维搜索。 这不仅节省了大量的计算,还允许我们排除许多导致虚假匹配的点)。这被称为对极约束。与此相同,所有的点在其他图像中都有与之对应的极线。平面XOO'被称为对极平面。O和O'是摄像机的中心。从上面的示意图可以看出,右侧摄像机的中心O'投影到左侧图像平面的e点,这个点就被称为极点。极点就是摄像机中心连线与图像平面的交点。 因此点e'是左侧摄像机的极点。有些情况下,我们可能不会在图像中找到极点,它们可能落在了图像之外(这说明这两个摄像机不能拍摄到彼此,在本实验中便是如此)。


在下图中,p是空间一点,z是其深度,Ol和Or是左右两个相机,对应上述的O和O’。f是相机焦距。


通过相似三角形的公式有:


通过上面的公式,我们可以轻松地知道一个点的深度与x和x’的查成反比,从而得到图中所有点的深度图。

在OpenCV中的代码实现:

实验的目录如下:data0是暗环境下的拍摄,data1是正常环境下的拍摄,data2是亮环境下的拍摄。View0~6是相机依次右移的拍摄。

实验直接调用OpenCV库函数,通过调整 numDisparities 和 blockSize 的值,我们会得到更好的结果。实验代码如下:

numDisparities:即最大视差值与最小视差值之差, 窗口大小必须是16的整数倍,int 型

blockSize:匹配的块大小。它必须是> = 1的奇数。通常情况下,它应该在3~11的范围内。这里设置为大于11也可以,但必须为奇数。

实验结果分析:

首先单个数据集内对比:选取data2(亮光)

  1. 1. 在选取图片1,2,ND(numDisparities)=64,BS(blocksize)=13时,结果如下:
  2. 2. 若调小ND,如32,结果如下:
  3. 3. 选取图片1,3,参数与1相同,结果如下。
  4. 与1结果相比还是差了很多,这是因为图片1.3的差距更大,导致需要更高的ND才能匹配特征。

  5. 4. 若修改ND为128,效果变好了。
  6. 5. 调小BS的能提高匹配精度,但是同时也会将无关噪声引入;调高BS则降低深度图的效果。因此适当的BS能让最后的图像更美观,信息更完整。
  7. 下图依次为BS=7,13,33,99时的结果,可看见BS=7时噪声很多,而BS=99时整个画面已经模糊失真了。

  8. 6. 而图像的明暗度对图像处理的结果影响并不是很大,以下依次为data0,1,2的图1,2的处理结果:

本次实验直接调用了OpenCV库函数,实现比较方便,若要全过程自己敲函数,工程量较大,不过过程是类似的。

点此投币支持!!

联系方式

  • 850466469
  • wtd2018@mail.ustc.edu.cn

编程学习