openGL将三维坐标转换成二维坐标在…


数据:利用kinect已经将人体骨架的三维坐标提取出来,并保存在一个txt文档里面

目的:将三维坐标在屏幕上显示出来。

工具:openGL

 

通过查阅资料和老师的指导,如果想把三维坐标在屏幕上显示出来,要先转换成二维坐标,因为屏幕上显示的都是二维数据,就比如一张图片上面的像素点都是二维数据(xy,即便有通道数,也是用二维来表示的。而能实现这个功能的工具有openGLDirect3Djava3D。通过查看《OpenGL入门教程()》,知道里面有将三维坐标显示的函数glVertex3f(1.0f, 3.0f, 0.0f);所以打算用openGL实现。

一:openGL简介

OpenGL英语Open Graphics Library)是个定义了一个跨编程语言、跨平台应用程序接口API)的规范,它用于生成二维三维图像。这个接口由近三百五十个不同的函数调用组成,用来从简单的图形比特绘制复杂的三维景象。而另一种程序接口系统是仅用于MicrosoftWindows上的Direct3DOpenGL常用于CAD拟实境、科学可视化程序和电子游戏开发。(来自维基百科)

看以上的的介绍,可以知道,openGL可以跨平台,而Direct3D只能在微软的系统上运行的API。微软为了推广自己的Direct3D,自从在VC6.0上这个也是老师建议学习一下API的原因,虽然只是皮毛。

进入正题:

首先,要配置openGL GLUTgl使用工具包)的环境(转)

第一步:下载OpenGLGLUT

Windows环境下的GLUT下载地址:(苹果机不需要安装,自带)  

http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip

第二步:OpenGL库和配置文件

OpenGL库配置用到的文件分为下面三类:

