Kinect for Windows SDK开发入门(七)骨骼追踪基础 下

上一篇文章用在UI界面上绘制骨骼数据的例子展示了骨骼追踪系统涉及的主要对象,然后详细讨论了骨骼追踪中所涉及的对象模型。但是了解了基本概念是一回事,能够建立一个完整的可用的应用程序又是另外一回事,本文通过介绍一个简单的Kinect游戏来详细讨论如何应用这些对象来建立一个完整的Kinect应用,以加深对Kinect骨骼追踪所涉及的各个对象的了解。

1. Kinect连线游戏

相信大家在小时候都做过一个数学题目,就是在纸上将一些列数字(用一个圆点表示)从小到大用线连起来。游戏逻辑很简单,只不过我们在这里要实现的是动动手将这些点连起来,而不是用笔或者鼠标。

这个小游戏显然没有第一人称射击游戏那样复杂,但如果能够做成那样更好。我们要使用骨骼追踪引擎来收集游戏者的关节数据,执行操作并渲染UI界面。这个小游戏展示了自然用户界面(Natural User Interface,NUI)的理念,这正是基于Kinect开发的常见交互界面,就是手部跟踪。这个连线小游戏没有仅仅用到了WPF的绘图功能,没有好看的图片和动画效果,这些以后可以逐步添加。

在开始写代码之前,需要明确定义我们的游戏目标。连线游戏是一个智力游戏,游戏者需要将数字从小到大连起来。程序可以自定义游戏上面的数字和位置(合称一个关卡)。每一个关卡包括一些列的数字(以点表示)及其位置。我们要创建一个DotPuzzle类来管理这些点对象的集合。可能一开始不需要这个类,仅仅需要一个集合就可以,但是为了以后方便添加其他功能,使用类更好一点。这些点在程序中有两个地方需要用到,一个是最开始的时候在界面上绘制关卡,其次是判断用户是否碰到了这些点。

当用户碰到点时,程序开始绘制,直线以碰到的点为起始点,直线的终点位用户碰到的下一个点。然后下一个点又作为另一条直线的起点,依次类推。直到最后一个点和第一个点连起来,这样关卡算是通过了,游戏结束。

游戏规则定义好了之后,我们就可以开始编码了,随着这个小游戏的开发进度,可能会添加一些其他的新功能。一开始,建一个WPF工程,然后引用Microsoft.Kinect.dll,和之前的项目一样,添加发现和初始化Kinect传感器的代码。然后注册KinectSensor对象的SkeletonFrameReady事件。

1.1 游戏的用户界面

游戏界面代码如下,有几个地方需要说明一下。Polyline对象用来表示点与点之间的连线。当用户在点和点之间移动手时,程序将点添加到Polyline对象中。PuzzleBoardElement Canvas对象用来作为UI界面上所有点的容器。Grid对象下面的Canvas的顺序是有意这样排列的,我们使用另外一个GameBoardElement Canvas对象来存储手势,以Image来表示,并且能够保证这一层总是在点图层之上。 将每一类对象放在各自层中的另外一个好处是重新开始一个新的游戏变得很容易,只需要将PuzzleBoardElement节点下的所有子节点清除,CrayonElement元素和其他的UI对象不会受到影响。

Viewbox和Grid对象对于UI界面很重要。如上一篇文章中讨论的,骨骼节点数据是基于骨骼空间的。这意味着我们要将骨骼向量转化到UI坐标系中来才能进行绘制。我们将UI控件硬编码,不允许它随着UI窗体的变化而浮动。Grid节点将UI空间大小定义为1920*1200。通常这个是显示器的全屏尺寸,而且他和深度影像数据的长宽比是一致的。这能够使得坐标转换更加清楚而且能够有更加流畅的手势移动体验。

<Window x:Class="KinectDrawDotsGame.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="600" Width="800" Background="White">
    <Viewbox>
        <Grid x:Name="LayoutRoot" Width="1920" Height="1200">
            <Polyline x:Name="CrayonElement" Stroke="Black" StrokeThickness="3" />
            <Canvas x:Name="PuzzleBoardElement" />
            <Canvas x:Name="GameBoardElement">
                <Image x:Name="HandCursorElement" Source="Images/hand.png" Width="75"
                       Height="75" RenderTransformOrigin="0.5,0.5">
                    <Image.RenderTransform>
                        <TransformGroup>
                            <ScaleTransform x:Name="HandCursorScale" ScaleX="1" />
                        </TransformGroup>
                    </Image.RenderTransform>
                </Image>
            </Canvas>
        </Grid>
    </Viewbox>
