前言:

之前写过一篇关于姿势(pose)识别的博文,之后又定义了几个姿势实现了体感俄罗斯方块。姿势识别是通过关节点与关节点之间的相对位置关系来进行判断。当判断成立,即执行指定的指令。那么,我们就可以指定姿势实现我们的天花乱坠的想法啦~~~ PPT播放助手应运而生。

  基本思路:

有了Kinect,我们就可以使用手势(手部姿势)来控制幻灯片的播放,而不需要一边演讲一遍按键盘或者手持一个ppt控制器,我们只需要做的就是双手握住头部就实现放映,轻轻的向左或者向右挥一下手就可以控制幻灯片向前或者向后翻一页,双手举起就使屏幕变黑。酷吧。虽然可能在演讲的时候做这个动作可能有点奇怪,但是这也是一种控制幻灯片放映的好方法。

实现Kinect控制幻灯片播放很简单,主要思路是:使用Kinect捕捉人体动作,然后根据识别出来的动作向系统发出点击向前,向后,"F5","B"按键的事件,从而使得幻灯片能够切换,放映,变黑。 这里的核心功能在于手势的识别,我们在开发之前需要定义怎么样的手势算是向前或者向后切换幻灯片。

对应关系:

姿势 对应按键 触发动作
双手抱住头部 F5 放映
向左挥动左手 left 上一页
向右挥动右手 right 下一页
双手举起 B 变黑

代码实现

由于之前几篇博文已经写了获取Kinect各种数据的代码,在此就讨论关键部分的代码。

由于是姿势控制,自然存在精确度的问题,所以我们需要定义几个阈值,作为判断依据。

/// <summary>
/// 手臂水平伸展的阈值
/// </summary>
private const double ArmStretchedThreshold = 0.45;/// <summary>
/// 手臂垂直上举的阈值
/// </summary>
private const double ArmRaisedThreshold = 0.20;/// <summary>
/// 头离双手距离的阈值
/// </summary>
private const double DistanceThreshold = 0.05; 

在控制ppt播放命令中,我们设定,如果双手距离头部小于0.05,认为用户试图进行点击键盘上的F5键,如果右手关节点在x轴上的距离比头部关节点大于0.45的话,认为用户试图进行点击键盘上的right按钮。如果头部关节点位置在x轴方向是比左手关节点在x轴上的位置大于0.45的话,认为用户试图点击键盘上的left按钮。如果双手超过头部高度0.20的话,认为用户试图点击键盘上的B键,0.05、0.45和0.20这几个阈值是通过反复测试的出来的(没错,是Test,而不是Dubug);所以,测试很重要。

关键代码如下:

/// <summary>
/// 处理手势的方法
/// </summary>
/// <param name="head"></param>
/// <param name="rightHand"></param>
/// <param name="leftHand"></param>
private void ProcessForwardBackGesture(Joint head, Joint rightHand, Joint leftHand)
{//若右手位置的横坐标值超过设定的阈值,除法PPT下一页命令if (rightHand.Position.X > head.Position.X + ArmStretchedThreshold){if (!isForwardGestureActive){//激活forward命令,确保每次操作执行一次命令isForwardGestureActive = true;//模拟鼠标按下“右”方向键System.Windows.Forms.SendKeys.SendWait("{Right}");}}else{isForwardGestureActive = false;}//若左手位置的横坐标超过设定的阈值,触发PPT上一页命令if (leftHand.Position.X < head.Position.X - ArmStretchedThreshold){if (!isBackGestureActive){//激活back命令,确保每次操作执行一次命令isBackGestureActive = true;//模拟鼠标按下“左”方向键System.Windows.Forms.SendKeys.SendWait("{Left}");}}else{isBackGestureActive = false;}//双手同时上举,在控制PPT时让屏幕变黑if ((leftHand.Position.Y > head.Position.Y - ArmRaisedThreshold) && (rightHand.Position.Y > head.Position.Y - ArmRaisedThreshold)){if (!isBlackScreenActive){isBlackScreenActive = true;System.Windows.Forms.SendKeys.SendWait("{B}");}}else{isBlackScreenActive = false;}//判断双手靠近头部,触发PPT放映if (Math.Abs(head.Position.Y - rightHand.Position.Y) < DistanceThreshold && (Math.Abs(head.Position.Y - leftHand.Position.Y) < DistanceThreshold && !isForwardGestureActive &&!isBackGestureActive)){if (!isPresent){ isPresent = true;System.Windows.Forms.SendKeys.SendWait("{F5}");}}else{isPresent = false;}
}

