体感(Kinect)开发要点总结一

体感(Kinect)开发要点总结一

    Kinect有两类摄像头,近红外摄像头和普通的视频摄像头。视频摄像头提供了一般摄像头类似的彩色影像。
 
    Kinect的彩色摄像头默认每秒产生30副ColorImageFrame。

    彩色影像数据,景深数据分别来自ColorImageSteam和DepthImageStream,骨骼数据来自SkeletonStream。

    Skeleton Tracking(骨骼追踪)是Kinect的核心技术。

    KinectSensor对象有一个名为SkeletonFrameReady事件。当SkeletonStream中有新的骨骼数据产生时就会触发该事件。通过AllFramesReady事件也可以获取骨骼数据。
    SkeletonStream产生的每一帧数据都是一个骨骼对象集合。每一个骨骼对象包含有描述骨骼位置以及骨骼关节的数据。每一个关节有一个唯一标示符如头(head)、肩(shoulder)、肘(dlbow)等信息和3D向量数据。
    SkeletonFrameReady事件的响应方法,每一次事件被激发时,通过调用事件参数的OpenSkeletonFrame方法就能够获取当前的骨骼数据帧。

Kinect传感器
    基于Kinect开发的应用程序最开始需要用到的对象就是KinectSensor对象,该对象直接表示Kinect硬件设备。KinectSensor对象是我们想要获取数据,包括彩色影像数据,景深数据和骨骼追踪数据的源头。
    每一个数据流以帧(frame)为单位。例如:ColorImageStream当获取到了新的数据时就会触发ColorFrameReady事件。

    每一种数据流(Color,Depth,Skeleton)都是以数据点的方式在不同的坐标系中显示的。
    将一个数据流中的点数据转换到另一个数据流中是一个很常见的操作。
    KinectSensor对象有一些列的方法能够进行数据流到数据点阵的转换,他们是MapDepthToColorImagePoint,MapDepthToSkeletonPoint以及MapSkeletonPointToDepth。
    在获取Kinect数据前,我们必须先发现连接的Kinect设备。

发现连接的Kinect设备
    KinectObject对象,该对象是SDK在探测到有连接的Kinect设备时创建的。当有Kinect设备连接到计算机上时,应用程序应该得到通知或者提醒。KinectSeneor对象有一个静态的属性KinectSensors,该属性是一个KinectSensorCollection集合,该集合继承自
ReadOnlyCollection,ReadOnlyCollection集合很简单,他只有一个索引器和一个称之为StatusChanged的事件。
    使用集合中的索引器来获取KinectSensor对象。集合中元素的个数就是Kinect设备的个数。也就是说,一台电脑上可以连接多个Kinect设备来从不同的方向获取数据。应用程序可以使用多个Kinect设备来获取多方面的数据,Kinect个数的限制 只有电脑配置的限制。
