使用的opencv版本是4.5.4,StereoBM可设置的参数及其释意如下。
/*匹配图像预处理*/
bm->setPreFilterCap(63);//31//预处理滤波器的截断值,计算每个像素的x导数,并按[-preFilterCap, preFilterCap]间隔裁剪其值,结果值传递给 Birchfield-Tomasi 像素代价函数。
bm->setPreFilterSize(7);//预处理滤波器窗口大小,容许范围是[5,255],一般应该在 5x5..21x21 之间,参数必须为奇数值
bm->setPreFilterType(cv::StereoBM::PREFILTER_XSOBEL);//预处理滤波器类型,有两种可选类型:PREFILTER_NORMALIZED_RESPONSE(归一化响应) 或者 PREFILTER_XSOBEL (水平方向Sobel算子,默认类型)
/*计算视差的参数*/
//bm->setSmallerBlockSize(blockSize/2);//
bm->setTextureThreshold(30);//低纹理区域的判断阈值,如果当前窗口内所有邻居像素点的x导数绝对值之和小于指定阈值,则该窗口对应的像素点的视差值为0
bm->setUniquenessRatio(10);// 视差窗口范围内最低代价(指最好的结果)是次低代价的(1 + uniquenessRatio/100)倍时,最低代价对应的视差值才是该像素点的视差,否则该像素点的视差为 0,一般5-15左右的值比较合适,代价是啥?
bm->setBlockSize(blockSize);// 块大小,应为奇数,取值【3,11】比较合适,较大的块大小意味着更平滑但不太准确的视差图。 较小的块大小提供了更详细的视差图,但算法发现错误对应关系的机会更高。
bm->setDisp12MaxDiff(-1);//左视差图(直接计算得出)和右视差图(通过cvValidateDisparity计算得出)之间的最大容许差异。超过该阈值的视差值将被清零。该参数默认为 -1,即不执行左右视差检查。
bm->setMinDisparity(0);
bm->setNumDisparities(numOfDisparities);// 搜索视差时的范围【MinDisparity,MinDisparity+numOfDisparities】,必须为16的整数倍
/*视差图后处理*/
//在算出初始视差图后会进行视差图后处理,包括中值滤波,连通域检测等。
//中值滤波能够有效去除视差图中孤立的噪点,而连通域检测能够检测出视差图中因噪声引起小团块(blob)。
//判断当前像素点四邻域的邻域点与当前像素点的差值diff,如果diff<speckRange,则表示该邻域点与当前像素点是一个连通域并设置一个标记。
//然后再以该邻域点为中心判断其四邻域点,步骤同上。直至某一像素点四邻域的点均不满足条件,则停止。
//然后判断被标记的像素点个数count,如果像素点个数count<=speckleWindowSize,则说明该连通域是一个小团块(blob),因此
//将当前像素点值设置为newValue(表示错误的视差值,newValue一般设置为负数或者0值)。否则,表示该连通域是个大团块,不做处理。
//所有像素点处理后,满足条件的区域会被设置为newValue值,后续可以用空洞填充等方法重新估计其视差值。
bm->setSpeckleRange(16);//在sgbm的官方参数介绍中说该值会被乘以16,设置为1或2比较合适,bm应该是没有乘以16
bm->setSpeckleWindowSize(72);//检查视差连通区域变化度的窗口大小, 值为 0 时取消 speckle 检查,否则取【50,200】内的值比较合适
参考文献:
opencv sgbm
opencv bm
opencv StereoBM各个参数的意义
OpenCV3.4两种立体匹配算法效果对比