上面的代码中,当判断到用户向右挥手动作是,执行System.Windows.Forms.SendKeys.SendWait("{Right}")语句从而发出点击键盘向右按键; 该方法执行时,要求PowerPoint程序处于当前活动的状态,这样里面的PPT才会向右键盘点击事件。需要注意的是方法中isBackGestureActive,isForwardGestureActive,isBlackScreenActive和isPresent这四个布尔型的标志位,可以防止当用户一直处于某一个动作时会一直发送System.Windows.Forms.SendKeys.SendWait("{xx}")。

上面的方法需要放在sensor_SkeletonFrameReady事件中,首先获取头部,左手右手关节点数据,然后调用该方法。

/// <summary>
/// 骨骼事件处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void sensor_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{using (var skeletonFrame = e.OpenSkeletonFrame()){if (skeletonFrame == null)return;if (skeletons == null ||skeletons.Length != skeletonFrame.SkeletonArrayLength){skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];}skeletonFrame.CopySkeletonDataTo(skeletons);}Skeleton closestSkeleton = skeletons.Where(s => s.TrackingState == SkeletonTrackingState.Tracked).OrderBy(s => s.Position.Z * Math.Abs(s.Position.X)).FirstOrDefault();if (closestSkeleton == null)return;var head = closestSkeleton.Joints[JointType.Head];var rightHand = closestSkeleton.Joints[JointType.HandRight];var leftHand = closestSkeleton.Joints[JointType.HandLeft];if (head.TrackingState == JointTrackingState.NotTracked ||rightHand.TrackingState == JointTrackingState.NotTracked ||leftHand.TrackingState == JointTrackingState.NotTracked){//Don't have a good read on the joints so we cannot process gesturesreturn;}//调用填充头和双手位置图案的的方法SetEllipsePosition(ellipseHead, head, false);SetEllipsePosition(ellipseLeftHand, leftHand, isBackGestureActive);SetEllipsePosition(ellipseRightHand, rightHand, isForwardGestureActive);//调用处理手势的方法ProcessForwardBackGesture(head, rightHand, leftHand);
}

代码已开诚布公到GitHub:https://github.com/Marsyangkang/KinectPowerpointControl

Kinect开发系列博文:

Kinect开发之 Interaction交互设计  
http://yacare.iteye.com/blog/1979683
Kinect开发之结合Unity3D进行游戏应用开发
http://yacare.iteye.com/blog/1950164
Kinect开发之体感举起手来程序设计(Kinect俄罗斯方块)
http://yacare.iteye.com/blog/1950133
Kinect开发之简单姿势识别
http://yacare.iteye.com/blog/1950112
Kinect开发之获取骨骼关节数据并绘制成火柴人
http://yacare.iteye.com/blog/1950085

