一些相关概念
双目立体视觉(Binocular Stereo Vision是机器视觉的一种重要形式,它是基于视差原理并利用成像设备从不同的位置获取被测物体的两幅图像,通过计算图像对应点间的位置偏差,来获取物体三维几何信息的方法。
为什么双目相机才能得到深度?
下图从物理原理上展示了为什么单目相机不能测量深度值而双目可以的原因。我们看到红色线条上三个不同远近的黑色的点在下方相机上投影在同一个位置,因此单目相机无法分辨成的像到底是远的那个点还是近的那个点,但是它们在上方相机的投影却位于三个不同位置,因此通过两个相机的观察可以确定到底是哪一个点。
提到双目视觉就不得不提视差图:双目立体视觉融合两只眼睛获得的图像并观察它们之间的差别,使我们可以获得明显的深度感,建立特征间的对应关系,将同一空间物理点在不同图像中的映像点对应起来,这个差别,我们称作视差(Disparity)图像。
(对于视差的理解自己可以体验一下:将手指头放在离眼睛不同距离的位置,并轮换睁、闭左右眼,可以发现手指在不同距离的位置,视觉差也不同,且距离越近,视差越大。)
这里再解释一下视差:视差是指在两个摄像机图像之间的像素位置的差异。假设立体视觉相机中的左图像在位置(1,30)具有像素,并且相同的像素在右图像中的位置(4,30)存在,视差值或差值为(4-1)=3。视差值与深度成反比。
深度图:深度图像也叫距离影像,是指将从图像采集器到场景中各点的距离(深度)值作为像素值的图像。获取方法有:激光雷达深度成像法、计算机立体视觉成像、坐标测量机法、莫尔条纹法、结构光法。
点云:当一束激光照射到物体表面时,所反射的激光会携带方位、距离等信息。若将激光束按照某种轨迹进行扫描,便会边扫描边记录到反射的激光点信息,由于扫描极为精细,则能够得到大量的激光点,因而就可形成激光点云。
深度图与点云的区别: 深度图像经过坐标转换可以计算为点云数据;有规则及必要信息的点云数据可以反算为深度图像。 两者在一定条件下是可以相互转化的,之前的博客里,有使用PCL库实现过点云提取深度图,当然给出相机参数也是可以由深度图转为点云的。截图一个深度图:
所以深度与视差的关系如下
理想双目相机成像模型:假设左右两个相机位于同一平面(光轴平行),且相机参数(如焦距f)一致。那么深度值的推导原理和公式如下:(相似三角形)
理想情况下双目立体视觉相机深度值计算原理
根据上述推导,空间点P离相机的距离(深度)z=f∗b/dz=f*b/dz=f∗b/d,可以发现如果要计算深度zzz,必须要知道:
1)相机焦距fff,左右相机基线bbb。这些参数可以通过先验信息或者相机标定得到。
2)视差ddd,需要知道左相机的每个像素点(xl,yl)(x_l, y_l)(xl,yl)和右相机中对应点(xr,yr)(x_r, y_r)(xr,yr)的对应关系。这是双目视觉的核心问题。
接下来要用到上篇博客写到的极线约束
但是要注意:
上一篇通过实验发现平移拍摄时需要(两相机共面且光轴平行,参数相 同)非常理想,这个要求太高了。C1,C2不在同一直线上的情况非常常见。这时候就需要极线较正。
下图为非理性情况下的极线(缺点:进行逐点搜索效率非常低)
极线校正(分别通过对两张图片用单应矩阵变换得到):目的就是把两个不同方向的图像平面(下图中灰色平面)重新投影到同一个平面且光轴互相平行(下图中黄色平面),这样就可以用前面理想情况下的模型了,两个相机的极线也变成水平的了。
经过极线矫正后,左图中的像素点只需要沿着水平的极线方向搜索对应点就可以了。
从下图中可以看到三个点对应的视差
红色双箭头线段表示视差:越远的物体视差越小,越近的物体视差越大,这和我们的常识是一致的。
图片来自于相机原理
上面讲到的对于左图的一个点,沿着它在右图中水平极线方向寻找和它最匹配的像素点,说起来简单,实际操作起来却不容易。这是因为上述都是理想情况下的假设。实际进行像素点匹配的时候会发现问题:
1)实际上要保证两个相机完全共面且参数一致是非常困难的,而且计算过程中也会产生误差累积,因此对于左图的一个点,其在右图的对应点不一定恰好在极线上。但是应该是在极线附近,所以搜索范围需要适当放宽。
2)单个像素点进行比较鲁棒性很差,很容易受到光照变化和视角不同的影响。
上述问题的解决办法就是:使用窗口来进行匹配。
使用窗口进行匹配。对于左图中的一个像素点(左图中红色方框中心),在右图中从左到右用一个同尺寸的窗口内的像素和它计算相似程度,相似度的度量有很多种方法,比如 误差平方和法(Sum of Squared Differences,简称SSD),左右图中两个窗口越相似,SSD越小。SSD值最小的位置对应的像素点就是最佳的匹配结果。这里详细使用的是NCC方法进行实验。
归一化相关性,normalization cross-correlation,因此简称NCC
NCC,就是用于归一化待匹配目标之间的相关程度,注意这里比较的是原始像素。
通过在待匹配像素位置p(px,py)p(p_x,p_y)p(px,py)构建n∗nn*nn∗n邻域匹配窗口,与目标像素位置p′(px+d,py)p'(p_x+d,p_y)p′(px+d,py)同样构建邻域匹配窗口的方式建立目标函数来对匹配窗口进行度量相关性,注意这里构建相关窗口的前提是两帧图像之间已经校正到水平位置,即光心处于同一水平线上,此时极线是水平的,否则匹配过程只能在倾斜的极线方向上完成,这将消耗更多的计算资源。相关程度的度量方式由如下式子定义:
NCC(p,d)=∑(x,y)∈Wp(I1(x,y)−I1ˉ(px.py))∗(I2(x+d,y)−I2ˉ(px.py))∑(x,y)∈Wp(I1(x,y)−I1ˉ(px.py))2∗∑(x,y)∈Wp(I2(x+d,y)−I2ˉ(px+d.py))2NCC(p,d)=\frac{\sum\limits_{(x,y)∈W_p}(I_1(x,y)-\bar{I_1}(p_x.p_y))*(I_2(x+d,y)-\bar{I_2}(p_x.p_y))}{\sqrt{\sum\limits_{(x,y)∈W_p}(I_1(x,y)-\bar{I_1}(p_x.p_y))^2*\sum\limits_{(x,y)∈W_p}(I_2(x+d,y)-\bar{I_2}(p_x+d.p_y))^2}}NCC(p,d)=(x,y)∈Wp∑(I1(x,y)−I1ˉ(px.py))2∗(x,y)∈Wp∑(I2(x+d,y)−I2ˉ(px+d.py))2(x,y)∈Wp∑(I1(x,y)−I1ˉ(px.py))∗(I2(x+d,y)−I2ˉ(px.py))
其中:
NCC(p,d)(p,d)(p,d)得到的值范围在[−1,1][-1,1][−1,1]之间
WpW_pWp:匹配窗口
I1(x,y)I_1(x,y)I1(x,y):原始图像的像素值
I1ˉ\bar{I_1}I1ˉ:原始图像窗口内的像素均值
I2(x+d,y)I_2(x+d,y)I2(x+d,y):原始图像在目标图像上对应位置在x方向上偏移d后的像素值
I2ˉ(x+d,y)\bar{I_2}(x+d,y)I2ˉ(x+d,y):目标图像窗口内的像素均值
NCC=1:两幅图像匹配度非常高
NCC=-1:两幅图像完全不匹配
左边为图像I1I_1I1,右边为图像I2I_2I2。图像I1I_1I1,蓝色方框表示待匹配像素坐标(px,py)(px,py)(px,py),图像I2I_2I2蓝色方框表示坐标位置为(px,py)(px,py)(px,py),红色方框表示坐标位置(px+d,py)(px+d,py)(px+d,py)
通过上述匹配结果得到的视差ddd,然后就可以根据上面讲过的相似三角形原理反推出以左视图为参考系的深度图。
图片下载网址:图片
第一组:
下载了图片在三组不同光线下的左右
wid都等于9
小结:
第二组:
同样是图片在三组不同光线下的左右
但是这种组白色的物品很多,想看看色彩不好区分的时候实验的结果
图片大小不同,窗口wid=9,光线相同
1) 图片长为300
2)图片长为500
小结:
1)由于双目立体视觉法根据视觉特征进行图像匹配,所以对于缺乏视觉特征的场景(如天空、白墙、沙漠等)会出现匹配困难,导致匹配误差较大甚至匹配失败。这组的纹理挺丰富,但是物品之间的色差很小。这组也有做3组只有光线不同时候的实验,结果是光线带来的噪声影响比第一组小很多,所以NCC算法对于白色的抗噪声能力是不错的。
2)从实验结果可以看出当图片的大小改变时,结果会有影响,当图片尺寸更小的时候,结果更为准确,连最前方的白色鼠标位置都十分清晰,因为wid的值并没有改变,图片的增大,就想到于滤波尺寸的减小,所以跟下面的实验窗口的大小改变的效果是相同的。下面一起分析。
4.3 窗口大小不同,图片亮度相同wid=3
wid=9
wid=12
小结:
1)通过这组实验可以看出对于这幅图像来说,改变wid的值对于物品边缘点的影响都会更明显。从第一幅图到最后一幅图片是轮廓越来越清晰的。(但是我的分析是如果wid继续增大,轮廓反而会不明显了,因为滤波器模板的面积过大,将更多的细节滤过了) 2)wid值的本质是滤波器的模板大小,对于均值滤波器来说,经过滤波后图像的每一个像素的灰度值都是原图像中窗口值大小内的所有灰度值的均值。wid值越小,得到的像素值参考周围像素点的灰度值越多,所以得出的结果细节越多,色块的面积越小;当wid值越大,得到的像素值参考周围像素点的灰度值越少,得出的结果细节越少,色块的面积越大。 3)这里还观察发现,当同一平面或者同一物体上花纹较多的时,结果会非常混乱,因为NCC要化为灰度图像,所以色彩信息会有影响。总结:
匹配流程
采集图像:通过标定好的双目相机采集图像,当然也可以用两个单目相机来组合成双目相机。 极线校正:校正的目的是使两帧图像极线处于水平方向,或者说是使两帧图像的光心处于同一水平线上。通过校正极线可以方便后续的NCCNCCNCC操作。由标定得到的内参中畸变信息中可以对图像去除畸变。通过校正函数校正以后得到相机的矫正变换R和新的投影矩阵PPP,接下来是要对左右视图进行去畸变,并得到重映射矩阵。 特征匹配:这里便是我们利用NCCNCCNCC做匹配的步骤,匹配方法如上所述,右视图中与左视图待测像素同一水平线上相关性最高的即为最优匹配。完成匹配后,我们需要记录其视差ddd。 深度恢复:通过上述匹配结果得到的视差图ddd,我们可以很简单的利用相似三角形反推出以左视图为参考系的深度图。实验中遇到的问题:
1.
解决办法:
scipy版本过高,降到1.2.1版本
pip install scipy==1.2.1
2. 选择图片跨度过大,一直出不来结果
分析原因:
视差范围约束:
两台摄像机之间具有一定的距离,
在沿极线搜索时,搜索的范围应小于一定的阈值。
视差范围约束限制了搜索的范围。
解决办法:
一开始一直以为图片的左右跨度越大越好,导致一直无法做出结果。最后改为官网上跨度较小的图片,结果较为理想。