最近越来越觉得封装一个模块之前,得写个文档来整理下思路,可以达到事半功倍的效果

 

   使用Kinect来获取关节点位置计算关节的旋转角,用于做mesh deformation

 

-------------------------

Kinect模块

 

要完成的事:

 

1.  生成用于显示的图像信息,使用opencv进行

<1>    显示深度图

           需要传入深度图元数据DepthMetaData的对象,可以传入其指针

<2>    显示骨骼

           需要获得骨骼的二维坐标,openni里的做法是使用UserGenerator里的骨骼功能获取指定的关节对象,使用枚举变量来指定具体的关节

    然后使用DepthGeneratorConvertRealWorldToProjective将关节点的空间坐标转换到投射坐标,用投射坐标来绘制关节点

 

<3>    显示文字信息

           显示什么文字,以及在什么位置显示文字,什么时候显示文字,对于这些信息均需要了解,可以存储几个全局变量来存放这些信息

           在程序中的其他位置更改这些全局变量,而在绘图处则仅需简单的使用这些全局变量

 

绘图的顺序应该遵循先绘制深度图,然后骨骼,然后文字的顺序,以防止覆盖

 

 

2.  获取关节点位置

获取所有的关节点位置,存放于一个数组当中,这个数组用于

<1> 提取出5个树枝的三维数组,用于计算旋转角

<2> 获取关节点的二维坐标,用于1中的骨骼绘制

 

Openni里使用XnSkeletonJointPosition来存储关节点

typedef struct XnSkeletonJointPosition

{

    XnVector3D    position;

    XnConfidence  fConfidence;

} XnSkeletonJointPosition;

 

XnSkeletonJoint这个枚举对象用来指定关节点

typedef enum XnSkeletonJoint

{

    XN_SKEL_HEAD         = 1,

    XN_SKEL_NECK         = 2,

    XN_SKEL_TORSO        = 3,

    XN_SKEL_WAIST        = 4,

 

    XN_SKEL_LEFT_COLLAR      = 5,

    XN_SKEL_LEFT_SHOULDER    = 6,

    XN_SKEL_LEFT_ELBOW       = 7,

    XN_SKEL_LEFT_WRIST       = 8,

    XN_SKEL_LEFT_HAND    = 9,

    XN_SKEL_LEFT_FINGERTIP   =10,

 

    XN_SKEL_RIGHT_COLLAR =11,

    XN_SKEL_RIGHT_SHOULDER   =12,

    XN_SKEL_RIGHT_ELBOW      =13,

    XN_SKEL_RIGHT_WRIST      =14,

    XN_SKEL_RIGHT_HAND       =15,

    XN_SKEL_RIGHT_FINGERTIP  =16,

 

    XN_SKEL_LEFT_HIP     =17,

    XN_SKEL_LEFT_KNEE    =18,

    XN_SKEL_LEFT_ANKLE       =19,

    XN_SKEL_LEFT_FOOT    =20,

 

    XN_SKEL_RIGHT_HIP    =21,

    XN_SKEL_RIGHT_KNEE       =22,

    XN_SKEL_RIGHT_ANKLE      =23,

    XN_SKEL_RIGHT_FOOT       =24

} XnSkeletonJoint

 

所以可以定义一个XnSkeletonJoint的数组,然后向这个数组填充数据

 

添加回调程序来了解程序的状态:

 

m_UserGenerator.RegisterUserCallbacks( User_NewUser, User_LostUser, NULL, hUserCallbacks );

 

m_UserGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_ALL);

 

m_UserGenerator.GetSkeletonCap().RegisterCalibrationCallbacks(&CalibrationStart, &CalibrationEnd, NULL, hCalibrationCallbacks);

    m_UserGenerator.GetPoseDetectionCap().RegisterToPoseCallbacks(&User_PoseDetected, NULL, NULL, hPoseCallbacks);

这里分别为新增用户、丢失用户,姿势检测,用户标定开始和用户标定结束注册了回调函数

这几个回调函数发生的顺序分别是

新增用户à姿势检测à用户标定开始à用户标定结束,丢失用户在用户丢失的时候发出通知

 

要获取骨骼数据,必须要开启姿势识别,使用UserGenerator里面的SkeletonCapability对象成员的函数StartPoseDetection("Psi", user);

 

这样在Psi姿势检测成功的时候就会调用上面注册的回调函数,姿势检测成功并不意味着骨骼的检测成功(用户成功被标定),但是要使骨骼被成功检测,则必须是姿势先检测成功,姿势检测成功是骨骼检测成功的充分不必要条件

 

在用户标定结束的回调函数里面有参数指明用户是否被成功标定,假如标定失败,则要重新开始姿势检测

 

从这里可以看出,回调函数做的主要的事可以是报告程序的状态,以及在用户没被成功标定的情况下重启姿势检测

 

 

 

关节数据的填充:

调用UserGeneratorSkeletonCapability成员的方法

GetSkeletonJointPosition(XnUserID user, XnSkeletonJoint eJoint, XnSkeletonJointPosition& Joint)可以获取关节点位置

 

在哪里对关节点数组进行填充?

关节点在骨骼成功标定后,每一帧都会发生更新,所以要在每一帧都对关节点数组进行填充,可以在调用绘制深度图函数的那个函数里,在这里面要先做一个判断,即用户标定是否成功,假如成功,才可以对关节数组进行更新

 

使用UserGenerator里的SkeletonCapability对象的IsTracking函数可以获得指定的用户已经被成功标定并正被跟踪,假如IsTracking返回真,就获取所有的关节点数据

 

3.关节点数组的后处理

   openni获取的关节点经常是不全的,所以对于一些关键点,需要进行补全或者是在遇到错误关节点的时候,进行怎么样的处理

    为了更好的进行处理,首先从这些关节点中把人体五个肢体的关节点提取出来,即左右手、左右腿、躯干,然后在这五个肢体中进行补全或其他处理

  

 

posted on 2011-05-09 09:28  柯大侠  阅读(1086)  评论(0编辑  收藏  举报