本文主要记录kinect相关的知识和对齐方法,这是第三部分,主要是代码说明,此记。
【1】XnCppWrapper.h是OpenNI的头文件,opencv/cv.h和opencv/highgui.h是opencv的一些头文件,关于opencv库内容可以参见书籍《openCV3编程入门》或OpenCV入门教程 。关于OpenNI库内容,可以看一个博客对官方文档的翻译OpenNI2 开发者指南。
【2】四个首地址imgDepth16u,imgRGB8u, depthShow, imageShow是由cvCreateImage()函数创建的,查询百度百科了解到函数功能是创建首地址并分配存储空间,用法是:header = cvCreateImageHeader(size,depth,channels);
size 图像宽、高.
depth 图像元素的位深度,可以是下面的其中之一:
IPL_DEPTH_8U - 无符号8位整型
IPL_DEPTH_8S - 有符号8位整型
IPL_DEPTH_16U - 无符号16位整型
IPL_DEPTH_16S - 有符号16位整型
IPL_DEPTH_32S - 有符号32位整型
IPL_DEPTH_32F - 单精度浮点数
IPL_DEPTH_64F - 双精度浮点数
channels 每个元素(像素)通道数.可以是 1, 2, 3 或 4.通道是交叉存取的。
header是返回的数据块首地址。关于图像基础内容,可以参看博客:opencv中图像基础(大小,深度,通道)。
【3】OpenNI::initialize()方法。这个方法初始化所有的传感器驱动并且扫描系统中所有可用的传感器设备。所有使用OpenNI的应用程序在使用其他API之前都应该调用此方法。
上下文对象(context object)是OpenNI的主对象,它包括(使用OpenNI的程序的)所有状态信息,以及这个程序使用的所有产品链。同一个程序可以创建多个上下文,但是它们不可以共享信息。上下文对象在使用前必须先被初始化,这个时候所有的内置模块都被加载。
【4】能产生数据的产品节点叫做generator(DepthGenerator和ImageGenerator),一旦它们被创建,并不立即开始产生数据,允许程序来设置所需的配置。这能够保证一旦这些对象开始抽取数据到程序,这些数据是根据所需配置产生的。数据生成器在没有指明被要求去产生数据的话,不会自己产生数据。
【5】XnMapOutputMode是用来设定生成器的参数,GetAlternativeViewPointCap().SetViewPoint( )函数是用来调整视角的。
【6】StartGeneratingAll()函数是打开图像数据收集开关。而为了确保能取得最新的数据,在读取 Generator 的数据前,都必须要先呼叫 context 的 wait / update 这一系列的函式,来进行 node 数据的更新。
这系列的函示有四个:WaitAnyUpdateAll()、WaitOneUpdateAll()、WaitNoneUpdateAll() 和 WiatAndUpdateAll()。这四者都会更新 context 下所有的 node 的数据,差别只在于更新的条件:
WiatAndUpdateAll() 会等到所有的 node 都取得新数据后,再统一更新所有的 node 的数据;
WaitAnyUpdateAll() 是等到随便一个 node 有新数据时就会更新;
WaitOneUpdateAll() 则是等到指定的 node 有新数据时再更新;
WaitNoneUpdateAll() 则是不管有没有新数据就强制更新。
【7】depthGenerator.GetMetaData是获取生成器里的数据并放在depthMD缓冲器中。
【8】OpenNI支持的图像格式比较单一,需要用OpenCV进行下一步操作,则需要将DepthMetaData、ImageMetaData转换为Mat数据类型,详见博客文章。
memcpy指的是c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
程序中memcpy()函数的作用是将深度数据复制到imgDepth16U.imageData,图像大小为640*480,2通道(2个字节) 。这里深度数据为什么是两个字节,相信都有疑惑。经查询资料了解到,Kinect的深度图像数据含有两种格式,两种格式都是用两个字节来保存一个像素的深度值,而两方式的差别为:
(1)唯一表示深度值:那么像素的低12位表示一个深度值,高4位未使用;
(2)既表示深度值又含有游戏者ID:Kinect SDK具有分析深度数据和探测人体或者游戏者轮廓的功能,它一次能够识别多达6个游戏者。SDK为每一个追踪到的游戏者编号作为索引。而这个方式中,像素值的高13位保存了深度值,低三位保存用户序号,7 (0000 0111)这个位掩码能够帮助我们从深度数据中获取到游戏者索引值(这个编程将在下一节)。
应用程序可以使用深度数据流中的深度数据来支持各种各样的用户特性,如追踪用户的运动并在程序中识别和忽略背景物体的信息等。
【9】cvConvertScale()函数作用是使用线形变换转换数据,255/4096比例压缩,转换到0-255范围。至于为什么,应该是电脑屏幕的正常显示(也即opencv的图像显示)的要求吧。
【10】cvWaitKey()函数的功能是不断刷新图像,频率时间为delay,单位为ms。返回值为当前键盘按键值。经查询,键值为27的是电脑键盘上的ESC退出键。
【11】最后调用CV库中的函数关闭窗口,释放内存空间。用StopGeneratingAll()函数关闭数据收集开关,用context.Shutdown()方法关闭所有驱动并且正确地清除所有。
整合自以下博客:
[1]https://blog.csdn.net/qq_36355662/article/details/76747290
[2]https://blog.csdn.net/zouxy09/article/details/8146719