自然交互(NI)是一种以人类感官为基础的人机交互概念,主要关注视觉和听觉感官。PrimeSense的NITE™是感知3D世界并将其转化为有意义的数据的中间件,类似于人类的方式。NITE作为感知引擎,理解用户在其环境中的交互,并包含计算机视觉算法。
本章提供了一个简单的步骤教程,描述了如何启动一个简单的NITE项目。
首先,需要下载并安装以下软件:
本节描述了如何在Windows上设置环境,使用NITE开发自己的应用程序。
要使用NITE创建一个简单项目,请按照以下步骤操作:
虽然Windows和Linux平台包都可以下载,但本文档仅介绍如何在Windows上使用。
本节列出了创建“Hello World”NI应用所需的代码部分。
需要包含OpenNI和NITE头文件:
// 通用头文件
#include <stdio.h>
// OpenNI头文件
#include <XnOpenNI.h>
// NITE头文件
#include <XnVNite.h>
XnOpenNI.h将包含任何所需的OpenNI头文件。XnVNite.h将包含任何所需的NITE头文件。
初始化OpenNI应用程序有两种方式:(i)显式打开传感器并启动流;(ii)隐式使用XML文件。后者允许应用程序更灵活,通过允许在不重新编译应用程序的情况下更改传感器/流。
// 使用xml初始化OpenNI
#define SAMPLE_XML_FILE "../Data/Sample-Tracking.xml"
现在将添加应用程序的全局变量。
XnBool g_bQuit = false;
XnVSessionManager* g_pSessionManager = NULL;
static XnUInt32 g_nWaveCounter = 1;
注意,g_pSessionManager对象也可以是局部变量,但为了简单和更容易的清理,决定将其作为全局变量使用。
在这种情况下,回调函数用于事件处理。就像希望应用程序在鼠标点击或按键时触发处理函数一样。也希望当NI事件发生时,应用程序会触发NI处理函数,即回调函数。
// 会话开始的回调
void XN_CALLBACK_TYPE SessionStart(const XnPoint3D& ptFocusPoint, void* UserCxt) {
printf("Session started. Please wave ...\n");
}
// 会话结束的回调
void XN_CALLBACK_TYPE SessionEnd(void* UserCxt) {
printf("Session ended. Please perform focus gesture to start session\n");
}
// 挥手检测的回调
void XN_CALLBACK_TYPE OnWaveCB(void* cxt) {
printf("Hello World - Wave number: %d!\n", g_nWaveCounter);
if (2 <= g_nWaveCounter)
CleanAndExit();
++g_nWaveCounter;
}
在主函数中,将初始化整个OpenNI和NITE组件,并创建一个无限循环,不断从传感器读取数据,NITE将分析这些数据。
首先,需要初始化OpenNI入口点,即xn::Context:
xn::Context context;
xn::ScriptNode scriptNode;
// 创建上下文
XnStatus rc = context.InitFromXmlFile(SAMPLE_XML_FILE, scriptNode);
if (rc != XN_STATUS_OK) {
printf("Couldn't initialize: %s\n", xnGetStatusString(rc));
return 1;
}
在这里,通过使用位于SAMPLE_XML_FILE路径的XML文件隐式初始化上下文。这样的文件可以在NITE安装文件夹的Data文件夹下找到。
其次,需要初始化NITE入口点,即XnVSessionManager:
// 创建会话管理器
g_pSessionManager = new XnVSessionManager();
if (NULL == g_pSessionManager) {
printf("Out of memory\n");
CleanAndExit();
}
rc = g_pSessionManager->Initialize(&context, "Click,Wave", "RaiseHand");
if (rc != XN_STATUS_OK) {
printf("Error: SessionManager: %s\n", xnGetStatusString(rc));
CleanAndExit();
}
// 注册会话回调
g_pSessionManager->RegisterSession(NULL, &SessionStart, &SessionEnd, NULL);
使用可以用于提取深度流的OpenNI上下文初始化会话管理器,并预定义了焦点和快速重新聚焦手势。
在这里,为了开始NI会话,需要执行Wave手势或Click手势。一旦进入NI会话,手将被跟踪,以便检测其他基于手点的手势(控制)。如果由于某种原因跟踪丢失,例如,手离开了视场(FOV),会话将在RaiseHand事件发生时继续,例如,手返回到FOV。
这段代码的最后一部分是注册会话函数回调。这将使能够在屏幕上打印会话开始时(SessionStart())的消息,即用户执行了焦点手势。当会话结束时(SessionEnd()),即没有手点可用并且快速重新聚焦宽限期结束(=默认宽限期时间为15秒)。
现在需要创建并初始化一个检测Wave手势的NITE树。这是一个非常简单的NITE树,只包含一个分支:XnVWaveDetector:
// 初始化并注册wave控制
XnVWaveDetector wd;
wd.RegisterWave(NULL, OnWaveCB);
g_pSessionManager->AddListener(&wd);
// 初始化完成。开始生成
context.StartGeneratingAll();
首先,实例化一个Wave Detector;wd。然后,注册Wave回调函数,一旦检测到wave,该函数将被调用。然后通过将其添加到手点的监听器列表中,将Wave Detector连接到会话管理器。
一旦NITE树完成,可以调用StartGeneratingAll()函数,该函数将开始生成流。
由于希望不断从传感器读取数据并相应地更新NITE组件,需要创建一个无限循环,不断读取传感器流并用它们更新NITE树。
// 主循环
while (!g_bQuit) {
context.WaitAnyUpdateAll();
g_pSessionManager->Update(&context);
}
NIHelloWorld.zip文件包含一个Windows项目,其中包含本文档中描述的示例代码。
如果有一个与OpenNI兼容的深度传感器,并且已经按照本文档中的说明操作,将能够编译并运行此示例。需要将传感器连接到计算机并运行应用程序。
一旦应用程序运行,站在传感器前约1米到2.5米的距离。执行焦点手势以开始会话;Wave或Click。为了执行Click手势,需要将手向前伸展朝向传感器,然后稍微向后收回手,动作要平滑,如下图所示。
图3-1:“Click”焦点手势
一旦获得了焦点,将收到一个打印的通知,表明它,并且将能够执行Wave手势在屏幕上打印“Hello World”消息。为了退出应用程序,需要执行Wave手势两次。