Kinect开发之PowerPoint播放助手相关推荐

  1. 安卓开发之SoundPool播放音效

    文章预览 前言 一.简单使用 1.1.activity_sound.xml 1.2.SoundActivity.java 1.3.RecyclerView适配器 二.效果 前言 SoundPool一般 ...

  2. Android开发之Audio播放:竞争Audio之Audio Focus的应用

    Android是多任务系统,Audio系统是竞争资源.Android2.2之前,没有内建的机制来解决多个程序竞争Audio的问题,2.2引入了称作AudioFocus的机制来管理对Audio资源的竞争 ...

  3. android语音播放工具类,Android开发之MediaPlayer多媒体(音频,视频)播放工具类

    本文实例讲述了Android开发之MediaPlayer多媒体(音频,视频)播放工具类.分享给大家供大家参考,具体如下: package com.android.imooc.chat; import ...

  4. 网页开发之amr音频的播放

    mp3格式播放大家都知道,amr格式就陌生了,至少我之前没有做过 amr格式文件播放出来的声音音质比mp3差,主要应用于手机铃声和手机录音,目的是为了给手机用户节省流量.大部分主流的音视频播放器都支持 ...

  5. android vr播放器 开发,Android应用开发之Android VR Player(全景视频播放器)- ExoPlayer播放器MPEG-DASH视频播放...

    本文将带你了解Android应用开发之Android VR Player(全景视频播放器)- ExoPlayer播放器MPEG-DASH视频播放,希望本文对大家学Android有所帮助. Androi ...

  6. SkeyeWebPlayer.js H5播放器开发之webpack编译flv.js实现基础播放器功能(二)

    SkeyeWebPlayer.js H5播放器是由成都视开信息科技开发和维护的一个完善的RTSP.FLV.HLS等多种流媒体协议播放,视频编码支持H.264,H.265,音频支持AAC,支持TCP/U ...

  7. iOS开发之AVKit框架使用

    2019独角兽企业重金招聘Python工程师标准>>> iOS开发之AVKit框架使用 一.引言 在iOS开发框架中,AVKit是一个非常上层,偏应用的框架,它是基于AVFounda ...

  8. Android NDK开发之旅31 FFmpeg音频解码

    ###前言 #####基于Android NDK开发之旅30--FFmpeg视频播放这篇文章,我们已经学会视频解码基本过程.这篇文章就对音频解码进行分析. #####音频解码和视频解码的套路基本是一样 ...

  9. Android NDK开发之 NEON基础介绍

    原文:http://blog.csdn.net/app_12062011/article/details/50434259 Android NDK开发之 NEON基础介绍 这是官方介绍: http:/ ...

最新文章

  1. Load Runner测试脚本(tuxedo服务)的编写指南
  2. Spring Web Application Security
  3. 无废话ExtJs 入门教程二十三[员工管理实例:Demo]
  4. Http Get 和 Post
  5. Delphi中的基础数据类型
  6. Mr.J--.c 和.cpp 后缀详解
  7. 一年换7家公司,95后跳槽多疯狂
  8. PLSQL Developer工具远程连接Oracle数据库的方法
  9. Python+django建站入门篇(2):素数判断
  10. Python为什么要self
  11. C++与tolua++的完整调用流程,超级详解解决交互疑难
  12. 用信号量及其PV操作处理实际问题
  13. TP框架漏洞复现(持续更新)
  14. Windows中的NTUSER.DAT文件是什么?
  15. 世界地图中国地图高清版
  16. 华硕t100安装linux,华硕T100ta 安装凤凰OS失败
  17. mysql分组取最新一条数据
  18. 40多个JAVA手机游戏打包
  19. 远程办公解决方案 6款远程办公必备工具
  20. php 公众号发表文章,公众号如何发文章不限次数(微信公众平台发文章流程)...

热门文章

  1. 基于ICP的点云融合拼接
  2. 如何让图像过渡更自然 python_如何使用Python和OpenCV融合、拼接照片?
  3. 【二维线段树】20150209测试 千石抚子的三维积木
  4. 议题征集倒计时|Pulsar Summit Asia 2021 议题征集截至 9 月 30 日
  5. oracle安装没有scott,Oracle安装时忘记解锁scott用户的解决方案
  6. 本地html页面录音,JavaScript实现页面中录音功能的方法
  7. Maven下载与配置详细教程
  8. Python Magic——文件操作
  9. 最新sogou搜狗搜索 机智操作绕过反爬验证码!
  10. 计算机软件应用职业规划,计算机软件专业的职业生涯规划