您的位置:首页 > 其它

三维重建之视图差的计算--SGBM和GC算法

2016-04-15 17:20 351 查看
最近一直在做三维重建的毕业设计,看了好多的算法、论文和代码。在查找资料的过程中发现很多人上传的东西真的是没法用,而且全都要积分。我虽说是一个水货,也不致力于从事着方面的研究和工作,但是为了毕设也没办法,目前调通了很多算法,虽然说不清原理,但是还是把代码创传上来,供大家使用。

一、win32项目工程,stereo vision1

1、头文件:

#include "stdafx.h"
#include <cstdio>
#include<cstring>
#include <cmath>
#include <highgui.h>
#include <cv.h>
#include <cxcore.h>
#include <iostream>
#include <iostream>
#include <stdlib.h>
#include <cvaux.h>

#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"

#pragma comment(lib,"opencv_highgui249d.lib")
#pragma comment(lib,"opencv_core249d.lib")
#pragma comment(lib,"opencv_imgproc249d.lib")

#include <math.h>
#include <GL/glut.h>
#include <iostream>


2、SGBM算法

int StereoSBGM(IplImage *img1, IplImage *img2)
{
cv::StereoSGBM sgbm;
int SADWindowSize = 9;
sgbm.preFilterCap = 63;
sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;
int cn = img1->nChannels;
int numberOfDisparities=64;
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;
Mat disp, disp8;
int64 t = getTickCount();
sgbm((Mat)img1, (Mat)img2, disp);
t = getTickCount() - t;
cout<<"Time elapsed:"<<t*1000/getTickFrequency()<<endl;
disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.));

//		getF_Gray2Color(disp8);
cv::Mat di;
getDisparityImage(disp8,di,true);
waitKey();
return 1;
}


3、GC算法

int StereoGC(IplImage *img1, IplImage *img2)
{
CvStereoGCState* GCState=cvCreateStereoGCState(64,3);
assert(GCState);
cout<<"start matching using GC"<<endl;
CvMat* gcdispleft=cvCreateMat(img1->height,img1->width,CV_16S);
CvMat* gcdispright=cvCreateMat(img2->height,img2->width,CV_16S);
CvMat* gcvdisp=cvCreateMat(img1->height,img1->width,CV_8U);
int64 t=getTickCount();
cvFindStereoCorrespondenceGC(img1,img2,gcdispleft,gcdispright,GCState);
t=getTickCount()-t;
cout<<"Time elapsed:"<<t*1/getTickFrequency()<<endl;

cvNormalize(gcdispright,gcvdisp,0,255,CV_MINMAX);

//    cvSaveImage("GC_right_disparity.png",gcvdisp);
//    cvNamedWindow("GC_disparity",0);
//    cvShowImage("GC_disparity",gcvdisp);

cv::Mat di;
CvMat *a = gcvdisp;
Mat b = Mat(a, true);
getDisparityImage(b,di,true);	//转换为彩色视图差

cvWaitKey(0);
cvReleaseMat(&gcdispleft);
cvReleaseMat(&gcdispright);
cvReleaseMat(&gcvdisp);

return 1;
}


4、伪彩色视图差

<span style="font-size:10px;">/*-----------</span>-----------------
* 功能 : 获取伪彩色视差图
*----------------------------
* 函数 : StereoMatch::getDisparityImage
* 访问 : public
* 返回 : 0 - 失败,1 - 成功
*
* 参数 : disparity			[in]	原始视差数据
* 参数 : disparityImage	[out]	伪彩色视差图
* 参数 : isColor			[in]	是否采用伪彩色,默认为 true,设为 false 时返回灰度视差图
*/
int getDisparityImage(cv::Mat& disparity, cv::Mat& disparityImage, bool isColor)
{
// 将原始视差数据的位深转换为 8 位
cv::Mat disp8u;
if (disparity.depth() != CV_8U)
{
disparity.convertTo(disp8u, CV_8U, 255/(64*16.));
}
else
{
disp8u = disparity;
}

// 转换为伪彩色图像 或 灰度图像
if (isColor)
{
if (disparityImage.empty() || disparityImage.type() != CV_8UC3 )
{
disparityImage = cv::Mat::zeros(disparity.rows, disparity.cols, CV_8UC3);
}

for (int y=0;y<disparity.rows;y++)
{
for (int x=0;x<disparity.cols;x++)
{
uchar val = disp8u.at<uchar>(y,x);
uchar r,g,b;

if (val==0)
r = g = b = 0;
else
{
r = 255-val;
g = val < 128 ? val*2 : (uchar)((255 - val)*2);
b = val;
}
disparityImage.at<cv::Vec3b>(y,x) = cv::Vec3b(r,g,b);
}
}
}
else
{
disp8u.copyTo(disparityImage);
}

IplImage * Image;
Image = &IplImage (disparityImage);
cvSaveImage("colordisparityImage.png",Image);
namedWindow("3、disparityImage",1);
cvShowImage("3、disparityImage",Image);
waitKey(0);
return 1;
}


