65.9K
CodeProject 正在变化。 阅读更多。
Home

如何创建简单的自然交互(NI)应用程序。

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2011 年 9 月 22 日

CPOL

6分钟阅读

viewsIcon

30843

downloadIcon

309

本文档为初学者 NI 程序员简要介绍了如何创建简单的“Hello World”手势应用程序。它包含环境依赖项下载页面链接、带解释的代码段和示例源代码。

引言

OpenNI 是一个易于使用的友好平台,用于自然交互(NI)编程以创建 NI 应用程序。

本文档为初学者 NI 程序员简要介绍了如何创建简单的“Hello World”NI 应用程序。

自然交互(NI)是指一种概念,其中人与设备的交互基于人类的感官,主要集中在视觉和听觉感官。NITE™(由 PrimeSense 提供)是中间件,它基于深度图像以 3D 方式感知世界,并以与人类相同的方式将这些感知转化为有意义的数据。NITE 作为感知引擎,可以理解用户在其周围环境中的交互,并包含计算机视觉算法。

入门

本章提供了一个简单的分步教程,介绍如何启动一个简单的 NITE 项目。

1.1 安装必要的软件

首先,您需要下载并安装所需的相应软件(SW)。

  1. OpenNI
  2. NITE 中间件
  3. 传感器相关软件(驱动程序)

1.2 创建一个使用 NITE 的空项目

1.2.1 在 Windows 上

本节介绍如何在 Windows 上设置您的环境,以便使用 NITE 开发自己的应用程序。

创建使用 NITE 的简单项目

  1. 创建一个新的 Visual Studio 项目,或打开一个现有项目,您想在其上使用 NITE。
  2. 在 Visual Studio 菜单中,打开“项目”菜单,然后选择“项目属性”。
  3. 在“C/C++”部分下的“常规”节点中,找到“附加包含目录”,然后添加环境变量 $(OPEN_NI_INCLUDE) 的值(默认位置为 C:\Program files\OpenNI\Include)。还要添加环境变量 $(XN_NITE_INSTALL_PATH) 的值,后跟 \Include(默认位置为 C:\Program files\Prime Sense\NITE\Include)。
  4. 在“链接器”部分下的“常规”节点中,找到“附加库目录”,然后添加环境变量 $(OPEN_NI_LIB) 的值(默认位置为 C:\Program files\OpenNI\Lib)。还要添加环境变量 $(XN_NITE_INSTALL_PATH) 的值,后跟 \Lib(默认位置为 C:\Program files\Prime Sense\NITE\Lib)。
  5. 在“链接器”部分下的“输入”节点中,找到“附加依赖项”,然后在字段中添加 openNI.lib XnVNITE_1_4_1.lib 库。
  6. 在“调试”部分,找到“工作目录”,并将 $(TargetDir) 添加到该字段。此添加将允许您调试应用程序。

1.2.2 在 Linux 上

Windows 和 Linux 平台都有可供下载的软件包,但是,本文档仅描述如何使用 Windows 版本。

实际代码

本节列出了 Hello World NI 应用程序所需的代码部分。

2.1 添加全局项

您需要包含 OpenNI 和 NITE 的头文件。

// General headers
#include <stdio.h>
// OpenNI headers
#include <XnOpenNI.h>
// NITE headers
#include <XnVNite.h>

XnOpenNI.h 将包含任何其他必需的 OpenNI 头文件。XnVNite.h 将包含任何其他必需的 NITE 头文件。

初始化 OpenNI 应用程序有两种方法:(i)显式打开传感器并初始化流;或(ii)通过使用 XML 文件隐式初始化。后者通过允许在不重新编译应用程序的情况下更改传感器/流,为应用程序提供了更大的灵活性。

// xml to initialize OpenNI
#define SAMPLE_XML_FILE "../Data/Sample-Tracking.xml"

现在我们将添加应用程序的全局变量。

XnBool g_bQuit = false;
XnVSessionManager* g_pSessionManager = NULL;
static XnUInt32 g_nWaveCounter = 1;

请注意,g_pSessionManager 对象也可以是局部变量,但为了简单起见并便于清理,我决定将其用作全局变量。

2.2 添加回调函数

在此情况下,回调函数用于事件处理。正如您希望应用程序在鼠标或键盘单击鼠标按钮或按键时触发您的处理函数一样。当发生 NI 事件时,您也希望应用程序触发 NI 处理函数,即回调函数。

