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

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


一、win32项目工程,stereo vision1

1、头文件:

#include "stdafx.h"
#include 
#include
#include 
#include 
#include 
#include 
#include 
#include   
#include     
#include 

#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   
#include     
#include 


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:"<


3、GC算法

int StereoGC(IplImage *img1, IplImage *img2)
{
    CvStereoGCState* GCState=cvCreateStereoGCState(64,3);
    assert(GCState);
    cout<<"start matching using GC"<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:"<


4、伪彩色视图差

/*----------------------------
 * 功能 : 获取伪彩色视差图
 *----------------------------
 * 函数 : 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(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(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 
#include
#include 
#include 
#include 
#include 
#include 
#include   
#include     
#include 

#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   
#include     
#include  



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;
}
暂时先写到这里,其他的代码段我会抽空上传。希望对大家有所帮助。

你可能感兴趣的:(三维重建)