openGL将三维坐标转换成二维坐标在…
数据:利用kinect已经将人体骨架的三维坐标提取出来,并保存在一个txt文档里面
目的:将三维坐标在屏幕上显示出来。
工具:openGL
通过查阅资料和老师的指导,如果想把三维坐标在屏幕上显示出来,要先转换成二维坐标,因为屏幕上显示的都是二维数据,就比如一张图片上面的像素点都是二维数据(x,y),即便有通道数,也是用二维来表示的。而能实现这个功能的工具有openGL、Direct3D、java3D。通过查看《OpenGL入门教程(精)》,知道里面有将三维坐标显示的函数glVertex3f(1.0f, 3.0f, 0.0f);所以打算用openGL实现。
一:openGL简介
OpenGL(英语:Open Graphics Library)是个定义了一个跨编程语言、跨平台的应用程序接口(API)的规范,它用于生成二维、三维图像。这个接口由近三百五十个不同的函数调用组成,用来从简单的图形比特绘制复杂的三维景象。而另一种程序接口系统是仅用于MicrosoftWindows上的Direct3D。OpenGL常用于CAD、虚拟实境、科学可视化程序和电子游戏开发。(来自维基百科)
看以上的的介绍,可以知道,openGL可以跨平台,而Direct3D只能在微软的系统上运行的API。微软为了推广自己的Direct3D,自从在VC6.0上这个也是老师建议学习一下API的原因,虽然只是皮毛。
进入正题:
首先,要配置openGL GLUT(gl使用工具包)的环境(转)
第一步:下载OpenGL的GLUT库
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.LIB、Glu32.lib、glut32.lib、Opengl32.lib,glut.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:WINDOWSsystem32目录下,system32目录下应该已经有 opengl32.dll, glu32.dll了。
把GL.H, GLAUX.h, glu.h,glut.h 拷贝到 C:Program FilesMicrosoft Visual Studio9.0VCincludegl
把 GLAUX.LIB、Glu32.lib、glut32.lib、Opengl32.lib,glut.lib拷贝到 C:Program FilesMicrosoft Visual Studio9.0VClib
接下来:实现三维坐标的显示。
遇到的问题1:由于我有15个骨骼点每一帧上面,所有我需要把这15个骨骼点显示出来,并且用直线连接起来,实现一帧图像中骨骼的重建。但是如果用线连起来之后,就有分不清楚点在哪的可能。比如:一条直线上可能有三个点,但是由于没有弯曲,所以会以为只有两端的两个点(或者只有弯曲处的点),为了解决这个问题,可以在三维点的周围画出一个圆球或者方块。也就是为了将是三维点的地方凸显出来。但是由于openGL要求:指定顶点的命令必须包含在glBegin 函数之后,glEnd 函数之前(否则指定的定点将被忽略),并由glBegin 来指明如何使用这些点。举例说明下:
glBegin(GL_POINTS);
glVertex2f(0.0f,0.0f);
glVertex2f(0.5f, 0.0f);
glEnd();
就是不管你是画点,画线,画多边形,等,要在glbegin和glEnd之间。和MFC中的路径层的定义差不多。
那么问题又来了,为什么openGL要这么做呢?
自然是有道理的:
假设现在我已经指定了若干顶点,那么 OpenGL 是如何知道我想拿这些顶点来干什么呢?是一个一个的画
出来,还是连成线?或者构成一个多边形?或者做其它什么事情?
问题2:如果在给定的glBegin和glEnd中,我只能画给定的几种图形中的一个,不知道怎么既画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 ", 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; }
- 上一篇: matlab中可视化二维矩阵 imagesc
- 下一篇: SQL一维数据转二维