二、基于对话框的mfc, stereovision

当转换到mfc上的时候,发现好多代码是无法直接移植的,愁死我了。/(ㄒoㄒ)/~~

后来一点点的改进,在这个过程中有很多的收获。

在网上搜了很多资料,针对两种算法,sgbm和gc算法,输入的图片要求不同,sgbm可以处理彩色图片,但是gc算法不允许,而且在转换为灰色图像的过程中,运行时会出现异常,在下面的代码里也都给出了解决的办法。但是因为本人学艺不精,就不给什么其他的注释了,大家尽量凭借自己的智慧去看吧。

1、头文件

#include "stdafx.h"
#include "stereovision.h"
#include "stereovisionDlg.h"
#include "afxdialogex.h"
#include <cstdio>
#include<cstring>
#include <cmath>
#include <highgui.h>
#include <cv.h>
#include <cxcore.h>
#include <iostream>
#include <iostream>
#include <stdlib.h>
#include <cvaux.h>

#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"

#pragma comment(lib,"opencv_highgui249d.lib")
#pragma comment(lib,"opencv_core249d.lib")
#pragma comment(lib,"opencv_imgproc249d.lib")

#include <math.h>
#include <GL/glut.h>
#include <iostream>


2、sgbm算法

int CstereovisionDlg::StereoSGBM(IplImage* img1, IplImage* img2)
{
cv::StereoSGBM sgbm;
int SADWindowSize = 9;
sgbm.preFilterCap = 63;
sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;
int cn = img1->nChannels;
int numberOfDisparities=64;
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;
Mat disp, disp8;
int64 t = getTickCount();
sgbm((Mat)img1, (Mat)img2, disp);
disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.));

cv::Mat di;
getDisparityImage(disp8,di,true);
waitKey();
return 1;
}


3、gc算法

int CstereovisionDlg::StereoGC(IplImage* img1, IplImage* img2)
{
IplImage* imgl=cvCreateImage(cvGetSize(img1),img1->depth,1);//不可以仅仅设置为IplImage* imgl = NULL
IplImage* imgr=cvCreateImage(cvGetSize(img2),img2->depth,1);
cvCvtColor(img1,imgl,CV_BGR2GRAY);
cvCvtColor(img2,imgr,CV_BGR2GRAY);

CvStereoGCState* state = cvCreateStereoGCState( 64, 3 );
assert(state);
CvMat* left_disp_  = cvCreateMat( imgl->height,imgl->width, CV_16S );
CvMat* right_disp_ = cvCreateMat( imgr->height,imgr->width,CV_16S );
CvMat* gcvdisp = cvCreateMat(imgl->height,imgl->width,CV_8U);
cvFindStereoCorrespondenceGC( imgl, imgr, left_disp_, right_disp_, state, 0 );

cvNormalize(right_disp_,gcvdisp,0,255,CV_MINMAX);

cv::Mat di;
CvMat *a = gcvdisp;
Mat b = Mat(a, true);
getDisparityImage(b,di,true);	//转换为彩色视图差

cvWaitKey(0);
cvReleaseMat(&left_disp_);
cvReleaseMat(&right_disp_);
cvReleaseMat(&gcvdisp);
cvReleaseStereoGCState(&state);
return 1;
}
暂时先写到这里,其他的代码段我会抽空上传。希望对大家有所帮助。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: