用户生成器(User Generator)是OpenNI的重要核心,体感开发中被广泛使用的骨骼,以及姿势侦测(Pose Detect)都注册在用户生成器下面,而用户生成器自身也包含了许多重要的功能。
6.4.1 获取用户数量
1.实例
对于Xtion设备来说,深度感应器可以感应到的范围内用户的数量可以不仅仅只有一个,因此,在一些应用中,获知感应器范围内感应到的用户数量也是体感开发中的一个重要的需求。
2.实现方法
OpenNI中提供了GetNumberOfUsers()函数用于获取当前用户数量,调用该函数会返回一个XnUInt16类型的变量,也就是用户的数量,使用代码如下。
// GetNumberOfUsers xn::UserGenerator mUserGenerator; XnUInt16 nUsers; nUsers = mUserGenerator.GetNumberOfUsers();
代码中在使用GetNumberOfUsers()函数之前需要定义一个XnUInt16类型的变量nUsers,而后通过调用mUserGenerator下的GetNumberOfUsers,并将返回的用户数量值传递给nUsers,此时nUsers的值代表的就是用户的数量。
6.4.2 获取用户
1.实例
用户的信息包括很多方面,在实际使用中获得用户本质上就是为了进一步地获取用户的详细信息,比如骨架节点之类的数据。而获得的用户本来的面目是一个用户的ID,也就是说实际上后续获取用户详细信息的方法也就是使用获取用户时拿到的用户ID。
2.实现方法
获取用户的前提是要获取用户的数量,而后根据数量开辟一定空间的内存用于存放用户ID,其方法如下。
// GetUsers xn::UserGenerator mUserGenerator; XnUInt16 nUsers = mUserGenerator.GetNumberOfUsers(); XnUserID* aUserID = new XnUserID[nUsers]; mUserGenerator.GetUsers(aUserID,nUsers);
首先使用获取用户数量的方法获取用户数量,然后根据用户数量开辟相应的存储空间用于存放即将取得的用户信息,而后调用mUserGenerator下的GetUsers函数,并传入存储空间以及用户数量两个参数,函数运行的结果就是把每一个用户的ID存储在aUserID这个XnUInt16类型的数组中。
6.4.3 获取用户质心
1.实例
得知一个用户的位置的方法就是获得该用户的质心,因为用户的位置在深度图中所显示的实际上是一个坐标,所以通常以质心的坐标作为用户的位置坐标。
2.实现方法
在用户生成器中,有用于获取用户质心的函数GetUserCoM,调用该函数会返回给调用者一个XnPoint3D类型的点,该点就是用户的质心,具体使用见下面的代码:
// GetUserCoM xn::UserGenerator mUserGenerator; XnUInt16 nUsers; nUsers = mUserGenerator.GetNumberOfUsers(); XnUserID* aUserID = new XnUserID[nUsers]; mUserGenerator.GetUsers(aUserID,nUsers); XnPoint3D* UserCoM = new XnPoint3D[nUsers]; for (int i=0;i<nUsers;i++) mUserGenerator.GetCoM(aUserID[i],UserCoM[i]); // 获取用户质心
想要获取用户的质心,首先还是要获取用户数量,而后获取用户ID,有了用户ID之后,就可以根据用户的ID来获得用户的质心,前面的两步也是获取其他一些用户信息所需要的前提步骤。
完成前提步骤之后就可以调用用户生成器mUserGenerator下的GetCoM()函数,这里需要传递进去的参数就是用户的ID和用于存储用户质心点数据的XnPoint3D类型的变量,例中这两者分别为aUserID[i]和UserCoM[i],在函数调用完成之后,UserCoM[i]中的数据就是用户aUserID[i]的质心所在的位置。
6.4.4 获取用户像素
1.实例
深度图实际上是一张像素格式大小的深度信息图,直观来说是一张按一定顺序数量排列的数字值,源图片里的数据是无法被开发者或者程序直接识别的,不过用户生成器中提供了可以识别深度图中用户所在位置的像素的算法,也就是说,通过调用用户生成器下的函数,开发者可以获得深度图中表示用户的那一块像素图,从而过滤掉其他信息,只针对用户部分的像素进行单独分析。
2.解决方法
OpenNI中的用户生成器下定义了GetUsersPixels(),用于获取用户的像素,该函数返回的是一个SceneMetaData类型的数据,也就是一个场景元数据对象,用于存放用户部分的像素,具体使用方法如下代码所示:
// GetUserPixels xn::UserGenerator mUserGenerator; XnUInt16 nUsers; nUsers = mUserGenerator.GetNumberOfUsers(); XnUserID* aUserID = new XnUserID[nUsers]; mUserGenerator.GetUsers(aUserID,nUsers); xn::SceneMetaData* SceneMD = new xn::SceneMetaData[nUsers]; for (int i=0;i<nUsers;i++) mUserGenerator.GetUserPixels(aUserID[i],SceneMD[i]);
因为需要使用到用户ID,所以要通过两个基本步骤获取用户ID,首先要获取用户数量,而后获取用户,取得ID。获得用户ID之后,就可以进入获取用户像素的步骤了,首先定义一组SceneMetaData类型的元数据对象,然后根据每一个用户ID,调用用户生成器下的GetUserPixels(),并传入用户ID,以及用于存储用户像素的场景元数据对象,这样传递进去的元数据对象就可以获取到对应ID的用户的像素了。例中使用的场景元数据对象名为SceneMD。在函数调用完成之后,用户aUserID[i]所对应的用户区域像素就存储在对应的元数据对象SceneMD[i]中了。
6.4.5 注册用户回调函数
1.实例
在针对用户进行的体感开发过程中,有两个最为重要的基本事件,设备使用范围内发现一个新的用户,以及一个用户在设备范围内丢失,这两个不同的事件对于OpenNI应用的用户设置起着至关重要的作用,在OpenNI中,对于这两个事件的发现,采用了回调函数机制,而开发者在使用这类函数之前,首先需要注册函数。
2.实现方法
发现新用户和丢失用户这两个事件都是属于用户生成器下的,所以注册这两个事件回调函数的地方也是用户生成器,在OpenNI中使用RegistertoUserCallbacks()函数进行注册,其具体的使用方法如下代码所示。
// RegistertoUserCallbacks xn::UserGenerator mUserGenerator; XnCallbackHandle hUserCB; mUserGenerator.RegisterUserCallbacks(NewUser,LostUser,NULL,hUserCB);
注册步骤只需要在用户生成器下调用RegisterUserCallbacks()函数即可,用户生成器的注册有两个事件,一个是发现一个新用户,一个是丢失用户,例中将这两个事件的回调函数命名为NewUser和LostUser,后面还跟着一个参数为回调函数的句柄,即本例中的hUserCB。
6.4.6 获取骨架功能
1.实例
用户生成器之所以称为OpenNI中的核心部分,主要原因之一就是骨架功能是属于用户生成器中的。所以在很多体感开发应用中,通过用户生成器获取其骨架功能,然后使用骨架功能下所属的功能函数,是体感开发过程中重要的方法之一。
2.解决方法
因为获取的是骨架功能,所以需要事先定义一个SkeletonCapability类型的变量,而后调用用户生成器下的GetSkeletonCap()函数,来获取骨架功能,具体代码如下。
// GetSkeletonCapability xn::UserGenerator mUserGenerator; xn::SkeletonCapability mSC = NULL; mSC = mUserGenerator.GetSkeletonCap();
例中定义了SkeletonCapability类型变量为mSC,而后调用用户生成器mUserGenerator下的GetSkeletonCap()函数获取骨架功能并传递给变量mSC,而后就可以通过mSC操作用户生成器的骨架功能下属的功能了。
6.4.7 获取姿势侦测功能
1.实例
在OpenNI中有骨架校准的概念,校准的前提就是首先要对用户进行姿势侦测,所以就需要调用用户生成器中的姿势侦测功能。获取姿势侦测功能的方法实际与上一节中获取骨架功能的方法类似。
2.解决方法
获取姿势侦测功能需要事先定义一个PoseDetectionCapability类型的变量,用于存储获得的姿势侦测功能,具体实现代码如下。
// GetPoseDetectionCap xn::UserGenerator mUserGenerator; xn::PoseDetectionCapability PDCap = NULL; PDCap = mUserGenerator.GetPoseDetectionCap();
例中定义了一个PoseDetectionCapability类型的变量PDCap,而后调用用户生成器mUserGenerator下的GetPoseDetectionCap()函数,接下来就可以通过PDCap调用姿势侦测功能了。