节点是硬件设备的抽象概念,它的存在是为了便于用软件操作硬件设备,OpenNI生产节点,它是在创建以自然交互为基础进行数据交互的应用程序所需的过程中,生产数据的一组单位的集合。每一个生产节点能够使用其他底层的生产节点(读取它们的数据,控制它们的配置等),并且被其他上层节点所使用,或者被应用程序自身使用。
例如,应用程序要在一个3D场景中跟踪人形的动作,这就需要一个生产节点产生人形动作数据,换句话说,也就是用户生成器,它会从深度生成器中获取深度数据,分析深度数据进一步输出人形动作数据,在这里用户生成器使用深度生成器产生的深度数据,就是一个上层节点使用下层节点的例子。其中深度生成器是一个被传感器执行的生产节点,它从深度传感器取得原始感官数据,并输出深度图。
3.2.1 生产节点的类型
每一个OpenNI中的生产节点都有一个类型并且属于以下类别:传感器关联的生产节点、中间件关联的生产节点。OpenNI当前支持的生产节点的类型如图3-5所示。
图3-5 OpenNI所支持生产节点
1.传感器关联的生产节点
传感器关联的生产节点意思是一个节点关联一个物理设备(例如,一个深度生成器会关联一个深度传感器,或者一个图像生成器会关联一个RGB摄像机)。
·深度生成器:一个产生深度图的节点。该节点应该被任意兼容OpenNI的3D传感器执行。
·图像生成器:一个产生有颜色的影像图的节点。该节点应该被任意兼容OpenNI的色彩传感器执行。
·红外生成器:一个产生红外影像图的节点。该节点应该被任意兼容OpenNI的红外传感器执行。
·音频生成器:一个产生音频流的节点。该节点应该被任意兼容OpenNI的音频设备执行。
2.中间件关联的生产节点
中间件关联的生产节点意思是一个节点关联一个中间件。(例如,姿势通知生成器会关联一个名为NITE的中间件)。
·姿势通知生成器:当预定义好的姿势被标识,就会产生应用程序回调。
·场景分析器:分析一个场景,包含前后景分离、标识场景中的图形以及地板平面探测,场景分析器主要输出是带标签的深度图,其中每一个像素带有一个标签,该标签标识它是否为一个图形,或者它是否为背景的一部分。
·手心生成器:提供手掌探测和跟踪,该节点产生回调以便在手心被探测到,并且当前手心被跟踪且改变了位置的时候发出通知。
·用户生成器:产生一个3D场景的身体表示,包括用户的标识、用户的像素信息、用户的关节点信息、骨架信息等。
3.2.2 生产节点概念图
对于OpenNI应用来说,可能会应用到多个生产节点。多个生产节点在使用时会产生大量的数据,这些数据从生成器经过中间件,最后流向应用程序,从而构成了OpenNI中的数据流,生产节点概念图如图3-6所示。
图3-6 生产节点概念图
底层传感器关联的生产节点,产生最原始的数据,经过OpenNI框架的接口,流向中间件部分,中间件部分分析这些数据后,会产生更高一层次的数据,这些数据重新流向OpenNI框架中,并通过接口流向应用程序,被应用程序识别和使用。当然,底层传感器关联节点产生的数据也会直接流向应用程序,而不经过中间件,这就是用户或者开发者直接使用的最原始的数据了。
更高层次输出的概念是相对,它实际上就是经过OpenNI中间件处理过后输出的数据,相比最原始的数据,就是直接从传感器关联节点中产生的数据,比如深度生成器产生的深度数据,这些数据实际上是一个一个的深度;又或者图像生成器产生的RGB数据,这些数据并不能被人或者应用所直接识别、理解,而需要做出进一步的处理之后才能得到所需要的数据。而这些可以被理解的数据则被称为“有意义”的3D数据。创建有意义的3D数据是一项复杂的任务。典型的它开始于使用传感器产生一种原始的数据输出,以深度传感器为例,通常这个数据就是一个深度图,图上的每个像素表示其与传感器的距离,然后用专门的中间件处理原始输出的数据,生成更高层次的输出,这样就可以被应用程序理解和使用了。
以下是几个更高层次的输出常见例子。
1.用户手的位置
输出可以是掌心(一般叫做“hand point”)或指尖,如图3-7所示。这是手心生成器通过分析理解下层节点的数据后,产生的更高层次的数据。
图3-7 手心输出
2.场景中的人形标识
输出场景中人形的位置和接头方向(通常称为“body data”),如图3-8所示。这是用户生成器分析理解下层节点数据后产生的更高层次的输出。
图3-8 人形数据
3.手势识别
输出为应用程序的通知,通知应用程序一个特别的手势已经发生,如图3-9所示。这是姿势通知生成器分析理解下层节点数据后产生的更高层次的输出。
图3-9 手势识别
3.2.3 生成和读取数据
产生数据的生产节点叫做生成器,被创建后不会马上开始生成数据,以便于应用程序设置需要的配置,调用xn::Generator::StartGenerating()函数开始生成数据,应用程序也需要在不销毁节点的情况下停止生成数据,为了保存配置,可以用xn::Generator::StopGenerating()函数来实现。
数据生成器会不停地产生新的数据,而应用程序却不一定能及时地跟上数据生成器的速率,所以应用程序很有可能使用旧的数据,考虑到这个问题,OpenNI采用了Updatedata函数机制,即任何数据生成器在内部存储新数据,直到明确要求更新到最新的可用数据,才会把最新的数据交给应用程序,这意味着数据生成器在内部隐藏新数据,直到使用Updatedata请求函数明确要求更新的数据再交给应用程序。OpenNI让应用程序用xn::Generator::WaitAndUpdatedata()函数等待最新的数据,然后更新它。
在某些情况下,应用程序拥有多个节点,并希望对所有的节点进行更新。OpenNI提供多个函数通过Updatedata来更新数据,如表3-7所示。
表3-7 Updatedata机制下的函数
OpenNI中有生产数据这样的概念,所以相应的就会有存储数据的概念,为了便于记录以下类型的生成节点类型被提供:
·记录器(recorder):执行数据记录。
·播放器(player):从记录中读取数据并播放。
·编码器(codec):用于在记录中压缩或解压缩数据。
3.2.4 OpenNI接口的配置
因为OpenNI中的节点是可配置的,所以每个OpenNI接口的配置都会包括以下功能:
·针对修改配置的set函数。
·提供一个获取当前值的get函数。
·当生产节点存在回调函数时,节点会提供注册和注销函数,使能够注册回调函数,当选项改变时回调函数被调用。