Kinect+Unity之手势识别初探
来源:互联网 发布:python做网站的服务器 编辑:程序博客网 时间:2024/06/05 20:55
前几天环境配好了,连上Kinect能跑示例项目KinectView。花了很大的力气找插件的API手册,原来插件并没有官方手册,目前官网也只有两个示例项目。于是自己看代码,想首先学会怎样写一个手势触发特定事件。主要看了BodySourceManager.cs和BodySourceView.cs,中午成功写出了如果左手高过头顶,自动截屏保存图片。
思路是if判断,如果左手的y坐标值大于等于头顶的y坐标值条件为真,触发事件,调用Unity的一个API叫Application.Capturescreenshot()。在BodySourceView.cs中的RefreshBodyObject()函数中修改,这个函数会在Update()中调用,每一帧都会更新。红框部分是自己添加的代码,其余均为无改动的示例源码。
Kinect.JoinType可以按F12查看插件中的源代码,可知是枚举类型,如图
简要分析一下示例程序中的RefreshBodyObejct函数。这个函数主要做的是获取关节点坐标,在Unity中画出人体骨骼。画骨骼直接用Unity的线渲染LineRender(在前面代码中已经调用它的SetVertexCount方法设置画得线有两个端点)。遍历Dictionary类型的_Bonemap(保存的是Key-Value键值对,Value是Key的下一个关联结点),key就是画线段的源位置,value就是线段的目标位置。
完整代码如下
BodySourceManager.csusing UnityEngine;using System.Collections;using Windows.Kinect;public class BodySourceManager : MonoBehaviour { private KinectSensor _Sensor; private BodyFrameReader _Reader; private Body[] _Data = null; public Body[] GetData() { return _Data; } void Start () { _Sensor = KinectSensor.GetDefault(); if (_Sensor != null) { _Reader = _Sensor.BodyFrameSource.OpenReader(); if (!_Sensor.IsOpen) { _Sensor.Open(); } } } void Update () { if (_Reader != null) { var frame = _Reader.AcquireLatestFrame(); if (frame != null) { if (_Data == null) { _Data = new Body[_Sensor.BodyFrameSource.BodyCount]; } frame.GetAndRefreshBodyData(_Data); frame.Dispose(); frame = null; } } } void OnApplicationQuit() { if (_Reader != null) { _Reader.Dispose(); _Reader = null; } if (_Sensor != null) { if (_Sensor.IsOpen) { _Sensor.Close(); } _Sensor = null; } }}
<pre name="code" class="csharp">BodySourceView.csusing UnityEngine;using System.Collections;using System.Collections.Generic;using Kinect = Windows.Kinect;public class BodySourceView : MonoBehaviour { public Material BoneMaterial; public GameObject BodySourceManager; private Dictionary<ulong, GameObject> _Bodies = new Dictionary<ulong, GameObject>(); private BodySourceManager _BodyManager; private Dictionary<Kinect.JointType, Kinect.JointType> _BoneMap = new Dictionary<Kinect.JointType, Kinect.JointType>() { { Kinect.JointType.FootLeft, Kinect.JointType.AnkleLeft }, { Kinect.JointType.AnkleLeft, Kinect.JointType.KneeLeft }, { Kinect.JointType.KneeLeft, Kinect.JointType.HipLeft }, { Kinect.JointType.HipLeft, Kinect.JointType.SpineBase }, { Kinect.JointType.FootRight, Kinect.JointType.AnkleRight }, { Kinect.JointType.AnkleRight, Kinect.JointType.KneeRight }, { Kinect.JointType.KneeRight, Kinect.JointType.HipRight }, { Kinect.JointType.HipRight, Kinect.JointType.SpineBase }, { Kinect.JointType.HandTipLeft, Kinect.JointType.HandLeft }, { Kinect.JointType.ThumbLeft, Kinect.JointType.HandLeft }, { Kinect.JointType.HandLeft, Kinect.JointType.WristLeft }, { Kinect.JointType.WristLeft, Kinect.JointType.ElbowLeft }, { Kinect.JointType.ElbowLeft, Kinect.JointType.ShoulderLeft }, { Kinect.JointType.ShoulderLeft, Kinect.JointType.SpineShoulder }, { Kinect.JointType.HandTipRight, Kinect.JointType.HandRight }, { Kinect.JointType.ThumbRight, Kinect.JointType.HandRight }, { Kinect.JointType.HandRight, Kinect.JointType.WristRight }, { Kinect.JointType.WristRight, Kinect.JointType.ElbowRight }, { Kinect.JointType.ElbowRight, Kinect.JointType.ShoulderRight }, { Kinect.JointType.ShoulderRight, Kinect.JointType.SpineShoulder }, { Kinect.JointType.SpineBase, Kinect.JointType.SpineMid }, { Kinect.JointType.SpineMid, Kinect.JointType.SpineShoulder }, { Kinect.JointType.SpineShoulder, Kinect.JointType.Neck }, { Kinect.JointType.Neck, Kinect.JointType.Head }, }; void Update () { if (BodySourceManager == null) { return; } _BodyManager = BodySourceManager.GetComponent<BodySourceManager>(); if (_BodyManager == null) { return; } Kinect.Body[] data = _BodyManager.GetData();//GetData(); if (data == null) { return; } List<ulong> trackedIds = new List<ulong>(); foreach(var body in data) { if (body == null) { continue; } if(body.IsTracked) { trackedIds.Add (body.TrackingId); } } List<ulong> knownIds = new List<ulong>(_Bodies.Keys); // First delete untracked bodies foreach(ulong trackingId in knownIds) { if(!trackedIds.Contains(trackingId))//List方法测试一个元素是否在List内 { Destroy(_Bodies[trackingId]);//先Destroy掉GameObject _Bodies.Remove(trackingId);//再将键值对从_Bodies字典中移除 } } foreach(var body in data) { if (body == null) { continue; } if(body.IsTracked) { if(!_Bodies.ContainsKey(body.TrackingId)) { _Bodies[body.TrackingId] = CreateBodyObject(body.TrackingId); } RefreshBodyObject(body, _Bodies[body.TrackingId]); } } } private GameObject CreateBodyObject(ulong id) { GameObject body = new GameObject("Body:" + id); for (Kinect.JointType jt = Kinect.JointType.SpineBase; jt <= Kinect.JointType.ThumbRight; jt++) { GameObject jointObj = GameObject.CreatePrimitive(PrimitiveType.Cube); LineRenderer lr = jointObj.AddComponent<LineRenderer>(); lr.SetVertexCount(2);//设置线段数 lr.material = BoneMaterial;//物体的材质 lr.SetWidth(0.05f, 0.05f);//设置线的开始和结束宽度 jointObj.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f); jointObj.name = jt.ToString(); jointObj.transform.parent = body.transform; } return body; } private void RefreshBodyObject(Kinect.Body body, GameObject bodyObject) { for (Kinect.JointType jt = Kinect.JointType.SpineBase; jt <= Kinect.JointType.ThumbRight; jt++) { Kinect.Joint sourceJoint = body.Joints[jt]; Kinect.Joint? targetJoint = null; if(_BoneMap.ContainsKey(jt)) { targetJoint = body.Joints[_BoneMap[jt]];//所以之前字典中设置就是一个一个关节连起来 } Transform jointObj = bodyObject.transform.FindChild(jt.ToString()); jointObj.localPosition = GetVector3FromJoint(sourceJoint); LineRenderer lr = jointObj.GetComponent<LineRenderer>(); if(targetJoint.HasValue) {//Debug.Log (jointObj.localPosition);ok lr.SetPosition(0, jointObj.localPosition); lr.SetPosition(1, GetVector3FromJoint(targetJoint.Value)); lr.SetColors(GetColorForState (sourceJoint.TrackingState), GetColorForState(targetJoint.Value.TrackingState)); } else { lr.enabled = false; }if(body.Joints[Kinect.JointType.HandLeft].Position.Y>=body.Joints[Kinect.JointType.Head].Position.Y){Debug.Log("handleft:"+body.Joints[Kinect.JointType.HandLeft].Position.Y);Debug.Log("head:"+body.Joints[Kinect.JointType.Head].Position.Y);Debug.Log("My LeftHand is Higher than head!~");Application.CaptureScreenshot ("Screenshoot.png", 0);} } } private static Color GetColorForState(Kinect.TrackingState state) { switch (state) { case Kinect.TrackingState.Tracked: return Color.green; case Kinect.TrackingState.Inferred: return Color.red; default: return Color.black; } } private static Vector3 GetVector3FromJoint(Kinect.Joint joint) { return new Vector3(joint.Position.X * 10, joint.Position.Y * 10, joint.Position.Z * 10); }}
自己琢磨代码还是很开心的,代码值得完整的分析在此不赘述了。写博文是有点折腾,但是今天看到别人的技术博客和心得分享真的是很励志(http://www.the5fire.com/ http://blog.csdn.net/the_fire?viewmode=list)。
- Kinect+Unity之手势识别初探
- kinect+openni手势识别
- 手势识别Kinect
- Kinect 手势识别
- Kinect 常用识别手势
- Kinect 手势识别之挥手(C++实现)
- kinect for windows - 手势识别之一,kinect手势识别框架
- kinect 手势识别的原理?
- iOS手势识别初探
- Unity 手势识别插件
- FingerGestures研究院之初探Unity手势操作(一)
- FingerGestures研究院之初探Unity手势操作(一)
- FingerGestures研究院之初探Unity手势操作(一)
- FingerGestures研究院之初探Unity手势操作(一)
- Kinect Windows SDK 开发:手势识别
- 关于Kinect手势识别的一点体会
- 基于Kinect手势跟踪和识别
- 基于C++的Kinect手势识别实现
- 13 Roman to Integer
- 查询android资源R对应的空间
- 关于手机屏幕信息的获取
- RelativeLayout属性
- SpringMVC 学习系列 (5) 之 数据绑定 -2
- Kinect+Unity之手势识别初探
- SpringMVC 学习系列 (6) 之 数据验证
- KMP模板
- codeforces Searching for Graph
- SpringMVC 学习系列 (7) 之 格式化显示
- SpringMVC 学习系列 (8) 之 国际化
- 论文笔记《Fully Convolutional Networks for Semantic Segmentation》
- CodeForces 319B 栈
- Altium Designer如何圆弧走线