当前位置:首页  <  应用教程  <  【创客学堂】基于Kinect的实例教程及硬件介绍(三)...
【创客学堂】基于Kinect的实例教程及硬件介绍(三)
编辑:Xtm 2014-08-04 浏览次数:833

 

    上篇文章我们介绍了SimpleOpenNI开发平台搭建,今天小编继续为大家讲解kinect绘制深度图与绘制人体躯干实例具体操作过程!

 

一 、用kinect绘制深度图

 

    
    Kinect+OpenNI允许用户获得深度图像,一个红外发射头负责发射红外,另一个负责接受,这样的话我们就获得了背影射物体离摄像头有多少个像素点,也就是有多远。
    在processing里面每一个工程被称为sketch而不是一般软件的Project因为Processing的程序运行起来更像是画家在纸上画的草图,素描风明显。
    为了让深度图在电脑上显示出来,获得用户想要的数据,我们就必须导入OpenNI,目的是导入打包好OpenNI数据,所以 首先导入数据包(库的思想).
--------------------------------------------------------
import SimpleOpenNI.*;
---------------------------------------------------------
    接下来我们声明一个全局对象,context来和Kinect来取得数据联系
 
--------------------------------------------------------
SimpleOpenNI  context;
---------------------------------------------------------
    接下来我们来看看setup()函数,要知道一个事情,就是setup()函数里面所有的内容只执行一遍,而且只是程序一开始的阶段才被执行。
--------------------------------------------------------
void setup()
{
  // 建立新的对象
  context = new SimpleOpenNI(this);
 
  // 使能深度影响
  context.enableDepth();
 
  // 创建一个这样的尺寸,它可以保证装下深度的一切信息
  size(context.depthWidth(), context.depthHeight()); 
}
---------------------------------------------------------
    接下来我们来看一下Draw()里面的 函数,有关于draw()函数,它是无限循环运行的,频率是每秒60次
 -------------------------------------------------------
void draw()
{
  //不断更新来自Kinect Camera的数据
  context.update();
 
  // 绘制深度图
  image(context.depthImage(),0,0); 
}
---------------------------------------------------------
    Context.update()函数对每一帧的数据都有更新动作
    运行sketch 的结果如图所示: 
运行sketch 的结果 
代码解析如下:
 
import SimpleOpenNI.*;
 
SimpleOpenNI  context;
 
void setup()
{
  // instantiate a new context
  context = new SimpleOpenNI(this);
 
  // enable depth image generation 
  context.enableDepth();
 
  // create a window the size of the depth information
  size(context.depthWidth(), context.depthHeight()); 
}
 
void draw()
{
  // update the camera
  context.update();
 
  // draw depth image
  image(context.depthImage(),0,0); 
}
---------------------------------------------------------------------
如果知道了深度信息,你有什么想法?
这个问题很值得在这里,仔细的思考一下,你打算做点什么?
或者是现在你没有太多想法,但是接下来的案例中我要求你必须有自己的想法,就算不会码代码。
 

二、 绘制人体躯干

 

    首先呢,先要普及一下知识,有关于3D空间距离计算的知识,
    在三D空间里,距离的计算,和我们在高中学得向量计算是一个道理的,下面从2D空间说起:
 
X1=2   X2=9          
 
 
 
直线由两个点构成,坐标如上图已给出.
       
 
 ----------------------------------(直角三角形关系)
 --------------------------------(a的坐标距离表示)
 ---------------------------------(b的坐标距离表示)
 --(同样符合三角形边的关系)
 --------(过渡到2D空间距离)
关键就是3D空间距离,多加了一个Z坐标
 
 
上面那个公式就是3D空间里点之间里的公式。
那么怎么在代码里实现计算3D空间两点间距离。
首先,定义一个新的函数
distances3D( )
void distance3D(PVector point1, PVector point2)
{
}
 
在函数里面首先我们要添加一些变量来储存xyz 的值,我们还需要一个变量来储存最终的结果也就是返回值
  float diff_x, diff_y, diff_z;    // 储存x,y,z的值
  float distance;                 // 来储存最后的返回值(结果也就是距离)
 
 接下来计算两个点之间的xyz的差值
 
 diff_x = point1.x - point2.x;
 diff_y = point1.y - point2.y;
 diff_z = point1.z - point2.z;
之后就是简单的计算
return distance;  // return the distance as a float
整理之后的代码就是:
float distance3D(PVector point1, PVector point2
){
float diff_x, diff_y, diff_z;   
   float distance;                 
   diff_x = point1.x - point2.x;
   diff_y = point1.y - point2.y;
   diff_z = point1.z - point2.z; 
   distance = sqrt(pow(diff_x,2)+pow(diff_y,2)+pow(diff_z,2)); 
   return distance; 
}
写好程序之后,运行结果就是这个深度图人体躯干的形态,其中黑色是后加工的,人体颜色也是加工过的。
 运行成功

三、望有所思

    看完这个例子千万别无动于衷,这回你一定要有好的想法,比如你想获得键盘映射操控键盘获得鼠标映射控制鼠标、或者是直接获得图形映射和控制图形变化,或许你能写出个好玩的游戏。
    这个话题先放一放,贪吃蛇的平台移植会很简单,所以以后我们一定要试一试,最终的结果就是:用手势控制蛇的运动方向从而控制蛇去吃更多的食物。
    基础教程这里做一个完结,基础教程完毕。请期待下几期的更新!
              基于Kinect的实例教程及硬件介绍(二)