数据:利用
kinect
已经将人体骨架的三维坐标提取出来,并保存在一个
txt
文档里面
目的:将三维坐标在屏幕上显示出来。
工具:openGL
通过查阅资料和老师的指导,如果想把三维坐标在屏幕上显示出来,要先转换成二维坐标,因为屏幕上显示的都是二维数据,就比如一张图片上面的像素点都是二维数据(x,y),即便有通道数,也是用二维来表示的。而能实现这个功能的工具有openGL、Direct3D、java3D。通过查看《OpenGL入门教程(精)》,知道里面有将三维坐标显示的函数glVertex3f(1.0f, 3.0f, 0.0f);所以打算用openGL实现。
一:openGL简介
OpenGL(英语:Open
看以上的的介绍,可以知道,openGL可以跨平台,而Direct3D只能在微软的系统上运行的API。微软为了推广自己的Direct3D,自从在VC6.0上这个也是老师建议学习一下API的原因,虽然只是皮毛。
进入正题:
首先,要配置openGL
第一步:下载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
下面就是区别了,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目录下应该已经有
把GL.H, GLAUX.h, glu.h,glut.h
把
接下来:实现三维坐标的显示。
遇到的问题1:由于我有15个骨骼点每一帧上面,所有我需要把这15个骨骼点显示出来,并且用直线连接起来,实现一帧图像中骨骼的重建。但是如果用线连起来之后,就有分不清楚点在哪的可能。比如:一条直线上可能有三个点,但是由于没有弯曲,所以会以为只有两端的两个点(或者只有弯曲处的点),为了解决这个问题,可以在三维点的周围画出一个圆球或者方块。也就是为了将是三维点的地方凸显出来。但是由于openGL要求:指定顶点的命令必须包含在glBegin 函数之后,glEnd 函数之前(否则指定的定点将被忽略),并由glBegin 来指明如何使用这些点。举例说明下:
glBegin(GL_POINTS);
glEnd();
就是不管你是画点,画线,画多边形,等,要在glbegin和glEnd之间。和MFC中的路径层的定义差不多。
那么问题又来了,为什么openGL要这么做呢?
自然是有道理的:
假设现在我已经指定了若干顶点,那么 OpenGL 是如何知道我想拿这些顶点来干什么呢?是一个一个的画
出来,还是连成线?或者构成一个多边形?或者做其它什么事情?
问题2:如果在给定的glBegin和glEnd中,我只能画给定的几种图形中的一个,不知道怎么既画Line又画圆或者方块之类的东西(应该能实现,但是我没有找到办法)。
解决办法:
为了解决以上两个问题,既能凸显出点存在的位置,又能将骨架显示出来(也就是将点用线连上)。我将每两点的连线用不同的颜色表示,同时将显示的颜色变的粗一些(openGL里面有函数void glLineWidth(GLfloat
问题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;
}