在ubuntu14.04下openni+opencv+kinectV1的学习二:图像的读取与显示

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36355662/article/details/76747290

1、编写代码

直接使用了博客上的代码,详见下面的博客:
Kinect开发教程二:OpenNI读取深度图像与彩色图像并显示
除了主函数文件以外,配置文件也是非常重要的,如果工程找不到相关的库,也是不能实现效果的,此处列出CMakeLists.txt文件代码:

cmake_minimum_required(VERSION 2.8)
project(2_hellokinect02)
# 寻找OpenCV库
find_package( OpenCV REQUIRED )
# 添加头文件
include_directories( ${OpenCV_INCLUDE_DIRS} )
# 包含OpenNI库
include_directories ("/usr/include/ni/"  )

add_executable(2_hellokinect02 main.cpp)
target_link_libraries( 2_hellokinect02 OpenNI ${OpenCV_LIBS})

组织好相关文件,就可以进行编译了,运行后会出来两个窗口,彩色图像窗口和深度图像窗口。

2、代码解释

原博客还是解释的不错的,这里补充一下相关内容。
【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的深度图像数据含有两种格式,两种格式都是用两个字节来保存一个像素的深度值,而两方式的差别详见博客文章

【9】cvConvertScale()函数作用是使用线形变换转换数据,255/4096比例压缩,转换到0-255范围。至于为什么,应该是电脑屏幕的正常显示(也即opencv的图像显示)的要求吧。

【10】cvWaitKey()函数的功能是不断刷新图像,频率时间为delay,单位为ms。返回值为当前键盘按键值。经查询,键值为27的是电脑键盘上的ESC退出键。

【11】最后调用CV库中的函数关闭窗口,释放内存空间。用StopGeneratingAll()函数关闭数据收集开关,用context.Shutdown()方法关闭所有驱动并且正确地清除所有。

猜你喜欢

转载自blog.csdn.net/qq_36355662/article/details/76747290