双目相机立体匹配算法BM和SGBM

立体匹配——在两个不同摄像机视图中匹配一个三维点——只能在两个摄像机视图重叠的可视区域进行计算,OpenCV实现了两种立体匹配算法,并且它们共享通用的对象接口。首先是快匹配算法(block matching,BM),它使用小的 “绝对值之差的和” (SAD)窗口来寻找左右立体校正图像之间的匹配点,更适合与强纹理图像;第二个是半全局块匹配算法(semi-global block matching,SGBM),为SGM的变形形式。
SGBM算法与BM算法的不同之处:
1.SGBM使用Birchfield-Tomasi度量[Birchfield99]在子像素水平上进行匹配。
2.SGBM视图基于所计算的深度信息来强制实现全局平滑约束。
这两种算法是互补的,BM计算稍快一些,但SGBM的可靠性和精确性更高一些。
使用BM算法和SGBM算法
这两个算法都需要调用create()函数获取一个智能指针指向cv::StereoBM对象 或者 cv::StereoSGBM对象,但在参数设置上是不相同的。
对于BM算法:静态create()函数有两个参数,numDisparitiesblockSize;numDisparities 视差搜索范围。对于每个像素算法将找到从0(默认最小视差)到numdifferences的最佳视差。然后可以通过改变最小视差来移动搜索范围。;blockSize 设置每个像素周围的区域大小,也会计算 “绝对差分符号” 度量。这个值越大找到的错误匹配越少。但是请注意,算法的计算成本不仅与窗口面积(即窗口大小的平方)相关,靠近不连续处(对象的边缘)将可能找不到匹配,结果是空白区域,因为在接近对象边缘处不存在视差。且窗口越大,空白区域的厚度越大;窗口越大,获得的深度图越模糊,意味着视差图中对象的剪影将越平滑,以一种近似的方式捕捉实际剪影。
create()函数的使用方法

Ptr<StereoBM> bm =StereoBM::create	(	
	int numDisparities = 0,
	int blockSize = 21 
)	

在调用create()函数创建BM算法的智能指针后,还可以通过一系列set*()函数进一步配置。可进一步配置的参数有:

参数名称 参数含义
numDisparities 最大视差与最小视差的差值,该值总是大于零,且必须能被16整除。
PreFilterCap 预滤波图像像素的截断值。该算法首先在每个像素处计算x导数,并按[-preFilterCap, preFilterCap]间隔剪辑其值。结果值被传递给Birchfield-Tomasi像素代价函数。
PreFilterSize 用于设置滤波器的窗口大小
PreFilterType 用于设置滤波器的类型
ROI1 与setROI2设置对矫正后的图像的裁剪区域
ROI2 与setROI1设置对矫正后的图像的裁剪区域
TextureThreshold 用于设置低纹理区域的判断阈值
UniquenessRatio 计算出的最佳(最小)成本函数值应该“赢得”第二个最佳值的百分比余量,从而认为找到的匹配是正确的。通常情况下,5-15范围内的值就足够了。

set*函数指的是“set”+“参数名称”+“()”,且*()*中写入该参数的取值,例如:setMinDisparity(0)
像如下这样进行进一步配置

bm->setROI1(validROIL);
bm->setROI2(validROIR);
bm->setPreFilterCap(31);
bm->setMinDisparity(0);
bm->setNumDisparities(numDisparities * 16 + 16);
bm->setTextureThreshold(10);
bm->setUniquenessRatio(uniquenessRatio);
bm->setSpeckleWindowSize(100);
bm->setSpeckleRange(32);
bm->setDisp12MaxDiff(-1);

对于SGBM算法
SGBM算法在利用create()函数创建cv::StereoSGBM对象的智能指针时,就设置了其用到的所有参数。在OpenCV StereoSGBM类中给出的create()函数声明是这样的:

static Ptr<StereoSGBM> cv::StereoSGBM::create(	
	int minDisparity = 0,
	int numDisparities = 16,
	int blockSize = 3,
	int P1 = 0,
	int P2 = 0,
	int disp12MaxDiff = 0,
	int preFilterCap = 0,
	int uniquenessRatio = 0,
	int speckleWindowSize = 0,
	int speckleRange = 0,
	int mode = StereoSGBM::MODE_SGBM 
)	

其中最后一个参数mode的取值是枚举的,可以直接输入对应的整型值,缺省值为0,即MODE_SGBM

enum
    {
        MODE_SGBM = 0,
        MODE_HH   = 1,
        MODE_SGBM_3WAY = 2
    };

各参数的含义如下表

参数名称 参数含义
minDisparity 最小可能的视差值。通常为零,但有时校正算法会使图像移位,因此需要对该参数进行相应调整
numDisparities 最大视差减去最小视差。该值总是大于零。在当前实现中,该参数必须能被16整除
blockSize 匹配的块大小。必须是奇数>=1。通常情况下,它应该在3…11范围
P1 控制视差平滑的第一个参数,P1是对相邻像素之间视差变化的加减1的惩罚,8*number_of_image_channels*SADWindowSize*SADWindowSize
P2 第二个控制视差平滑的参数。值越大,视差越平滑。P2是相邻像素之间视差变化大于1的惩罚。该算法要求P2 > P1,32*number_of_image_channels*SADWindowSize*SADWindowSize
disp12MaxDiff 左右的最大允许差异(以整数像素单位)差异检查,将其设置为非正数以禁用检查
preFilterCap 预滤波图像像素的截断值。首先是算法在每个像素处计算x导数,并按[-preFilterCap, preFilterCap]间隔剪辑其值
uniquenessRatio 最佳(最小)计算成本函数的百分比边际Value应该“赢得”第二个最佳值,从而认为找到的匹配是正确的。通常在5-15个范围内
speckleWindowSize 平滑视差区域的最大大小,以考虑它们的噪点和无效。将其设置为0以禁用散斑过滤。否则,将其设置在50 - 200的范围内
speckleRange 每个连接组件内的最大视差变化,如果进行散斑过滤,将参数设置为正值,将隐式地乘以16。通常1或2就足够了
mode 选择MODE_SGBM,MODE_HH = 1,MODE_SGBM_3WAY 三种计算模式

在自行搭建双目设备过程中,软件部分的立体匹配我使用的就是SGBM算法,下面是在我的实际工程项目中定义的SGBM算法的指针,参数取值为这个工程的实际取值

cv::Ptr<cv::StereoSGBM> sgbm = cv::StereoSGBM::create(
       0, 144, 5, 8 * 8 * 5 * 5, 8 * 32 * 5 * 5, 1, 63, 10, 100, 16, 0);

SGBM算法也可以像BM算法那样使用一些列set*函数设置其参数。

如果我的文章有幸被您看到,希望您能不吝赐教,向您学习,感觉写得不错的话请点个赞哦。

你可能感兴趣的:(计算机视觉,opencv,计算机视觉,程序人生,人工智能)