由于每个Kinect是通过USB来进行数据传输的,所以每一个Kinect设备需要一条USB线与电脑相连。此外,更多的Kinect设备需要更多的CPU和内存消耗。
    查找Kinect设备可以通过简单的遍历集合找到;但是KinectSensor集合中的设备不是都能直接使用,所以KinectSensor对象有一个Status属性,他是一个枚举类型,标识了当前Kinect设备的状态。
    只有设备在Connected状态下时,KinectSensor对象才能初始化。在应用的整个生命周期中,传感器的状态可能会发生变化,这意味着我们开发的应用程序必须监控设备的连接状态,并且在设备连接状态发生变化时能够采取相应的措施来提高用户体验。

    添加Microsoft.Kinect.dll;

    添加命名空间;
    using Microsoft.Research.Kinect.Nui;
    using Microsoft.Research.Kinect.Audio;
    using Coding4Fun.Kinect.Wpf;


    发现,获取Kinect传感器的状态


    private KinectSensor kinect;
    public KinectSensor Kinect
    {
        get { return this.kinect;}
        set {
            //如果带赋值的传感器和目前的不一样
            if (this.kinect!=value)
            {
                //如果当前的传感对象不为null
                if (this.kinect!=null)
                {
                 //uninitailize当前对象
                    this.kinect=null;
                }
                //如果传入的对象不为空,且状态为连接状态
                if (value!=null&&value.Status==KinectStatus.Connected)
                {
                    this.kinect=value;
                }
            }
        }


打开传感器
    一旦发现了传感器,在应用程序能够使用传感器之前必须对其进行初始化。传感器的初始化包括三个步骤。首先,应用程序必须设置需要使用的数据流,并将其状态设为可用。每一中类型的数据流都有一个Enable方法,该方法可以初始化数据流。每一种数据流都完
全不同,在使用之前需要进行一些列的设置。在一些情况下这些设置都在Enable方法中处理了。
    初始化之后,接下来就是要确定应用程序如何使用产生的数据流。最常用的方式是使用Kinect对象的一些列事件,每一种数据流都有对应的事件,他们是:ColorImageStream对应ColorFrameReady事件、DepthImageStream对应DepthFrameReady事件、SkeletonStream
对象对应SkeletonFrameReady事件。以及AllFramesReady事件。各自对应的事件只有在对应的数据流enabled后才能使用,AllFramesReady事件在任何一个数据流状态enabled时就能使用。
    最后,应用程序调用KinectSensor对象的Start方法后,frame-ready事件就会触发从而产生数据。

停止传感器
    一旦传感器打开后,可以使用KinectSensor对象的Stop方法停止。这样所有的数据产生都会停止,因此在监听frameready事件时要先检查传感器是否不为null。
    KinectSensor对象以及数据流都会使用系统资源,应用程序在不需要使用KinectSensor对象时必须能够合理的释放这些资源。在这种情况下,程序不仅要停止传单器,还用注销frameready事件。注意,不要去调用KinectSensor对象的Dispose方法。这将会阻止应用程
序再次获取传感器。应用程序必须从启或者将Kinect从新拔出然后插入才能再次获得并使用对象。

平滑化
    骨骼运动会呈现出跳跃式的变化。有几个原因会导致出现这一问题,可能是应用程序的性能,游戏者的动作不够连贯,也有可能是Kinect硬件的性能问题。骨骼关节点的相对位置可能在帧与帧之间变动很大,这对应用程序产生一些负面的影响。

    SkeletonStream对象有一种方法。他通过将骨骼关节点的坐标标准化来减少帧与帧之间的关节点位置差异。当初始化SkeletonStream对象调用重载的Enable方法时可以传入一个TransformSmoothParameters参数。SkeletonStream对象有两个与平滑有关只读属性:IsSmoothingEnabled和SmoothParameters。当调用Enable方法传入了TransformSmoothParameters是IsSmoothingEnabled返回true而当使用默认的不带参数的Enable方法初始化时,IsSmoothingEnabled对象返回false。SmoothParameters属性用来存储定义平滑参数。
    TransformSmoothParameters这个结构定义了一些属性:
        修正值(Correction)属性,接受一个从0-1的浮点型。值越小,修正越多。
        抖动半径(JitterRadius)属性,设置修正的半径,如果关节点“抖动”超过了设置的这个半径,将会被纠正到这个半径之内。该属性为浮点型,单位为米。
        最大偏离半径(MaxDeviationRadius)属性,用来和抖动半径一起来设置抖动半径的最大边界。任何超过这一半径的点都不会认为是抖动产生的,而被认定为是一个新的点。该属性为浮点型,单位为米。
        预测帧大小(Prediction)属性,返回用来进行平滑需要的骨骼帧的数目。
        平滑值(Smoothing)属性,设置处理骨骼数据帧时的平滑量,接受一个0-1的浮点值,值越大,平滑的越多。0表示不进行平滑。
    对骨骼关节点进行平滑处理会产生性能开销。平滑处理的越多,性能消耗越大。设置平滑参数没有经验可以遵循。需要不断的测试和调试已达到最好的性能和效果。在程序运行的不同阶段,可能需要设置不同的平滑参数。

    平滑化示例代码;
            nui.SkeletonEngine.TransformSmooth = true;
            var parameters = new TransformSmoothParameters
            {
                Smoothing = 0.75f,
                Correction = 0.0f,
                Prediction = 0.0f,
                JitterRadius = 0.05f,
                MaxDeviationRadius = 0.04f
            };
            nui.SkeletonEngine.SmoothParameters = parameters;


为骨骼帧准备好事件添加处理函数
        nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);

在SkeletonData对象的Joints属性集合中保存了所有骨骼点的信息。每个骨骼点的信息都是一个Joint对象,其中的Position的X、Y、Z表示了三维位置。其中X和Y的范围都是-1到1,而Z是Kinect到识别物体的距离。

骨骼追踪系统中涉及到的一些主要的对象模型。有四个最主要的对象,他们是SkeletonStream,SkeletonFrame,Skeleton和Joint。

参考

http://blog.sina.com.cn/s/blog_45ef30330100uhoq.html
https://www.cnblogs.com/yangecnu/archive/2012/04/06/KinectSDK_Skeleton_Tracking_Part1.html
https://www.cnblogs.com/yangecnu/archive/2012/03/31/KinectSDK_Application_Fundamentals_Part1.html

发布了434 篇原创文章 · 获赞 512 · 访问量 294万+

猜你喜欢

转载自blog.csdn.net/bcbobo21cn/article/details/90109804