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

来源:互联网 发布:电视网络机顶盒什么牌子的好 编辑:程序博客网 时间:2024/05/21 10:27

数据:利用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--2glColor3ub(255,0,0);//红//1--2glVertex3f(skeletonData[0], skeletonData[1], 0.999999);glVertex3f(skeletonData[3], skeletonData[4], skeletonData[5]);//2--3glColor3ub(0,255,0);//绿glVertex3f(skeletonData[3], skeletonData[4], skeletonData[5]);glVertex3f(skeletonData[6], skeletonData[7], skeletonData[8]);//2--4glColor3ub(0,0,255);//蓝glVertex3f(skeletonData[3], skeletonData[4], skeletonData[5]);glVertex3f(skeletonData[9], skeletonData[10], skeletonData[11]);//3--5glColor3ub(255,255,0);//黄glVertex3f(skeletonData[6], skeletonData[7], skeletonData[8]);glVertex3f(skeletonData[12], skeletonData[13], skeletonData[14]);//5--7glColor3ub(255,255,255);//白glVertex3f(skeletonData[12], skeletonData[13], skeletonData[14]);glVertex3f(skeletonData[18], skeletonData[19], skeletonData[20]);//4--6glColor3ub(255,0,255);//粉glVertex3f(skeletonData[9], skeletonData[10], skeletonData[11]);glVertex3f(skeletonData[15], skeletonData[16], skeletonData[17]);//6--8glColor3ub(255,128,0);//橙glVertex3f(skeletonData[15], skeletonData[16], skeletonData[17]);glVertex3f(skeletonData[21], skeletonData[22], skeletonData[23]);//2--9glColor3ub(0,255,255);glVertex3f(skeletonData[3], skeletonData[4], skeletonData[5]);glVertex3f(skeletonData[24], skeletonData[25], skeletonData[26]);//9--10glColor3ub(128,128,0);glVertex3f(skeletonData[24], skeletonData[25], skeletonData[26]);glVertex3f(skeletonData[27], skeletonData[28], skeletonData[29]);//9--11glColor3ub(128,128,128);glVertex3f(skeletonData[24], skeletonData[25], skeletonData[26]);glVertex3f(skeletonData[30], skeletonData[31], skeletonData[32]);//10--12glColor3ub(0,128,64);glVertex3f(skeletonData[27], skeletonData[28], skeletonData[29]);glVertex3f(skeletonData[33], skeletonData[34], skeletonData[35]);//12--14glColor3ub(64,0,64);glVertex3f(skeletonData[33], skeletonData[34], skeletonData[35]);glVertex3f(skeletonData[39], skeletonData[40], skeletonData[41]);//11--13glColor3ub(0,64,64);glVertex3f(skeletonData[30], skeletonData[31], skeletonData[32]);glVertex3f(skeletonData[36], skeletonData[37], skeletonData[38]);//13--15glColor3ub(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;}


 

0 0