■ 动态链接库文件(.dll

glaux.dll, glu32.dll,glut32.dll, OPENGL32.DLL, glut.dll

■ 头文件(.h

GL.H, GLAUX.H, GLU.H,glut.h

■ 库文件(.lib

GLAUX.LIBGlu32.libglut32.libOpengl32.libglut.lib

其中opengl32.dll,glaux.dll,glu32.dll是安装显卡驱动自带,应该每个系统里面都有,如果没有重新安装显卡驱动。

其中glut32.dll, glut.dll, glut.h,glut32.lib, glut.lib 是在刚才那个地址下载的,打开压缩包后会有5个文件

下面就是区别了,VC++2008不带GL.H, GLAUX.h,glu.h, glaux.lib, glu32.lib,opengl32.lib这些文件要在网上下载或者在VC6.0里面拷贝出来,

如果想要全套的文件,网上可以下载,也可以给我博客留言,我发给你。 

第三步:Windows下配置OpenGL

glut32.dll,glut.dll拷贝到C:\WINDOWS\system32目录下,system32目录下应该已经有 opengl32.dll, glu32.dll了。

GL.H, GLAUX.h, glu.h,glut.h  拷贝到 C:\Program Files\Microsoft Visual Studio9.0\VC\include\gl

 GLAUX.LIBGlu32.libglut32.libOpengl32.libglut.lib拷贝到 C:\Program Files\Microsoft Visual Studio9.0\VC\lib

接下来:实现三维坐标的显示。

遇到的问题1由于我有15个骨骼点每一帧上面,所有我需要把这15个骨骼点显示出来,并且用直线连接起来,实现一帧图像中骨骼的重建。但是如果用线连起来之后,就有分不清楚点在哪的可能。比如:一条直线上可能有三个点,但是由于没有弯曲,所以会以为只有两端的两个点(或者只有弯曲处的点),为了解决这个问题,可以在三维点的周围画出一个圆球或者方块。也就是为了将是三维点的地方凸显出来。但是由于openGL要求:指定顶点的命令必须包含在glBegin 函数之后,glEnd 函数之前(否则指定的定点将被忽略),并由glBegin 来指明如何使用这些点。举例说明下:

glBegin(GL_POINTS);

   glVertex2f(0.0f,0.0f);

   glVertex2f(0.5f, 0.0f);

glEnd();

 

就是不管你是画点,画线,画多边形,等,要在glbeginglEnd之间。和MFC中的路径层的定义差不多。

那么问题又来了,为什么openGL要这么做呢?

自然是有道理的:

假设现在我已经指定了若干顶点,那么 OpenGL 是如何知道我想拿这些顶点来干什么呢?是一个一个的画

出来,还是连成线?或者构成一个多边形?或者做其它什么事情?

 

问题2如果在给定的glBeginglEnd中,我只能画给定的几种图形中的一个,不知道怎么既画Line又画圆或者方块之类的东西(应该能实现,但是我没有找到办法)。

解决办法:

为了解决以上两个问题,既能凸显出点存在的位置,又能将骨架显示出来(也就是将点用线连上)。我将每两点的连线用不同的颜色表示,同时将显示的颜色变的粗一些(openGL里面有函数void glLineWidth(GLfloat width);可以指定直线的宽度)。这样以上两个问题都解决了。

 

问题3:怎么将一帧一帧的图像形成视频,跑起来。

解决办法:

利用函数glutIdleFunc(&myIdle);该函数在CPU空闲的时候被调用,参数myIdle是一个自定义函数,将要显示的视频帧的函数myDisplay放入其中,就可以实现视频的功能了。因为CPU是循环调用这个函数的。

 

总结:解决这个问题分以下两步:

1、将txt里面的数据全部读取到一个Vector中,二维Vector,每一维表示一帧图像的数据。

2、将一帧数据在myDisplay函数中显示出来。在myIdle函数里面调用myDisplay函数即可。由于myDisplay循环被调用,所以视频帧也就成视频了。

 上代码:新手,写的不好。

#include "stdafx.h"

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <windows.h>
#include <math.h>	
#include <time.h> 
#define GLUT_DISABLE_ATEXIT_HACK
#include <GL/glut.h>


using namespace std;

int i=0;
vector<float> skeletonData;
int frameidx = 0;
vector< vector<float> > frames;

//计算帧率
double CalFrequency() 
{ 
	static int count;  
	static double save; 
	static clock_t last, current; 
	double timegap; 

	++count; 
	if( count <= 50 ) 
		return save; 
	count = 0; 
	last = current; 
	current = clock(); 
	timegap = (current-last)/(double)CLK_TCK;  
	save = 50.0/timegap; 
	return save; 
} 

//用直线画骨架
void myDisplayLine()
{
	double FPS = CalFrequency(); 
	//printf("FPS = %f\n", FPS); 
	cout <<"第"<< frameidx<<"帧"<< endl;
	skeletonData = frames[frameidx];
	glClear(GL_COLOR_BUFFER_BIT);
	//glPointSize(5.0f);
	glLineWidth(3.0f);
	//glBegin(GL_POINTS);
	glBegin(GL_LINES);
	//1--2
	glColor3ub(255,0,0);//红
	//1--2
	glVertex3f(skeletonData[0], skeletonData[1], 0.999999);
	glVertex3f(skeletonData[3], skeletonData[4], skeletonData[5]);
	
	//2--3
	glColor3ub(0,255,0);//绿
	glVertex3f(skeletonData[3], skeletonData[4], skeletonData[5]);
	glVertex3f(skeletonData[6], skeletonData[7], skeletonData[8]);
	//2--4
	glColor3ub(0,0,255);//蓝
	glVertex3f(skeletonData[3], skeletonData[4], skeletonData[5]);
	glVertex3f(skeletonData[9], skeletonData[10], skeletonData[11]);
	//3--5
	glColor3ub(255,255,0);//黄
	glVertex3f(skeletonData[6], skeletonData[7], skeletonData[8]);
	glVertex3f(skeletonData[12], skeletonData[13], skeletonData[14]);
	//5--7
	glColor3ub(255,255,255);//白
	glVertex3f(skeletonData[12], skeletonData[13], skeletonData[14]);
	glVertex3f(skeletonData[18], skeletonData[19], skeletonData[20]);
	//4--6
	glColor3ub(255,0,255);//粉
	glVertex3f(skeletonData[9], skeletonData[10], skeletonData[11]);
	glVertex3f(skeletonData[15], skeletonData[16], skeletonData[17]);
	//6--8
	glColor3ub(255,128,0);//橙
	glVertex3f(skeletonData[15], skeletonData[16], skeletonData[17]);
	glVertex3f(skeletonData[21], skeletonData[22], skeletonData[23]);
	//2--9
	glColor3ub(0,255,255);
	glVertex3f(skeletonData[3], skeletonData[4], skeletonData[5]);
	glVertex3f(skeletonData[24], skeletonData[25], skeletonData[26]);
	//9--10
	glColor3ub(128,128,0);
	glVertex3f(skeletonData[24], skeletonData[25], skeletonData[26]);
	glVertex3f(skeletonData[27], skeletonData[28], skeletonData[29]);
	//9--11
	glColor3ub(128,128,128);
	glVertex3f(skeletonData[24], skeletonData[25], skeletonData[26]);
	glVertex3f(skeletonData[30], skeletonData[31], skeletonData[32]);
	//10--12
	glColor3ub(0,128,64);
	glVertex3f(skeletonData[27], skeletonData[28], skeletonData[29]);
	glVertex3f(skeletonData[33], skeletonData[34], skeletonData[35]);
	//12--14
	glColor3ub(64,0,64);
	glVertex3f(skeletonData[33], skeletonData[34], skeletonData[35]);
	glVertex3f(skeletonData[39], skeletonData[40], skeletonData[41]);
	//11--13
	glColor3ub(0,64,64);
	glVertex3f(skeletonData[30], skeletonData[31], skeletonData[32]);
	glVertex3f(skeletonData[36], skeletonData[37], skeletonData[38]);
	//13--15
	glColor3ub(128,64,64);
	glVertex3f(skeletonData[36], skeletonData[37], skeletonData[38]);
	glVertex3f(skeletonData[42], skeletonData[43], skeletonData[44]);

	glEnd();
	glFlush();

	//使用双缓冲技术
	glutSwapBuffers();
}

void readdata(string &filename, vector< vector<float> > &skeData)
{
	skeData.clear();
	ifstream infile(filename.c_str());
	string temp;
	int j = 0;
	vector<float> tmp;
	skeData.push_back(tmp);
	while (getline(infile,temp))
	{
		cout<<temp<<endl;
		string xx;
		string yy;
		string zz;

		if (temp.size()>20)
		{

			int pos1 = temp.find(' ');
			int pos2 = temp.find(',');
			xx = temp.substr(pos1,10);

			string str = temp.substr(pos2+1,temp.size());

			pos1 = str.find(',');
			yy = str.substr(0,pos1);

			zz = str.substr(pos1+1,str.size());

			skeData[j].push_back(atof(xx.c_str()));
			skeData[j].push_back(atof(yy.c_str()));
			skeData[j].push_back(atof(zz.c_str()));
			i = i+3;
		}
		if(i == 45)
		{
			i = 0;
			j++;
			vector<float> tmp1;
			skeData.push_back(tmp1);
		}


	}
	skeData.pop_back();
	infile.close();
}
void myIdle()
{
	if(frameidx >= frames.size())
	{
		frameidx = 0;
	}
	myDisplayLine();
	frameidx++;
	
	Sleep(30);
}
int _tmain(int argc, _TCHAR* argv[])
{

	string filename("video1.txt");
	//cin>>filename;

	readdata(filename, frames);

	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_RGB |GLUT_DOUBLE);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(500,500);
	glutCreateWindow("openGL 显示三维坐标信息");

	glutDisplayFunc(&myDisplayLine);

	glutIdleFunc(&myIdle);
	//利用定时器可以实现和函数flutIdleFunc相同的功能
	//glutTimerFunc(500,timerProc,1); 
	//SetupRC();
	glutMainLoop();
	return 0;
}


 

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页