以OpenCV自带的Aloe图像对为例:
1.BM算法(Block Matching)
参数设置如下:
int numberOfDisparities = ((imgSize.width / 8) + 15) & -16;
cv::Ptr<:stereobm> bm = cv::StereoBM::create(16, 9);
cv::Rect roi1, roi2;
bm->setROI1(roi1);
bm->setROI2(roi2);
bm->setPreFilterCap(31);
bm->setBlockSize(9);
bm->setMinDisparity(0);
bm->setNumDisparities(numberOfDisparities);
bm->setTextureThreshold(10);
bm->setUniquenessRatio(15);
bm->setSpeckleWindowSize(100);
bm->setSpeckleRange(32);
bm->setDisp12MaxDiff(1);
bm->compute(imgL, imgR, disp);
效果如下:
BM算法得到的视差图(左),空洞填充后得到的视差图(右)
2.SGBM(Semi-Global Block matching)算法:
参数设置如下:
enum { STEREO_BM = 0, STEREO_SGBM = 1, STEREO_HH = 2, STEREO_VAR = 3, STEREO_3WAY = 4};int numberOfDisparities = ((imgSize.width / 8) + 15) & -16;
cv::Ptr<:stereosgbm> 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);
sgbm->compute(imgL, imgR, disp);
效果如图:
SGBM算法得到的视差图(左),空洞填充后得到的视差图(右)
可见SGBM算法得到的视差图相比于BM算法来说,减少了很多不准确的匹配点,尤其是在深度不连续区域,速度上SGBM要慢于BM算法。OpenCV3.0以后没有实现GC算法,可能是出于速度考虑,以后找时间补上对比图,以及各个算法的详细原理分析。
后面我填充空洞的效果不是很好,如果有更好的方法,望不吝赐教。
preFilterCap()匹配图像预处理
两种立体匹配算法都要先对输入图像做预处理,OpenCV源码中中调用函数 static void prefilterXSobel(const cv::Mat& src, cv::Mat& dst, int preFilterCap),参数设置中preFilterCap在此函数中用到。函数步骤如下,作用主要有两点:对于无纹理区域ÿ