1.双目立体匹配算法
左右视差
以后再细写。
1.1 立体匹配的流程
- 摄像机标定(包括内参和外参):直接用matlab标定工具箱即可
- 双目图像的校正(包括畸变校正和立体校正):立体校正opencv samples里给了案
- 立体匹配算法获取视差图,以及深度图
- SAD/SGBM/BM/GC/
- 利用视差图,或者深度图进行虚拟视点的合成
- 利用分水岭算法或者Grabcut算法进行分割
1.2 最新的方法
最近已经出现了使用DL做视差预测以及场景流预测的工作了,如:
Pyramid Stereo Matching Network (CVPR2018):
2.SGBM算法
SGBM(semi-global block matching,又称SGM算法)
参考SGM算法思路
该算法已经在opencv库中,函数为SGBM;并且在ROS中也有实现,并且为默认方法
SGBM详细步骤可参考:SGBM解读
2.1 算法原理
主要分为:
1)预处理 preprocessing:
先运用sobel算子获得边缘;
再用一个函数将经过水平Sobel算子处理后的图像上每个像素点
预处理实际上是得到图像的梯度信息。
2)代价计算 cost
包括:
- 经过预处理得到的图像的梯度信息经过基于采样的方法得到的梯度代价;
- SAD(sum of absolute difference),即左右图像在一个窗口内对应像素之差的和。
3)动态规划 dynamic programming
4)后处理 postprocessing
- 唯一性检测
- 亚像素差值
- 左右一致性检测
- 连通区域检测
2.2 opencv4.0调用
如下,其中比较关键的参数有:
1)预处理
preFilterCap:水平sobel预处理后,映射滤波器大小,默认为15。
2)代价函数
minDisparity:最小视差,默认为0。此参数决定左图中的像素点在右图匹配搜索的起点。
numberOfDisparities:视差搜索范围,其值必须为16的整数倍。最大搜索边界= numberOfDisparities+ minDisparity。我通常取64。
SADWindowSize:SAD窗口大小,通常取11。
3)动态规划
有两个参数,分别是P1、P2,它们控制视差变化平滑性的参数。
P1、P2的值越大,视差越平滑。P1是相邻像素点视差增/减 1 时的惩罚系数;P2是相邻像素点视差变化值大于1时的惩罚系数。P2必须大于P1。需要指出,在动态规划时,P1和P2都是常数。
在官方例子中,
P1=8cnsgbm.SADWindowSizesgbm.SADWindowSize;
P2=32cnsgbm.SADWindowSizesgbm.SADWindowSize;
4)后处理
uniquenessRatio:唯一性检测参数。用于判断当前像素点是否无匹配,取值在5-15之间,通常取10。
disp12MaxDiff:左右一致性检测最大容许误差阈值,通常取1。
speckleWindowSize:视差连通区域像素点个数的大小。对于每一个视差点,当其连通区域的像素点个数小于speckleWindowSize时,认为该视差值无效,是噪点。通常取100。
speckleRange:视差连通条件,在计算一个视差点的连通区域时,当下一个像素点视差变化绝对值大于speckleRange就认为下一个视差像素点和当前视差像素点是不连通的。通常取10。
string img_nameR = img_path +img_name;
string img_truename = img_name.substr(0,img_name.find_last_of('R'));
string img_nameL = img_path + img_truename+"L"+suffix;
Mat left = imread(img_nameL, IMREAD_GRAYSCALE);
Mat right = imread(img_nameR, IMREAD_GRAYSCALE);
Mat disp;
int mindisparity = 0;
int ndisparities = 64;
int SADWindowSize = 11;
cv::Ptr<cv::StereoBM> bm = cv::StereoBM::create(ndisparities, SADWindowSize);
// setter
bm->setPreFilterType(1);
bm->setBlockSize(SADWindowSize);
bm->setMinDisparity(mindisparity);
bm->setNumDisparities(ndisparities);
bm->setPreFilterSize(15);
bm->setPreFilterCap(31);
bm->setTextureThreshold(10);
bm->setUniquenessRatio(5);
bm->setSpeckleRange(32);
bm->setSpeckleWindowSize(100);
bm->setDisp12MaxDiff(1);
copyMakeBorder(left, left, 0, 0, 80, 0, BORDER_REPLICATE); //防止黑边
copyMakeBorder(right, right, 0, 0, 80, 0, BORDER_REPLICATE);
bm->compute(left, right, disp);
disp.convertTo(disp, CV_32F, 1.0 / 16); //除以16得到真实视差值
disp = disp.colRange(80, disp.cols);
Mat disp8U = Mat(disp.rows, disp.cols, CV_8UC1);
normalize(disp, disp8U, 0, 255, NORM_MINMAX, CV_8UC1);
参考:立体匹配
总结:
- blockSize(SADWindowSize) 越小,也就是匹配代价计算的窗口越小,视差图噪声越大;blockSize越大,视差图越平滑;太大的size容易导致过平滑,并且误匹配增多,体现在视差图中空洞增多;
- 惩罚系数控制视差图的平滑度,P2>P1,P2越大则视差图越平滑;
- 八方向动态规划较五方向改善效果不明显,主要在图像边缘能够找到正确的匹配;
2.2 UV视差
参考:
U-V视差1
2.3 Git Repo参考
其实git上一搜一大把,还是贴几个以供参考,记录一下。
- SGM-disparity
- SGM(包含GPU版本实现)
- SGM-CPU实现
- 基于CUDA的实现:https://github.com/fixstars/libSGM.git
- 基于ROS与CUDA的实现:https://github.com/hunterlew/stereo_matching
- 基于ROS并生成电云的实现:https://github.com/rachillesf/stereoMagic.git
- Some basical stereo matching methods:https://github.com/galad-loth/StereoMatching.git