</Window>

硬编码UI界面也能够简化开发过程,能够使得从骨骼坐标向UI坐标的转化更加简单和快速,只需要几行代码就能完成操作。况且,如果不应编码,相应主UI窗体大小的改变将会增加额外的工作量。通过将Grid嵌入Viewbox节点来让WPF来帮我们做缩放操作。最后一个UI元素是Image对象,他表示手的位置。在这个小游戏中,我们使用这么一个简单的图标代表手。你可以选择其他的图片或者直接用一个Ellipse对象来代替。本游戏中图片使用的是右手。在游戏中,用户可以选择使用左手或者右手,如果用户使用左手,我们将该图片使用ScaleTransform变换,使得变得看起来像右手。

1.2 手部追踪

游戏者使用手进行交互,因此准确判断是那只手以及手的位置对于基于Kinect开发的应用程序显得至关重要。手的位置及动作是手势识别的基础。追踪手的运动是从Kinect获取数据的最重要用途。在这个应用中,我们将忽视其他关节点信息。

小时候,我们做这中连线时一般会用铅笔或者颜料笔,然后用手控制铅笔或则颜料笔进行连线。我们的这个小游戏颠覆了这种方式,我们的交互非常自然,就是手。这样有比较好的沉浸感,使得游戏更加有趣。当然,开发基于Kinect的应用程序这种交互显得自然显得至关重要。幸运的是,我们只需要一点代码就能实现这一点。

在应用程序中可能有多个游戏者,我们设定,不论那只手离Kinect最近,我们使用距离Kinect最近的那个游戏者的那只手作为控制程序绘图的手。当然,在游戏中,任何时候用户可以选择使用左手还是右手,这会使得用户操作起来比较舒服,SkeletonFrameReady代码如下:

private void KinectDevice_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
    using (SkeletonFrame frame = e.OpenSkeletonFrame())
    {
        if (frame != null)
        {
            frame.CopySkeletonDataTo(this.frameSkeletons);
            Skeleton skeleton = GetPrimarySkeleton(this.frameSkeletons);

            Skeleton[] dataSet2 = new Skeleton[this.frameSkeletons.Length];
            frame.CopySkeletonDataTo(dataSet2);

            if (skeleton == null)
            {
                HandCursorElement.Visibility = Visibility.Collapsed;
            }
            else
            {
                Joint primaryHand = GetPrimaryHand(skeleton);
                TrackHand(primaryHand);
                TrackPuzzle(primaryHand.Position);
            }
        }
    }
}

