Kinect v2.0原理介绍之七:彩色帧获取


~~有兴趣的小伙伴,加kinect算法交流群:462964980。

使用SDK: Kinect for Windows SDK v2.0 public preview


好了,真正正式进入SDK的学习当中。

同大多数Kinect相关的文章,第一个自然也是获取它那1080P的彩色图像。

值得说明的是,这次Kinect支持不同的程序使用同一个Kinect,至于有没有坏处,

毕竟不是这方面的专家,不敢出狂言,只是隐约感觉到了一点蛋疼。


好了,可以使用上节给的模板创建项目了,需要简单配置一下项目,选择项目属性后请按照图中一样设置

Kinect v2.0原理介绍之七:彩色帧获取_第1张图片

里面的"KINECTSDK20_DIR"是一个环境变量,可以在系统属性-高级-环境变量 里边查看/修改

再在stdafx.h里面添加


[cpp] view plain copy print ?
  1. #include <Kinect.h>  
  2. #pragma comment ( lib, "kinect20.lib" )  





好了,COM组件是基于面向对象模型的接口,那么Kinect的类是什么呢,是KinectSensor,

比一代的NUISensor好点了。不过COM只提供了接口,于是叫做IKinectSensor。


使用

GetDefaultKinectSensor(IKinectSensor**)获取一个默认的Kinect。如果有复数台Kinect可以使用

GetKinectSensorCollection(IKinectSensorCollection** )进行枚举,代码大致如下

[cpp] view plain copy print ?
  1. IKinectSensorCollection* pKinectCollection = nullptr;  
  2. IEnumKinectSensor* pEnumKinect = nullptr;  
  3. IKinectSensor* pKinect = nullptr;  
  4. // 获取Kinect集合  
  5. HRESULT hr = ::GetKinectSensorCollection(&pKinectCollection);  
  6. // 获取Kinect枚举器  
  7. if (SUCCEEDED(hr)){  
  8.     hr = pKinectCollection->get_Enumerator(&pEnumKinect);  
  9. }  
  10. // 枚举Kinect  
  11. if (SUCCEEDED(hr)){  
  12.     BOOLEAN available = false;  
  13.     while (true){  
  14.         // 获取下一个  
  15.         if (SUCCEEDED(pEnumKinect->GetNext(&pKinect))){  
  16.             // 判断有效性  
  17.             pKinect->get_IsAvailable(&available);  
  18.             if (available && YourJudgmentFunc(pKinect)){  
  19.                 break;  
  20.             }  
  21.             SafeRelease(pKinect);  
  22.         }  
  23.         else  
  24.             break;  
  25.     }  
  26. }  
  27. SafeRelease(pEnumKinect);  
  28. SafeRelease(pKinectCollection);  


不过除了土豪和专家,谁用的起多台

不过!等等!居然看到小写的方法名:get_IsAvailable,夭寿啦,微软居然有小写开头的方法,长这么大第一次看到啊(笔者见识短,见谅大哭)

是的,Kinect SDK中存在大量的get_开头的方法,不过本人觉得Kinect的类太多了,虽然很好,但是效率与易用性会下降啊,

直接Kinect::GetColorFrameData也不错,简单粗暴。



IKinectSensor::Open() 绅士地打开传感器

IKinectSensor::Close() 优雅地关闭传感器


那么怎么获取彩色帧呢,没有一代那样打开指定功能。

一代获取彩色帧需要先说明“我要获取彩色帧啦”,然后指定彩色帧格式。


二代设计上简单了,直接获取彩色帧相关对象几个,目前还不能设置获取分辨率。

本人估计为了达到“多个程序使用一个Kinect”的效果,二代干脆直接一股脑像扔垃圾一样全扔过来了,

你要啥自己到地上捡,不需要像一代那样开发票啦!


使用

IKinectSensor::get_ColorFrameSource(IColorFrameSource**)

获取一个ColorFrameSource(彩色帧源)

再使用

IColorFrameSource::OpenReader(IColorFrameReader **)

打开一个ColorFrameReader(彩色帧读取器)

再使用
IColorFrameReader::AcquireLatestFrame(IColorFrame**)    

获取彩色帧,有就返回S_OK,否则返回错误代码

这个称为轮询模式,有空的时候来问一下Kinect有没有新的彩色帧,这个模式适合游戏 ,

在每帧询问一下,毕竟游戏是每帧都要刷新的


还有一个称为事件模式,这个就适合其他一般程序啦。

Windows下使用WaitForSingleObject、WaitForMultipleObjects等待事件用于线程同步,

详细可以参考其他文章,关键函数有CreatEvent, SetEvent, ResetEvent等。

这里是用的是MsgWaitForMultipleObjects,这个函数不仅可以等待内核对象,还能对Windows消息进行响应,

当然,详细的可以自行搜索一下。


[cpp] view plain copy print ?
  1. MsgWaitForMultipleObjects(lengthof(events), events, FALSE, INFINITE, QS_ALLINPUT);  

比如这里用这个

event是个静态数组,lengthof是个宏,定义如下,判断静态数组的长度

[cpp] view plain copy print ?
  1. #define lengthof(a) (sizeof(a)/sizeof(*a))  

当然,这里事件只有一个,那就是彩色帧到达事件(下面简称彩色临帧事件)

怎么获取呢?

在打开ColorFrameReader后不要急,IColorFrameReader::SubscribeFrameArrived(WAITABLE_HANDLE*)

获取事件即可,使用时上边的

[cpp] view plain copy print ?
  1. events[0] = reinterpret_cast<HANDLE>(hColorFrameArrived)  
强制转换即可



当彩色临帧事件被触发时,

IColorFrameReader::GetFrameArrivedEventData(WAITABLE_HANDLE, IColorFrameArrivedEventArgs**)

来获取事件的数据

再使用

IColorFrameArrivedEventArgs::get_FrameReference(IColorFrameReference**)

获取彩色帧引用

最后使用

IColorFrameReference::AcquireFrame(IColorFrame**)

获取彩色帧


说到这里,只想说: 我去,微软你累不累。

这几个类几乎只有一个可用方法,完全可以合并啊


好了,这样,事件轮询两个模式终于同步了。


目前,彩色帧分辨率固定为1920*1080,不过为了保证以后能自行设置采样分辨率,

所以应该获取获取的彩色帧分辨率

使用IColorFrame::get_FrameDescription获取彩色帧描述,再利用这个描述获取宽度与高度


自然还需要获取源数据格式,我们需要的是BGRA格式,

使用IColorFrame::get_RawColorImageFormat检查格式,如果是ColorImageFormat_Bgra后

可以直接使用

IColorFrame::AccessRawUnderlyingBuffer(UINT*, BYTE**)

获取该帧数据地址与长度,BGRA顺序的位图。

如果不是BGRX格式的,可以用自带的转换方法进行转换,不过这个方法需要自备缓冲区,

自己在构造函数里面new[]一个就好了,记得在析构函数里面释放

自带的方法是:

IColorFrame::CopyConvertedFrameDataToArray(UINT, BYTE*,ColorImageFormat)

然后就完事大吉,用自己想用的图像接口显示吧:


嗯,光线不是特别好,寝室很乱,见笑了


附加:

提供FPS显示与鼠标缩放功能与显示,详细的请看范例,再根据例子讲本工程补全吧。

还有就是不知道为什么有时15FPS,有时30FPS,简直了...


本节范例下载

你可能感兴趣的:(kinect,彩色帧获取)