转载请说明出处:http://blog.csdn.net/zhubaohua_bupt/article/details/51866567算法
这段时间对opencvSGBM半全局立体匹配算法进行了比较细致的研究,现总结一下。函数
本文先描述一下opencvSGBM算法流程,接着给出调用opencvSGBM须要设置参数的含义、数值选取以及运行效果,最后贴出opencvSGBM源码。测试
第一部分:SGBM算法研究总结:ui
整个算法实现分为spa
1预处理.net
2代价计算blog
3动态规划(默认4条路径)源码
4后处理it
这四个步骤。下面分别说明一下各个步骤:io
Step1:SGBM采用水平Sobel算子,把图像作处理,公式为:
Sobel(x,y)=2[P(x+1,y)-P(x-1,y)]+ P(x+1,y-1)-P(x-1,y-1)+ P(x+1,y+1)-P(x-1,y+1)
Step2:用一个函数将通过水平Sobel算子处理后的图像上每一个像素点(P表示其像素值
)映射成一个新的图像:PNEW表示新图像上的像素值。
映射函数:
preFilterCap 为一个常数参数,opencv缺省状况下取15,例程中取63。
预处理其实是获得图像的梯度信息。
经预处理的图像保存起来,将会用于计算代价
代价有两部分组成:
1通过预处理获得的图像的梯度信息通过基于采样的方法获得的梯度代价
2原图像通过基于采样的方法获得的SAD代价
上述两个代价都会在SAD窗口内进行计算。
关于什么是基于采样的方法,参考论文:DepthDiscontinuities by Pixel-to-Pixel Stereo 在计算代价的时候,用基于采样的方法效果会好一些。
规划公式:
默认4条路径,其中动态规划很重要两个参数P1,P2是这样设定的:
P1 =8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
cn是图像的通道数, SADWindowSize是SAD窗口大小,数值为奇数。
能够看出,当图像通道和SAD窗口肯定下来,SGBM的规划参数P1和P2是常数。
opencvSGBM的后处理包含如下几个步骤:
Step1:惟一性检测:视差窗口范围内最低代价是次低代价的(1 + uniquenessRatio/100)倍时,最低代价对应的视差值才是该像素点的视差,不然该像素点的视差为0。其中uniquenessRatio是一个常数参数。
Step2:亚像素插值:
插值公式:
Step3:左右一致性检测:偏差阈值disp12MaxDiff默认为1,能够本身设置。
OpencvSGBM计算右视差图的方式:
经过获得的左视察图计算右视差图
图1经过获得的左视察图计算右视差图
这个时候dispR[X-d]是d仍是d+n?
实际上,dispR[X-d]的肯定方式是比较dispL中X和X+n出的最小代价,选代价最小的对应的视差做为最优视差。
肯定右图视差后,经过这样一个措施来肯定左视察图中的像素视差是否有效:
| dispR[X-d]-dispL[X]|<disp12MaxDiff&&| dispR[X-d-1]- dispL[X]-1|<disp12MaxDiff (条件1)
若是这个条件成立,就是误匹配点。
这个条件成立,为何就是误匹配点呢?
实际上这个条件(LRcheck)检测的大都是遮挡点,好比图1中,左视差图X和X+n处按照图一规则都会映射到右视差图的X-d处,若在左视差图中,X位置是遮挡点,那么左视差图X位置的最小代价必定会比X+n处大(由于X处根本找不到匹配,所谓最小代价也是很大的),这样dispR[X-d]=d+n。
如今开始用条件1来检测左视差图的误匹配点。
先解释一下条件1左侧的条件:检测到X处(遮挡误匹配点),发现dispR[x-d]=d+n,并非d。所以就会符合条件1中的dispR[X-d]-dispL[X]|<disp12MaxDiff,
亲测把条件1变成dispR[X-d]-dispL[X]|<disp12MaxDiff检测效果和条件1几乎无差异。
再解释一下条件1右侧的条件:
条件1的另外一部分(| dispR[X-d-1]-dispL[X]-1|<disp12MaxDiff)是用来检测右视差图在X-d处的视差值是否连续,若是左视差图X处是遮挡误匹配点,那么dispL[X]中的d是不许确的,所以dispR[X-d]=d也是不许确的,即不能保证dispR[X-d-1]处视差值和d很相近,故右视差图在X-d处的视差值是不连续的。
综上,在左视察图中,若是一个像素点是遮挡误匹配点,那么就会符合条件1。于是就会被检测出来。
Step4:连通区域的检测:简述:对左右一致性检测后的视差图再一次检测误匹配点,根据与当前处理的视差点知足连通条件的像素点个数来判断当前处理的视差点是不是误匹配点,个数小于一个阈值就认为是误匹配点。
方法:循环遍历每个像素点,对每个视差像素点d而言,检测其周围(上下左右)的视差是否知足这样的条件(称为视差连通条件):
1, 首先是LRcheck后,视差有效的点
2, 和中心视差值的(变化)绝对值不超过speckleRange。注:speckleRange是一个常数参数,能够本身设定。Opencv例程中speckleRange=10.
对于一个视差点:
Step1:当上下左右(如下简称周围)点至少有一个视差点知足视差连通条件后,再分别以它们为起点(称为传播),检测其周围(前向传播的点不算,好比,Pixel2是经过Pixel1传播过来的,即Pixel2确定是Pixel1周围的点。再以Pixel2为起点检测周围的视差点是否知足视差连通条件时,Pixel1虽然也是Pixel2周围的视差点,但不算知足视差连通条件)的视差点是否知足视差连通条件。
Step2:每检测到一个新的连通点,其相应点的标志位置1,,计数器加一,直到对于每个新的连通点,其周围的点(标志位置1的点也不算知足视差连通条件)都不知足视差连通条件。中止计数。
Step3:判断计数值(即和当前处理的视差点的连通区域的像素点个数)>speckleWindowSize?(注:speckleWindowSize是一个常数参数,能够本身设定。Opencv例程中speckleRange=100。)若大于,视差值认为有效,不然认为当前视差值是噪点。
连通区域检测有助于去除经LR和惟一性检测后残余的噪点,效果比较理想。
第二部分:opencvSGBM算法的参数含义及数值选取
一 预处理参数
1:preFilterCap:水平sobel预处理后,映射滤波器大小。默认为15
int ftzero =max(params.preFilterCap, 15) | 1;
opencv测试例程test_stereomatching.cpp中取63。
二 代价参数
2:SADWindowSize:计算代价步骤中SAD窗口的大小。由源码得,此窗口默认大小为5。
SADWindowSize.width= SADWindowSize.height = params.SADWindowSize > 0 ?params.SADWindowSize : 5;
注:窗口大小应为奇数,通常应在3x3到21x21之间。
3:minDisparity:最小视差,默认为0。此参数决定左图中的像素点在右图匹配搜索的起点。int 类型
4:numberOfDisparities:视差搜索范围,其值必须为16的整数倍(CV_Assert( D % 16 == 0 );)。最大搜索边界= numberOfDisparities+ minDisparity。int 类型
三 动态规划参数
动态规划有两个参数,分别是P一、P2,它们控制视差变化平滑性的参数。P一、P2的值越大,视差越平滑。P1是相邻像素点视差增/减 1 时的惩罚系数;P2是相邻像素点视差变化值大于1时的惩罚系数。P2必须大于P1。须要指出,在动态规划时,P1和P2都是常数。
5:opencv测试例程test_stereomatching.cpp中,P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
6:opencv测试例程test_stereomatching.cpp中,P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
四:后处理参数
7:uniquenessRatio:惟一性检测参数。对于左图匹配像素点来讲,先定义在numberOfDisparities搜索区间内的最低代价为mincost,次低代价为secdmincost。若是知足
即说明最低代价和次第代价相差过小,也就是匹配的区分度不够,就认为当前匹配像素点是误匹配的。
opencv测试例程test_stereomatching.cpp中,uniquenessRatio=10。int 类型
8:disp12MaxDiff:左右一致性检测最大允许偏差阈值。int 类型
opencv测试例程test_stereomatching.cpp中,disp12MaxDiff =1。
9:speckleWindowSize:视差连通区域像素点个数的大小。对于每个视差点,当其连通区域的像素点个数小于speckleWindowSize时,认为该视差值无效,是噪点。
opencv测试例程test_stereomatching.cpp中,speckleWindowSize=100。
10:speckleRange:视差连通条件,在计算一个视差点的连通区域时,当下一个像素点视差变化绝对值大于speckleRange就认为下一个视差像素点和当前视差像素点是不连通的。
opencv测试例程test_stereomatching.cpp中,speckleWindowSize=10。
运行效果:
源码见opencvSGBM半全局立体匹配算法的研究(2)