Kinect SDK 正式版(二)骨骼追踪,实现PC版体感水果忍者

来源:互联网 发布:为什么衍生网络主播 编辑:程序博客网 时间:2024/05/29 16:59

    这篇来介绍一下几个正式版SDK提供的新特性,还有比较被主流应用的骨骼数据操作。

    首先先介绍一个新特性,Kinect角度调整,继续上篇的项目工程,在界面上添加两个控件,一个下拉列表,一个按钮。

<Button Content="角度调整" Height="23" HorizontalAlignment="Left" Margin="138,276,0,0" Name="button3" VerticalAlignment="Top" Width="75" Click="button3_Click" /><ComboBox Height="23" HorizontalAlignment="Left" Margin="12,276,0,0" Name="comboBox2" VerticalAlignment="Top" Width="120" />

并添加按钮的后台处理事件:

private void button3_Click(object sender, RoutedEventArgs e){    ks.ElevationAngle = (int)this.comboBox2.SelectedItem;}

并准备获取角度值并放入下拉列表的方法:

        private void LoadElevationAngle()        {            int min = ks.MinElevationAngle;            int max = ks.MaxElevationAngle;            for (int i = min; i <= max; i++)            {                this.comboBox2.Items.Add(i);            }            this.comboBox2.SelectedValue = ks.ElevationAngle;        }

PS:这里的ks是继续上篇工程中的button2_Click事件中的ks对象提取到了方法外面作为全局变量来访问。并在button2_Click事件中,启动了Kinect后调用LoadElevationAngle()加载kinect角度值。

然后我们就可以通过改变下拉列表中的值后,然后点击按钮,来调整Kinect角度:

然后进入这篇的正题,骨骼信息追踪。

继续在启动前加入代码:

        //添加骨骼数据获取事件        ks.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(ks_SkeletonFrameReady);        //设置启动,启动骨骼监听        ks.SkeletonStream.Enable();        void ks_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)        {            //获得所有骨骼信息            SkeletonFrame sf = e.OpenSkeletonFrame();            if (sf != null)            {                //取出骨骼信息                Skeleton[] arrS = new Skeleton[sf.SkeletonArrayLength];                sf.CopySkeletonDataTo(arrS);                Skeleton skeleton = null;                //获取第一个追踪到的骨骼信息                foreach (var item in arrS)                {                    if (item.TrackingState == SkeletonTrackingState.Tracked)                    {                        skeleton = item;                        break;                    }                }                //如果有,获得这个人的右手点                if (skeleton != null)                {                    Joint hand = skeleton.Joints[JointType.HandRight];                }            }        }

其中JointType包含20个值,可以取人体二十个有效骨骼点信息,但是只有这20个可以用么?理论上不是的,这20个只是kinect提供使用的,更多的点是可以通过算法计算出来位置的。下图介绍了Kinect支持的点的分布情况:

这之后我们能获取好多点的信息,可以应用这些信息能做些什么呢?这个就有待于大家积极地发现了,那么延续上面的功能,再多扩展点功能,使用右手点来控制鼠标移动来玩水果忍着吧,那么在获取到右手点的位置添加下面代码:

                //如果有,获得这个人的右手点                if (skeleton != null)                {                    Joint hand = skeleton.Joints[JointType.HandRight];                    if (reHand != null)                    {                        int x,y;                        GetScreenPoint(hand, reHand, out x, out y);                        //鼠标按下                        mouse_event(MouseEventFlag.LeftDown, 0, 0, 0, 0);                        //鼠标移动                        mouse_event(MouseEventFlag.Move, x, y, 0, 0);                    }                    reHand = hand;                }

 

添加方法外的全局变量以及win32函数引用:

        private Joint reHand;        enum MouseEventFlag : uint        {            Move = 0x0001,             LeftDown = 0x0002,             LeftUp = 0x0004,             RightDown = 0x0008,             RightUp = 0x0010,             MiddleDown = 0x0020,             MiddleUp = 0x0040,             XDown = 0x0080,             XUp = 0x0100,             Wheel = 0x0800,             VirtualDesk = 0x4000,             Absolute = 0x8000        }        [DllImport("user32.dll")]        static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, int extraInfo);

 

补充两个点换算的方法:

        private void GetScreenPoint(Joint hand, Joint hand2, out int w, out int h)        {            double w1;            double h1;            GetScreenPoint(hand, out w1, out h1);            double w2;            double h2;            GetScreenPoint(hand2, out w2, out h2);            w = (int)(w1 - w2);            h = (int)(h1 - h2);        }        private void GetScreenPoint(Joint hand, out double w, out double h)        {            w = SystemParameters.PrimaryScreenWidth;            h = SystemParameters.PrimaryScreenHeight;            w = w / 2 + hand.Position.X * w;            h = h / 2 - hand.Position.Y * h;        }

 

 

现在运行起来,并且获得人体信息的时候就会鼠标按下,别且计算两次点的相对坐标来移动鼠标了。怎么样,你的水果忍着能体感了么?呵呵,这篇代码上的比较全了,如果需要帮助,可以留言,或者发送邮件到:57512434@qq.com,看到后会第一时间回复的。

有好多Kinect的应用已经出来了,Kinect控制机器人、代替遥控器、商场试衣,相信陆续会有更多惊喜。

 

原创粉丝点击