Kinect for Windows SDK v2.0 开发笔记 (二)彩色帧获取

(转载请注明出处)

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


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

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

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

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


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

Kinect for Windows SDK v2.0 开发笔记 (二)彩色帧获取_第1张图片

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

再在stdafx.h里面添加


#include 
#pragma comment ( lib, "kinect20.lib" )





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

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


使用

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

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

    IKinectSensorCollection* pKinectCollection = nullptr;
    IEnumKinectSensor* pEnumKinect = nullptr;
    IKinectSensor* pKinect = nullptr;
    // 获取Kinect集合
    HRESULT hr = ::GetKinectSensorCollection(&pKinectCollection);
    // 获取Kinect枚举器
    if (SUCCEEDED(hr)){
        hr = pKinectCollection->get_Enumerator(&pEnumKinect);
    }
    // 枚举Kinect
    if (SUCCEEDED(hr)){
        BOOLEAN available = false;
        while (true){
            // 获取下一个
            if (SUCCEEDED(pEnumKinect->GetNext(&pKinect))){
                // 判断有效性
                pKinect->get_IsAvailable(&available);
                if (available && YourJudgmentFunc(pKinect)){
                    break;
                }
                SafeRelease(pKinect);
            }
            else
                break;
        }
    }
    SafeRelease(pEnumKinect);
    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消息进行响应,

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


MsgWaitForMultipleObjects(lengthof(events), events, FALSE, INFINITE, QS_ALLINPUT);

比如这里用这个

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

#define lengthof(a) (sizeof(a)/sizeof(*a))

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

怎么获取呢?

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

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

events[0] = reinterpret_cast(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)

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

Kinect for Windows SDK v2.0 开发笔记 (二)彩色帧获取_第2张图片

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


附加:

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

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


本节范例下载

你可能感兴趣的:(C++,Kinect,开发笔记,Kinect,C++,开发笔记,Kinect,for,Windows,SDK,v2.0,开发笔记)