private static Skeleton GetPrimarySkeleton(Skeleton[] skeletons)
{
    Skeleton skeleton = null;

    if (skeletons != null)
    {
        //查找最近的游戏者
        for (int i = 0; i < skeletons.Length; i++)
        {
            if (skeletons[i].TrackingState == SkeletonTrackingState.Tracked)
            {
                if (skeleton == null)
                {
                    skeleton = skeletons[i];
                }
                else
                {
                    if (skeleton.Position.Z > skeletons[i].Position.Z)
                    {
                        skeleton = skeletons[i];
                    }
                }
            }
        }
    }
    return skeleton;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索对象
, kinect
, kinect2.0
, kinect2.0 win8.1
, kinect开发
, 用户
, 位置追踪
, 追踪
, kinect,C#,输出坐标
, 一个
游戏开发手势
kinect 骨骼点追踪、kinect骨骼跟踪、kinect2.0骨骼节点、kinect 骨骼、kinect获取骨骼坐标,以便于您获取更多的相关知识。

时间: 2024-11-01 00:27:38

Kinect for Windows SDK开发入门(七)骨骼追踪基础 下的相关文章

Kinect for Windows SDK开发入门(六)骨骼追踪基础 上

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

Kinect for Windows SDK开发入门(九)骨骼追踪进阶 下

1. 基于景深数据的用户交互 到目前为止我们只用了骨骼数据中关节点的X,Y值.然而Kinect产生的关节点数据除了X,Y值外还有一个深度值.基于Kinect的应用程序应该利用好这个深度值.下面的部分将会介绍如何在Kinect应用程序中使用深度值. 除了使用WPF的3D特性外,在布局系统中可以根据深度值来设定可视化元素的尺寸大小来达到某种程序的立体效果.下面的例子使用Canvas.ZIndex属性来设置元素的层次,手动设置控件的大小并使用ScaleTransform来根据深度值的改变来进行缩放.用

Kinect for Windows SDK开发入门(八)骨骼追踪进阶 上

前7篇文件我们介绍了Kinect SDK中各种传感器的各种基本知识,我们用实验的方式演示了这些基本对象和方法的如何使用,这些都是Kinect开发最基本的知识.了解了这些基本知识后,就可以开发出一个基于Kinect的简单程序了.但是这些离开发出一个好的基于Kinect的应用程序还有一段距离.后面的文章中,将会结合Kinect SDK介绍WPF以及其它第三方工具,类库来建立一个以Kinect为驱动的有较好用户体验的程序.我们将利用之前讲到的知识来进行下面一些比较复杂的话题. Kinect传感器核心只

Kinect for Windows SDK开发入门(十五)进阶指引 下

上一篇文章介绍了Kinect for Windows SDK进阶开发需要了解的一些内容,包括影像处理Coding4Fun Kinect工具类库以及如何建立自己的扩展方法类库来方便开发,接下来介绍了利用Kinect进行近距离探测的一些方法,限于篇幅原因,仅仅介绍了近距离探测的三种方式.  本文接上文将继续介绍近距离探测中如何探测运动,如何获取并保存产生的影像数据:然后将会介绍如何进行脸部识别,以及介绍全息图(Holograme)的一些知识,最后介绍了一些值得关注的类库和项目. 2.4 运动识别 目

Kinect for Windows SDK开发入门(十四)进阶指引 上

前面十三篇文章介绍了Kinect SDK开发中的各个方面的最基础的知识.正如本系列博闻标题那样,这些知识只是Kinect for windows SDK开发的入门知识.本文将会介绍Kinect进阶开发需要了解一些知识(beyond the basic). 读者可能会注意到,在学习了前面十三篇文章中关于Kinect开发的方方面面,如影像数据流.景深摄像机.骨骼追踪.麦克风阵列.语音识别等这些知识后,离开发出一些我们在网上看到的那些具有良好用户体验的Kinect应用程序还是显得捉襟见肘.Kinect

Kinect for Windows SDK开发入门(二)基础知识 上

上篇文章介绍了Kinect开发的环境配置,这篇文章和下一篇文章将介绍Kinect开发的基本知识,为深入研究Kinect for Windows SDK做好基础. 每一个Kinect应用都有一些基本元素.应用程序必须探测和发现链接到设备上的Kinect传感器.在使用这些传感器之前,必须进行初始化,一旦初始化成功后,就能产生数据,我们的程序就能处理这些数据.最后当应用程序关闭是,必须合理的释放这些传感器. 本文第一部分将会介绍如何探测初始化几释放传感器,这是非常基础的话题,但是对于基于Kinect开

Kinect for Windows SDK开发入门(一) 开发环境配置

前几天无意中看到微软发布了Kinect for windows sensor,进去看了一下Kinect应用的例子,发现 Kinect除了作为xbox360游戏的外设外还能开发一些很酷的应用,而且微软也发布可针对Kinect开发的 Kinect for windows SDK1.0正式版本,原本想买一个Kinect for windows sensor来进行开发玩一玩的 ,可是那个出来没多久,淘宝上只有代购的,而且比Kinect for Xbox360 sensor贵了很多,而且只能进 行开发,考

Kinect for Windows SDK开发入门(十二)语音识别 上

Kinect的麦克风阵列在Kinect设备的下方.这一阵列由4个独立的水平分布在Kinect下方的麦克风组成.虽然每一个麦克风都捕获相同的音频信号,但是组成阵列可以探测到声音的来源方向.使得能够用来识别从某一个特定的方向传来的声音.麦克风阵列捕获的音频数据流经过复杂的音频增强效果算法处理来移除不相关的背景噪音.所有这些复杂操作在Kinect硬件和Kinect SDK之间进行处理,这使得能够在一个大的空间范围内,即使人离麦克风一定的距离也能够进行语音命令的识别. 在Kinect第一次作为Xbox3

Kinect for Windows SDK开发入门(五)景深数据处理 下

1. 简单的景深影像处理 在上篇文章中,我们讨论了如何获取像素点的深度值以及如何根据深度值产生影像.在之前的例子中,我们过滤掉了阈值之外的点.这就是一种简单的图像处理,叫阈值处理.使用的阈值方法虽然有点粗糙,但是有用.更好的方法是利用机器学习来从每一帧影像数据中计算出阈值.Kinect深度值最大为4096mm,0值通常表示深度值不能确定,一般应该将0值过滤掉.微软建议在开发中使用1220mm(4')~3810mm(12.5')范围内的值.在进行其他深度图像处理之前,应该使用阈值方法过滤深度数据至