opencv3.4.6 立体匹配:StereoSGBM算法

semi-global matching(SGM)是一种用于计算双目视觉中视差(disparity)的半全局匹配算法,在OpenCV中的实现为semi-global block matching(SGBM);

opencv中SGBM算法的参数含义及数值选取

一、 预处理参数

1:preFilterCap:水平sobel预处理后,映射滤波器大小。默认为15

int ftzero =max(params.preFilterCap, 15) | 1;

opencv测试例程stereo_match.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 类型

三 、动态规划参数

动态规划有两个参数,分别是P1、P2,它们控制视差变化平滑性的参数。P1、P2的值越大,视差越平滑。P1是相邻像素点视差增/减 1 时的惩罚系数;P2是相邻像素点视差变化值大于1时的惩罚系数。P2必须大于P1。需要指出,在动态规划时,P1和P2都是常数。

5:opencv测试例程stereo_match.cpp中,P1 = 8*cn*sgbmWinSize*sgbmWinSize;

6:opencv测试例程stereo_match.cpp中,P2 = 32*cn*sgbmWinSize*sgbmWinSize;

四、后处理参数

7:uniquenessRatio:唯一性检测参数。对于左图匹配像素点来说,先定义在numberOfDisparities搜索区间内的最低代价为mincost,次低代价为secdmincost。如果满足

即说明最低代价和次第代价相差太小,也就是匹配的区分度不够,就认为当前匹配像素点是误匹配的。

opencv测试例程stereo_match.cpp中,uniquenessRatio=10。int 类型

8:disp12MaxDiff:左右一致性检测最大容许误差阈值。int 类型

opencv测试例程stereo_match.cpp中,disp12MaxDiff =1。

9:speckleWindowSize:视差连通区域像素点个数的大小。对于每一个视差点,当其连通区域的像素点个数小于speckleWindowSize时,认为该视差值无效,是噪点。

opencv测试例程stereo_match.cpp中,speckleWindowSize=100。

10:speckleRange:视差连通条件,在计算一个视差点的连通区域时,当下一个像素点视差变化绝对值大于speckleRange就认为下一个视差像素点和当前视差像素点是不连通的。

opencv测试例程stereo_match.cpp中,speckleRange=10。

 测试示例:

enum { STEREO_BM = 0, STEREO_SGBM = 1, STEREO_HH = 2, STEREO_VAR = 3, STEREO_3WAY = 4 };

void calDispWithSGBM(Mat imgL, Mat imgR, Mat &imgDisparity8U)
{
	cv::Size imgSize = imgL.size();
	int numberOfDisparities = ((imgSize.width / 8) + 15) & -16;
	cv::Ptr sgbm = cv::StereoSGBM::create(0, 16, 3);

	sgbm->setPreFilterCap(63);

	int SADWindowSize = 9;
	int sgbmWinSize = SADWindowSize > 0 ? SADWindowSize : 3;
	sgbm->setBlockSize(sgbmWinSize);

	int cn = imgL.channels();
	sgbm->setP1(8 * cn*sgbmWinSize*sgbmWinSize);
	sgbm->setP2(32 * cn*sgbmWinSize*sgbmWinSize);

	sgbm->setMinDisparity(0);
	sgbm->setNumDisparities(numberOfDisparities);
	sgbm->setUniquenessRatio(10);
	sgbm->setSpeckleWindowSize(100);
	sgbm->setSpeckleRange(32);
	sgbm->setDisp12MaxDiff(1);

	int alg = STEREO_SGBM;
	if (alg == STEREO_HH)
		sgbm->setMode(cv::StereoSGBM::MODE_HH);
	else if (alg == STEREO_SGBM)
		sgbm->setMode(cv::StereoSGBM::MODE_SGBM);
	else if (alg == STEREO_3WAY)
		sgbm->setMode(cv::StereoSGBM::MODE_SGBM_3WAY);

	Mat imgDisparity16S = Mat(imgL.rows, imgL.cols, CV_16S);
	sgbm->compute(imgL, imgR, imgDisparity16S);

	//--Display it as a CV_8UC1 image:16位有符号转为8位无符号
	imgDisparity16S.convertTo(imgDisparity8U, CV_8U, 255 / (numberOfDisparities*16.));
}

int main()
{
	//--读取图像
	Mat imgL = imread("..\\image\\aloeL.jpg", 0);
	Mat imgR = imread("..\\image\\aloeR.jpg", 0);

	//--And create the image in which we will save our disparities
	Mat imgDisparity8U = Mat(imgL.rows, imgL.cols, CV_8UC1);

	//calDispWithBM(imgL, imgR, imgDisparity8U);
	calDispWithSGBM(imgL, imgR, imgDisparity8U);
}

opencv3.4.6 立体匹配:StereoSGBM算法_第1张图片

你可能感兴趣的:(图像配准)