根据两个不同视角的图片来获得视差图:
#include "cv.h"
#include "cvaux.h"
#include "cxcore.h"
#include "highgui.h"
int main1(int argc, char** argv)
{
IplImage * cv_left_rectified;
IplImage * cv_right_rectified;
//note the sequence of the stereo pairs
cv_left_rectified = cvLoadImage("D://a//left1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
cv_right_rectified = cvLoadImage("D://a//right1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
CvSize size = cvGetSize(cv_left_rectified);
//the disparity map is an array h*w, with 16bit signed elements.
CvMat* disparity_left = cvCreateMat(size.height, size.width, CV_16S);
CvMat* disparity_right = cvCreateMat(size.height, size.width, CV_16S);
CvStereoGCState* state = cvCreateStereoGCState(16, 2);
cvFindStereoCorrespondenceGC(cv_left_rectified,
cv_right_rectified,
disparity_left,
disparity_right,
state,
0);
cvReleaseStereoGCState(&state);
//post-progressing the result
CvMat* disparity_left_visual = cvCreateMat(size.height, size.width, CV_8U);
cvConvertScale(disparity_left, disparity_left_visual, -16);
cvNamedWindow("disparity", 1);
cvShowImage("disparity", disparity_left_visual);
cvSaveImage("dst.jpg", disparity_left_visual);
cvWaitKey(0);
cvDestroyWindow("disparity");
return 0;
}
视差图的每个像素代表该对象的移动距离。
我使用的两张图片为:
经过运算得到的视差图:
根据该视差图进行三维建模:
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include<opencv2/opencv.hpp>
#include <math.h>
#include <GL/glut.h>
#include <iostream>
using namespace cv;
using namespace std;
#define MAX_SIZE 1024
float imgdata[MAX_SIZE][MAX_SIZE];
int w = 0;
int h = 0;
float scalar = 50;//scalar of converting pixel color to float coordinates
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity(); // Reset the coordinate system before modifying
gluLookAt(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glRotatef(-30, 0.0, 1.0, 0.0); //rotate about the x axis
glRotatef(-180, 0.0, 0.0, 1.0); //rotate about the z axis
glRotatef(-180, 0.0, 1.0, 0.0); //rotate about the y axis
float imageCenterX = w*.5;
float imageCenterY = h*.5;
float x, y, z;
glPointSize(1.0);
glBegin(GL_POINTS);//GL_POINTS
for (int i = 0; i<h; i++)
{
for (int j = 0; j<w; j++)
{
// color interpolation
glColor3f(1 - imgdata[i][j] / 255, imgdata[i][j] / 255, imgdata[i][j] / 255);
x = ((float)j - imageCenterX) / scalar;
y = ((float)i - imageCenterY) / scalar;
z = imgdata[i][j] / scalar;
glVertex3f(x, y, z);
}
}
glEnd();
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
void displayDisparity(IplImage* disparity)
{
double xyscale = 100;
int j = 0;
int i = 0;
CvScalar s;
//accessing the image pixels
for (i = 0; i<h; i++)
{
for (j = 0; j<w; j++)
{
s = cvGet2D(disparity, i, j);
imgdata[i][j] = s.val[0];//for disparity is a grey image.
}
}
}
int main(int argc, char *argv)
{
cout << "OpenCV and OpenGL working together!" << endl;
//char* filename = "tsuDisparity.bmp;";
IplImage* imgGrey = cvLoadImage("dst.jpg", 0); //read image as a grey one
if (imgGrey == NULL)
{
cout << "No valid image input." << endl;
char c = getchar();
return 1;
}
w = imgGrey->width;
h = imgGrey->height;
displayDisparity(imgGrey);
cvNamedWindow("original", CV_WINDOW_AUTOSIZE);
cvShowImage("original", imgGrey);
//------------------OpenGL-------------------------
glutInit(&argc, (char**)argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(500, 500);
glutCreateWindow("3D disparity image");
glutDisplayFunc(renderScene);
glutReshapeFunc(reshape);
glutMainLoop();
cvWaitKey(0);
//release opencv stuff.
cvReleaseImage(&imgGrey);
cvDestroyWindow("Original");
return 0;
}
重构结果: