计算机视觉——立体视觉NCC法计算视差图

原理

归一化互相关NCC

NCC,顾名思义,就是用于归一化待匹配目标之间的相关程度,注意这里比较的是原始像素。通过在待匹配像素位置p(px,py)构建3*3邻域匹配窗口,与目标像素位置p’(px+d,py)同样构建邻域匹配窗口的方式建立目标函数来对匹配窗口进行度量相关性,注意这里构建相关窗口的前提是两帧图像之间已经校正到水平位置,即光心处于同一水平线上,此时极线是水平的,否则匹配过程只能在倾斜的极线方向上完成,这将消耗更多的计算资源。相关程度的度量方式由如下式子定义:
在这里插入图片描述
其中p点表示图像I1待匹配像素坐标(px,py),d表示在图像I2被查询像素位置在水平方向上与px的距离。

深度

图像中的一点距离拍摄的像平面的距离
双目视图通过略微移动相机拍摄两张左右的图片来呈现。图像中的目标离摄像机距离越近,左右拍摄时目标移动的幅度越大。

立体视觉

立体视觉是双眼观察景物能分辨物体远近形态的感觉。
立体视觉是计算机视觉领域的一个重要课题,它的目的在于重构场景的三维几何信息。立体视觉的研究具有重要的应用价值,其应用包括移动机器人的自主导航系统,航空及遥感测量,工业自动化系统等。

立体视觉目标

拍摄出左右两幅图像,左右图像略微平移。对每一个点计算视差,视差越大,在视差图中体现出来的越亮,即距离摄像机距离越近。

计算视差图步骤

  1. 将相机绑定在一个固定设备上,模拟人类双眼,以便于算出深度信息。
  2. 在绑定时,尽量使两个相机的主光轴平行,像平面在同一个平面上,xy坐标相互平行。因此对相机进行标定,并校正。
  3. 找到两个图像之间的匹配点,通过光心与匹配点的分别连线,在空间中的交点就是实际物体的空间坐标,这个交点到光心连线(像平面)的垂直距离就是物体与摄像机的距离。
    在这里插入图片描述
  4. 计算每个点的视差大小。即求出点与点在左右图像中的坐标差了几个像素。
  5. 利用每个点的三维坐标,通过三角化,生成空间中的三维点。

测试图像

左图像

在这里插入图片描述

右图像

在这里插入图片描述

左图像

在这里插入图片描述

右图像

在这里插入图片描述

运行结果及分析

窗口值为3

在这里插入图片描述

窗口值为6

在这里插入图片描述

窗口值为9

在这里插入图片描述

窗口值为11

在这里插入图片描述

窗口值为100

在这里插入图片描述

分析

前面在原理中我们提到,视差越大,在视差图中体现出来的越亮,即距离摄像机距离越近。先用目测对图像中的几个比较大的目标进行一下距离排序(由近及远):台灯–人头和箱子–桌子上的两摞罐头和桌子–黑色架子–书架黑板墙面等。
我们从物体平滑部分和物体边缘部分的效果变化分析窗口值不同的各个结果图。当窗口值较小时(窗口值为3),对物体平滑的地方处理的比较糟糕,体现在视差图混乱,有较多亮点(白点),比如说在平滑的桌子上就有所体现。尽管如此,物体的边缘部分,比如说人头和箱子的轮廓,台灯的轮廓,还是有比较清晰的体现出来,但是如果说是离摄像机距离比较远的黑色架子,罐头等,边缘还是有点模糊。当窗口值较大(窗口值为11)时,可以看到,整张视差图层次比较清晰,也就是说,目标物体与摄像机的距离体现的比较清晰,可以比利用较小窗口值处理出来的视差效果更好的表达2.5维的信息。我们看到,离摄像机比较近的人头和台灯,他们上面平滑的部分处理的很稳定,在人头脸上的鼻子和头发这两个深度有渐变的部分(因为是面朝前的立体人头,鼻子肯定比头发更近摄像机一些,但也近的不多,所以我认为他是深度有渐变的部分),利用较大的窗口值处理出来的效果比较明显。同时,在离摄像机较远的黑色架子、罐头等的边缘部分也比利用较小窗口值处理出来的更清晰。当窗口值过大(窗口值为100)时,所有物体的边缘都模糊了,看不出目标物体原来的形状了!

窗口值为3

在这里插入图片描述

窗口值为6

在这里插入图片描述

窗口值为9

在这里插入图片描述

窗口值为11

在这里插入图片描述

窗口值为100

在这里插入图片描述

分析

从原图像就可以看出,这一组测试图像的颜色比较少,有一些颜色,例如说白色,通过目测看出离摄像机近处也有,离摄像机远处的也有,这就有可能造成对匹配点的困扰,有可能在前面的白色物体会匹配到在后面的白色物体上,这样可能就会导致视差计算的误差。因此,在视差图的呈现上,也可以这一组测试图像呈现出来的效果是比上一组更混乱的。但是在窗口值过大(窗口值为100)的情况下,也是看不出边缘的效果。当窗口值为6的时候,图片下方的几本书的边缘比较清楚。但是所有的平滑部分的处理效果都很不理想,我猜可能是与匹配的准确度有关,因为颜色相近,场景单一,导致匹配误差,因而视差图的效果也不好了。

遇到的问题

NameError: name ‘filters’ is not defined

翻书得知,ndimage.filters 模块中的 uniform_filter() 函数可以在一个矩形
图像块中计算相加,推测filters是在scipy.ndimage包中。导入scipy.ndimage包,就可以正常运行。

NameError: name ‘roll’ is not defined、NameError: name ‘argmax’ is not defined

翻书得知,roll() 函数是用来平移一幅图像;因为 uniform_filter() 函数的输入参数为数组,我们需要创建用于保存滤波结果的一些数组。使用 argmax() 函数找到对于每个像素的最佳深度。根据roll函数后面进行的数字运算,argmax函数用以操作数组,推测这两个函数都在numpy包中。导入numpy包,就可以正常运行。

总结

通过此次实验,我学习到了如何利用NCC法计算视差图,从而在2维图像的基础上表达出有关距离深度的信息,即表达2.5维的信息。从实验结果来看,在第一组图中,窗口值越大,表达的2.5维信息就越准确。但是窗口值过大,比如实验的值100,会导致边缘非常模糊,甚至可以说完全看不出原来的样子。所以过大的窗口值明显也是不可取的。比较小的窗口值对于距离比较近的物体的边缘值处理的效果比较好,可以清晰的看出物体的形状,但是平滑部分处理不好。因此在选择窗口值时,可以根据自己的实际需求,是更关注边缘信息还是平滑部分的细节信息,来选择合适的窗口值。对于第二组测试图像,由于图像本身的性质(颜色相近,场景单一)导致不管如何取窗口值,其结果都不理想,这时候应该考虑检查图像与图像之间匹配的关系,减小匹配误差。