BM:Block Matching ,采用SAD方法计算匹配代价;
SGBM: 修改自Heiko Hirschmuller的《Stereo Processing by Semi-global Matching and Mutual Information》;
与原方法不同点:
GC:OpenCV3.0中没有实现,可以在OpenCV以下版本中找到。该方法效果是最好的,但是速度太慢,不能达到实时的匹配效率;
1、SGBM
主要参数:minDisparity 、numDisparities、blockSize、P1、P2。其他参数设置参照http://blog.csdn.net/zhubaohua_bupt/article/details/51866567
代码:
#include "stdafx.h"
#include "opencv2/opencv.hpp
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
Mat left = imread("imgL.jpg", IMREAD_GRAYSCALE);
Mat right = imread("imgR.jpg", IMREAD_GRAYSCALE);
Mat disp;
int mindisparity = 0;
int ndisparities = 64;
int SADWindowSize = 11;
//SGBM
cv::Ptr sgbm = cv::StereoSGBM::create(mindisparity, ndisparities, SADWindowSize);
int P1 = 8 * left.channels() * SADWindowSize* SADWindowSize;
int P2 = 32 * left.channels() * SADWindowSize* SADWindowSize;
sgbm->setP1(P1);
sgbm->setP2(P2);
sgbm->setPreFilterCap(15);
sgbm->setUniquenessRatio(10);
sgbm->setSpeckleRange(2);
sgbm->setSpeckleWindowSize(100);
sgbm->setDisp12MaxDiff(1);
//sgbm->setMode(cv::StereoSGBM::MODE_HH);
sgbm->compute(left, right, disp);
disp.convertTo(disp, CV_32F, 1.0 / 16); //除以16得到真实视差值
Mat disp8U = Mat(disp.rows, disp.cols, CV_8UC1); //显示
normalize(disp, disp8U, 0, 255, NORM_MINMAX, CV_8UC1);
imwrite("results/SGBM.jpg", disp8U);
return 0;
}
minDisparity:最小视差,默认为0。此参数决定左图中的像素点在右图匹配搜索的起点,int 类型;
numDisparities:视差搜索范围长度,其值必须为16的整数倍。最大视差 maxDisparity = minDisparity + numDisparities -1;
blockSize:SAD代价计算窗口大小,默认为5。窗口大小为奇数,一般在3*3 到21*21之间;
P1、P2:能量函数参数,P1是相邻像素点视差增/减 1 时的惩罚系数;P2是相邻像素点视差变化值大于1时的惩罚系数。P2必须大于P1。需要指出,在动态规划时,P1和P2都是常数。
一般建议:P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
tsukuba_left.jpg | tsukuba_right.jpg |
SADWindowSize = 5 | SADWindowSize = 11 | SADWindowSize = 21 |
P1 = 8 , P2 = 10 | P1 = 8 , P2 = 32 | P1 = 8 , P2 = 64 |
MODE_SGBM(5方向) | MODE_HH(8方向) |
总结:
2、BM
代码:
#include "stdafx.h"
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
Mat left = imread("imgL.jpg", IMREAD_GRAYSCALE);
Mat right = imread("imgR.jpg", IMREAD_GRAYSCALE);
Mat disp;
int mindisparity = 0;
int ndisparities = 64;
int SADWindowSize = 11;
cv::Ptr bm = cv::StereoBM::create(ndisparities, SADWindowSize);
// setter
bm->setBlockSize(SADWindowSize);
bm->setMinDisparity(mindisparity);
bm->setNumDisparities(ndisparities);
bm->setPreFilterSize(15);
bm->setPreFilterCap(31);
bm->setTextureThreshold(10);
bm->setUniquenessRatio(10);
bm->setDisp12MaxDiff(1);
copyMakeBorder(left, left, 0, 0, 80, 0, IPL_BORDER_REPLICATE); //防止黑边
copyMakeBorder(right, right, 0, 0, 80, 0, IPL_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);
imwrite("results/BM.jpg", disp8U);
return 0;
}
SADWindowSize = 5 | SADWindowSize = 21 | SADWindowSize = 31 | SADWindowSize = 41 |
3、GC
OpenCV3.0暂未实现GC算法,这里直接贴出结果(来自:http://www.cnblogs.com/polly333/p/5130375.html)
SGBM | BM | GC |
视差效果:BM < SGBM < GC;
处理速度:BM > SGBM > GC ;
参考:
http://www.cnblogs.com/polly333/p/5130375.html
http://www.cnblogs.com/polly333/p/5130375.html
http://blog.csdn.net/u014493244