Welcome

首页 / 软件开发 / .NET编程技术 / Kinect for Windows SDK开发入门(六)骨骼追踪基础 上

Kinect for Windows SDK开发入门(六)骨骼追踪基础 上2014-03-12Kinect产生的景深数据作用有限,要利用Kinect创建真正意义上交互,有趣和难忘的应用,还需要除了深度数据之外的其他数据。这就是骨骼追踪技术的初衷,骨骼追踪技术通过处理景深数据来建立人体各个关节的坐标,骨骼追踪能够确定人体的各个部分,如那部分是手,头部,以及身体。骨骼追踪产生X,Y,Z数据来确定这些骨骼点。在上文中,我们讨论了景深图像处理的一些技术。骨骼追踪系统采用的景深图像处理技术使用更复杂的算法如矩阵变换,机器学习及其他方式来确定骨骼点的坐标。

本文首先用一个例子展示骨骼追踪系统涉及的主要对象,然后在此基础上详细讨论骨骼追踪中所涉及的对象模型。

1. 获取骨骼数据

本节将会创建一个应用来将获取到的骨骼数据绘制到UI界面上来。在开始编码前,首先来看看一些基本的对象以及如何从这些对象中如何获取骨骼数据。在进行数据处理之前了解数据的格式也很有必要。这个例子很简单明了,只需要骨骼数据对象然后将获取到的数据绘制出来。

彩色影像数据,景深数据分别来自ColorImageSteam和DepthImageStream,同样地,骨骼数据来自SkeletonStream。访问骨骼数据和访问彩色影像数据、景深数据一样,也有事件模式和 “拉”模式两种方式。在本例中我们采用基于事件的方式,因为这种方式简单,代码量少,并且是一种很普通基本的方法。KinectSensor对象有一个名为SkeletonFrameReady事件。当SkeletonStream中有新的骨骼数据产生时就会触发该事件。通过AllFramesReady事件也可以获取骨骼数据。在下一节中,我们将会详细讨论骨骼追踪对象模型,现在我们只展示如何从SkeletonStream流中获取骨骼数据。SkeletonStream产生的每一帧数据都是一个骨骼对象集合。每一个骨骼对象包含有描述骨骼位置以及骨骼关节的数据。每一个关节有一个唯一标示符如头(head)、肩(shoulder)、肘(dlbow)等信息和3D向量数据。

现在来写代码。首先创建一个新的wpf工程文件,添加Microsoft.Kinect.dll。添加基本查找和初始化传感器的代码,这些代码参考之前的文章。在开始启动传感器之前,初始化SkeletonStream数据流,并注册KinectSensor对象的SkeletonFrameReady事件,这个例子没有使用彩色摄像机和红外摄像机产生的数据,所以不需要初始化这些数据流。UI界面采用默认的,将Grid的名称改为LayoutRoot,之后就再Grid里面绘制。代码如下:

<Window x:Class="KinectSkeletonTracking.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow" Height="350" Width="525"><Grid x:Name="LayoutRoot" Background="White"></Grid></Window>
后台逻辑代码如下:

private KinectSensor kinectDevice;private readonly Brush[] skeletonBrushes;//绘图笔刷private Skeleton[] frameSkeletons;public MainWindow(){InitializeComponent();skeletonBrushes = new Brush[] { Brushes.Black, Brushes.Crimson, Brushes.Indigo, Brushes.DodgerBlue, Brushes.Purple, Brushes.Pink };KinectSensor.KinectSensors.StatusChanged += KinectSensors_StatusChanged;this.KinectDevice = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);}public KinectSensor KinectDevice{get { return this.kinectDevice; }set{if (this.kinectDevice != value){//Uninitializeif (this.kinectDevice != null){this.kinectDevice.Stop();this.kinectDevice.SkeletonFrameReady -= KinectDevice_SkeletonFrameReady;this.kinectDevice.SkeletonStream.Disable();this.frameSkeletons = null;}this.kinectDevice = value;//Initializeif (this.kinectDevice != null){if (this.kinectDevice.Status == KinectStatus.Connected){this.kinectDevice.SkeletonStream.Enable();this.frameSkeletons = new Skeleton[this.kinectDevice.SkeletonStream.FrameSkeletonArrayLength];this.kinectDevice.SkeletonFrameReady += KinectDevice_SkeletonFrameReady;this.kinectDevice.Start();}}}}}private void KinectSensors_StatusChanged(object sender, StatusChangedEventArgs e){switch (e.Status){case KinectStatus.Initializing:case KinectStatus.Connected:case KinectStatus.NotPowered:case KinectStatus.NotReady:case KinectStatus.DeviceNotGenuine:this.KinectDevice = e.Sensor;break;case KinectStatus.Disconnected://TODO: Give the user feedback to plug-in a Kinect device.this.KinectDevice = null;break;default://TODO: Show an error statebreak;}}