// callback for session start
void XN_CALLBACK_TYPE SessionStart(const XnPoint3D& ptFocusPoint, void* UserCxt)
{
  printf("Session started. Please wave ...\n");
}
// Callback for session end
void XN_CALLBACK_TYPE SessionEnd(void* UserCxt)
{
  printf("Session ended. Please perform focus gesture to start session\n");
}
// Callback for wave detection
void XN_CALLBACK_TYPE OnWaveCB(void* cxt)
{
  printf("Hello World - Wave number: %d!\n", g_nWaveCounter);
  if(2 <= g_nWaveCounter)
      CleanAndExit();
  ++g_nWaveCounter;
}

2.3 添加主函数

在主函数中,我们将初始化整个 OpenNI 和 NITE 组件,并创建一个无限循环,该循环将不断从传感器读取数据,然后由 NITE 进行分析。

2.3.1 OpenNI 入口点初始化

首先,我们需要初始化 OpenNI 入口点,即 xn::Context。

xn::Context context;
xn::ScriptNode scriptNode;

// Create context
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 文件来隐式初始化 Context。此类文件可以在 NITE 安装文件夹的 Data 文件夹下找到。

2.3.2 NITE 入口点初始化

其次,我们需要初始化 NITE 入口点,即 XnVSessionManager。

// Create the Session Manager
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();
}
// Register session callbacks
g_pSessionManager->RegisterSession(NULL, &SessionStart, &SessionEnd, NULL);

我们使用 OpenNI Context 初始化 Session Manager,该 Context 可用于提取深度流,并具有预定义的焦点和快速重新聚焦手势。

在这里,为了开始 NI 会话,您需要执行“挥手”手势或“点击”手势。

一旦进入 NI 会话,您的手将被跟踪,以便检测其他基于手的姿势(控件)。

如果由于某种原因(例如,手离开了视野 FOV)导致跟踪丢失,一旦发生 RaiseHand 事件(例如,手返回到 FOV),会话将继续。

此代码片段的最后一部分是注册会话函数回调。这将使您能够在会话开始(SessionStart())时打印到屏幕,即用户执行了焦点手势。当会话结束(SessionEnd())时,即没有可用的手点且快速重新聚焦宽限期结束(=默认宽限期为 15 秒)。

2.3.3 NITE 组件初始化

现在,我们需要创建并初始化一个 NITE 树来检测“挥手”手势。这是一个非常简单的 NITE 树,只包含一个分支:XnVWaveDetector。

// init & register wave control
XnVWaveDetector wd;
wd.RegisterWave(NULL, OnWaveCB);
g_pSessionManager->AddListener(&wd);

// Initialization done. Start generating
context.StartGeneratingAll();

首先,我们实例化一个 Wave Detector;wd。

然后,我们注册 Wave 回调函数,该函数将在检测到挥手时被调用。然后,通过将其添加到其手点监听器列表中,我们将 Wave Detector 连接到 Session Manager。
一旦 NITE 树完成,我们就可以调用 StartGeneratingAll() 函数来开始生成流。

2.3.4 更新

由于我们希望不断从传感器读取数据并相应地更新 NITE 组件,因此我们需要创建一个无限循环,该循环将不断读取传感器流并用它们更新 NITE 树。

// Main loop
while (!g_bQuit)
{
  context.WaitAnyUpdateAll();
  g_pSessionManager->Update(&context);
}

3 运行应用程序

NIHelloWorld.zip 文件包含一个 Windows 项目,其中包含本文档中描述的示例代码。

如果您拥有兼容 OpenNI 的深度传感器并遵循本文档中的说明,您将能够编译并运行此示例。您需要将传感器连接到计算机并运行该应用程序。

3.1 操作您的第一个 NI 应用程序

应用程序运行时,请站在距离传感器约 1 米至 2.5 米的位置。

执行焦点手势以开始会话;可以是“挥手”或“点击”。要执行“点击”手势,您需要将手向前伸向传感器,然后以平滑的动作向后缩回一点,如下图所示。

image001.jpg

图 3-1:“点击”焦点手势

获得焦点后,您将收到一个指示性的打印通知,然后您就可以执行“挥手”手势在屏幕上打印“Hello World”消息。要退出应用程序,您需要执行两次“挥手”手势。

有关更多信息,您可以查阅 OpenNI Google Group:http://groups.google.com/group/openni-dev

您可以在 OpenNI Arena 上找到更多有趣的应用程序,其中许多都附带源代码,开发者们在此展示他们的 NI 应用程序。

© . All rights reserved.