在双目立体匹配中,有基于SAD算法的BM、SGBM、GC立体匹配技术,但是在OpenCv3.0以后,GC算法就从legacy中去除掉了。为了查看三种算法的匹配效果及运算性能,我在Windows10中安装了OpenCv2.4.9,并以VsCode为IDE进行程序编写。
一、VsCode中集成OpenCv2.4.9
VsCode中集成OpenCv2.4.9,我主要是参照了这个文章的方法,根据这位博主的方法,我完成了环境的配置,由于需要相应的legacy库,所以我的tasks.json如下所示
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"command": "g++",
"args": [
"-g",
"-std=c++11",
"${file}",
"-o",
"${fileBasenameNoExtension}.exe",
"-I", "F:\\opencv\\build\\include",
"-I", "F:\\opencv\\build\\include\\opencv2",
"-I", "F:\\opencv\\build\\include\\opencv",
"-L", "F:\\opencv\\build\\x64\\MinGW\\lib",
"-l", "opencv_core249",
"-l", "opencv_imgproc249",
"-l", "opencv_video249",
"-l", "opencv_ml249",
"-l", "opencv_highgui249",
"-l", "opencv_objdetect249",
"-l", "opencv_flann249",
"-l", "opencv_photo249",
"-l", "opencv_legacy249",
"-l", "opencv_calib3d249"
],// 编译命令参数
"problemMatcher":{
"owner": "cpp",
"fileLocation":[
"relative",
"${workspaceFolder}"
],
"pattern":[
{
"regexp": "^([^\\\\s].*)\\\\((\\\\d+,\\\\d+)\\\\):\\\\s*(.*)$",
"file": 1,
"location": 2,
"message": 3
}
]
},
"group": {
"kind": "build",
"isDefault": true
}
}
二、程序的实现
程序实现的文章参考了OpenCV三种立体匹配求视差图算法总结这篇博客,同时也有对官网例程的参考。程序的完整代码如下:
#include
#include
#include
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/legacy/legacy.hpp"
using namespace std;
using namespace cv;
enum { STEREO_BM=0, STEREO_SGBM=1, STEREO_HH=2, STEREO_VAR=3 };
int alg = STEREO_SGBM;
int main()
{
time_t begin,end;
double ret;
int SADWindowSize = 0, numberOfDisparities = 0;
IplImage * img1 = cvLoadImage("D:/tsukuba_l.png",0);
IplImage * img2 = cvLoadImage("D:/tsukuba_r.png",0);
Mat left = imread("D:/tsukuba_l.png",0);
Mat right = imread("D:/tsukuba_r.png",0);
Size img_size = left.size();
CvMat* displeft=cvCreateMat(img1->height,img1->width,CV_16S);
CvMat* dispright=cvCreateMat(img2->height,img2->width,CV_16S);
CvMat* disp=cvCreateMat(img1->height,img1->width,CV_8U);
//BM算法
CvStereoBMState *BMState = cvCreateStereoBMState();
numberOfDisparities = numberOfDisparities > 0 ? numberOfDisparities : ((img_size.width/8) + 15) & -16;
BMState->SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 9;
BMState->minDisparity = 0;
BMState->numberOfDisparities = numberOfDisparities;
BMState->textureThreshold = 10;
BMState->uniquenessRatio = 15;
BMState->speckleWindowSize = 100;
BMState->speckleRange = 32;
BMState->disp12MaxDiff = 1;
begin=clock();
cvFindStereoCorrespondenceBM( img1, img2, displeft,BMState);
end=clock();
ret=double(end-begin)/CLOCKS_PER_SEC;
cout<<"BM algorithm runtime: "<<ret<<" s"<<endl;
cvNormalize( displeft, disp, 0, 255, CV_MINMAX );
cvSaveImage("BM_right_disparity.png",disp);
cvNamedWindow("BM_disparity",0);
cvShowImage("BM_disparity",disp);
//SGBM算法
StereoSGBM sgbm;
sgbm.preFilterCap = 63;
sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;
int cn = left.channels();
sgbm.P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
sgbm.minDisparity = 0;
sgbm.numberOfDisparities = numberOfDisparities;
sgbm.uniquenessRatio = 10;
sgbm.speckleWindowSize = 100;
sgbm.speckleRange = 32;
sgbm.disp12MaxDiff = 1;
sgbm.fullDP = alg == STEREO_HH;
Mat disp_, disp8;
//sgbm(left , right , left_disp);
begin=clock();
sgbm(left, right, disp_);
end=clock();
disp_.convertTo(disp8, CV_8U);
ret=double(end-begin)/CLOCKS_PER_SEC;
cout<<"SGBM algorithm runtime: "<<ret<<" s"<<endl;
imwrite("SGBM_disparity.png",disp8);
namedWindow("SGBM_disparity",WINDOW_AUTOSIZE);
imshow("SGBM_disparity",disp8);
//GC算法
CvStereoGCState* GCState=cvCreateStereoGCState(16,2); //原始为64 3
assert(GCState);
begin=clock();
cvFindStereoCorrespondenceGC(img1,img2,displeft,dispright,GCState);
end=clock();
ret=double(end-begin)/CLOCKS_PER_SEC;
cout<<"GC algorithm runtime: "<<ret<<" s"<<endl;
/*CvStereoGCState* state = cvCreateStereoGCState( 16, 2 );
left_disp_ =cvCreateMat( left->height,left->width, CV_32F );
right_disp_ =cvCreateMat( right->height,right->width,CV_32F );*/
cvNormalize(dispright,disp,0,255,CV_MINMAX);
cvSaveImage("GC_disparity.png",disp);
cvNamedWindow("GC_disparity",0);
cvShowImage("GC_disparity",disp);
cvWaitKey(0);
cvReleaseMat(&displeft);
cvReleaseMat(&dispright);
cvReleaseMat(&disp);
return 0;
}
三、效果对比
我的电脑为联想拯救者Y7000,在上面运行,三种算法的时间分别为BM:8ms,SGBM:33ms,GC:2030ms,效果图如下:
tsukuba_l.png
BM算法