Unity使用Kinect初级教程
准备
首先,你需要准备的东西
-
Windows 8以上系统的电脑,当然,配置不要太渣⊙︿⊙
-
Kinect for Windows开发套件
-
安装好Kinect for Windows SDK,这个应该属于开发套件里的吧╮(╯▽╰)╭
-
安装好了Unity5.X,并且确定可以使用
-
Kinect For Windows Wrapper。这是使用unity开发Kinect的中间插件,网上有很多种版本。但是基本都推荐卡耐基梅隆的,我这里也用的是卡耐基梅隆,版本是v2.9。2.7和2.8我都试过,但是使用总有一些问题没有在其他电脑上试过,不知道其他电脑可不可用。反正在这里推荐2.9,至少我用着没问题<( ̄︶ ̄)>。
版本更新了,点击后面那坨云下载2.13版插件 密码:e4uw
入门
上面如果都没有问题的话下面我们可以着手入门开发了
-
新建一个unity项目
-
导入Kinect For Windows Wrapper
-
导入之后可以运行一些Demo,看看我们可以拿这个Kinect做些什么
-
开发的第一步当然是看他的帮助文档,这里面讲述了使用的步骤
-
英文看不懂?我这里有一个翻译得非常粗糙的版本。点我跳过去。作为一个四级没过的能翻译成这样还要啥自行车
-
至此你可以把鼠标移到右上角点×关掉去看帮助文档了。懒癌患者可以继续往下浏览。但是这里我不打算讲太多,还是推荐去看文档,英文原版那个<( ̄︶ ̄)>。
-
好吧,继续。首先配置好你准备角色的Avatar。至于怎么配置我这里说不清楚,去看看这方面的教程,最好是视频的。下图是我在Asset Store里下载的一个角色模型。我们就用它了
-
把角色拖入场景,不要有Rigibody,不要有Collider,Animator里不要有Controller。因为这些可能会影响角色的动画,但我们需要角色的各个节点都能自由移动
-
然后把AvatarController脚本拖给角色
-
新建一个空物体,命名为KinectManager,然后把KinectManager脚本拖给他
-
然后你可以运行测试一下了,这个机器人将会同步你的动作。没错,就是这么简单(>﹏<)。至于具体的参数什么的还是去看文档。这里不多说。
再入门
上面我们已经能让模型反映真实人的动作了,下面来讲解一下动作识别
-
首先,需要把KinectGestures脚本添加到KinectManager这个物体上。
-
新建一个空物体,命名为GestureListener。
-
具体函数的功能什么的在帮助文档里面有。先看关于手势识别的帮助文档,然后在来看下面的代码
代码:
1 using UnityEngine; 2 using System; 3 4 5 public class MyGestureListener : MonoBehaviour, KinectGestures.GestureListenerInterface 6 { 7 [Tooltip("GUI-Text to display gesture-listener messages and gesture information.")] 8 public GUIText gestureInfo; 9 10 // private bool to track if progress message has been displayed 11 private bool progressDisplayed; 12 private float progressGestureTime; 13 14 15 16 /* 17 * 当识别到用户时调用该函数 18 */ 19 public void UserDetected(long userId, int userIndex) 20 { 21 // as an example - detect these user specific gestures 22 KinectManager manager = KinectManager.Instance; 23 //manager.DetectGesture(userId, KinectGestures.Gestures.Jump); 24 //manager.DetectGesture(userId, KinectGestures.Gestures.Squat); 25 //manager.DetectGesture(userId, KinectGestures.Gestures.LeanLeft); 26 //manager.DetectGesture(userId, KinectGestures.Gestures.LeanRight); 27 //manager.DetectGesture(userId, KinectGestures.Gestures.RaiseLeftHand); 28 //manager.DetectGesture(userId, KinectGestures.Gestures.RaiseRightHand); 29 30 manager.DetectGesture(userId, KinectGestures.Gestures.Run); 31 32 if (gestureInfo != null) 33 { 34 gestureInfo.GetComponent<GUIText>().text = "Swipe, Jump, Squat or Lean."; 35 } 36 Debug.Log("发现用户"); 37 } 38 39 40 41 /* 42 * 当失去用户时出发 43 */ 44 public void UserLost(long userId, int userIndex) 45 { 46 if (gestureInfo != null) 47 { 48 gestureInfo.GetComponent<GUIText>().text = string.Empty; 49 } 50 Debug.Log("失去用户"); 51 } 52 53 54 /// <summary> 55 /// Invoked when a gesture is in progress. 56 /// </summary> 57 /// <param name="userId">被识别者的id</param> 58 /// <param name="userIndex">被识别者的序号</param> 59 /// <param name="gesture">手势类型</param> 60 /// <param name="progress">手势识别的进度,可以认为是相似度。范围是[0,1]</param> 61 /// <param name="joint">关节类型</param> 62 /// <param name="screenPos">视图坐标的单位向量</param> 63 public void GestureInProgress(long userId, int userIndex, KinectGestures.Gestures gesture, 64 float progress, KinectInterop.JointType joint, Vector3 screenPos) 65 { 66 /* 67 * 主要将一些需要动态监测的手势放在这个函数下 68 * 比如说缩放、滚轮都是依据你两手之间的距离来判断应该缩放或旋转多少度 69 */ 70 71 //监测缩放,如果相似度大于50% 72 if ((gesture == KinectGestures.Gestures.ZoomOut || gesture == KinectGestures.Gestures.ZoomIn) && progress > 0.5f) 73 { 74 if (gestureInfo != null) 75 { 76 string sGestureText = string.Format("{0} - {1:F0}%", gesture, screenPos.z * 100f); 77 gestureInfo.GetComponent<GUIText>().text = sGestureText; 78 79 progressDisplayed = true; 80 progressGestureTime = Time.realtimeSinceStartup; 81 } 82 } 83 else if ((gesture == KinectGestures.Gestures.Wheel || gesture == KinectGestures.Gestures.LeanLeft || 84 gesture == KinectGestures.Gestures.LeanRight) && progress > 0.5f) 85 { 86 if (gestureInfo != null) 87 { 88 string sGestureText = string.Format("{0} - {1:F0} degrees", gesture, screenPos.z); 89 gestureInfo.GetComponent<GUIText>().text = sGestureText; 90 91 progressDisplayed = true; 92 progressGestureTime = Time.realtimeSinceStartup; 93 } 94 } 95 else if (gesture == KinectGestures.Gestures.Run && progress > 0.5f) 96 { 97 if (gestureInfo != null) 98 { 99 string sGestureText = string.Format("{0} - progress: {1:F0}%", gesture, progress * 100); 100 gestureInfo.GetComponent<GUIText>().text = sGestureText; 101 102 progressDisplayed = true; 103 progressGestureTime = Time.realtimeSinceStartup; 104 } 105 } 106 } 107 108 109 110 111 /// <summary> 112 /// 当一个手势识别完成后被调用 113 /// </summary> 114 /// <returns>true</returns> 115 /// <c>false</c> 116 /// <param name="userId">被识别者的ID</param> 117 /// <param name="userIndex">被识别者的序号</param> 118 /// <param name="gesture">被识别到的手势类型</param> 119 /// <param name="joint">被识别到的关节类型</param> 120 /// <param name="screenPos">视图坐标的单位向量</param> 121 public bool GestureCompleted(long userId, int userIndex, KinectGestures.Gestures gesture, 122 KinectInterop.JointType joint, Vector3 screenPos) 123 { 124 if (progressDisplayed) 125 return true; 126 127 string sGestureText = gesture + " detected"; 128 if (gestureInfo != null) 129 { 130 gestureInfo.GetComponent<GUIText>().text = sGestureText; 131 } 132 133 return true; 134 } 135 136 137 138 //参数同上,在手势被取消的时候调用 139 public bool GestureCancelled(long userId, int userIndex, KinectGestures.Gestures gesture, 140 KinectInterop.JointType joint) 141 { 142 if (progressDisplayed) 143 { 144 progressDisplayed = false; 145 146 if (gestureInfo != null) 147 { 148 gestureInfo.GetComponent<GUIText>().text = String.Empty; 149 } 150 } 151 152 return true; 153 } 154 155 public void Update() 156 { 157 if (progressDisplayed && ((Time.realtimeSinceStartup - progressGestureTime) > 2f)) 158 { 159 progressDisplayed = false; 160 161 if (gestureInfo != null) 162 { 163 gestureInfo.GetComponent<GUIText>().text = String.Empty; 164 } 165 166 Debug.Log("Forced progress to end."); 167 } 168 } 169 170 }
-
这个代码我直接用的官方的实例修改的。为了显示出效果,可以新建一个空物体,添加上GUI Text组件,让他显示识别的效果
-
好了,你可以测试一下了
下面来讲关于手势识别的,上面讲的手势其实是Gesture的翻译,是全身的;下面讲的手势是针对于手的
好了,咋们。。。。︿( ̄︶ ̄)
继续入门
-
首先要知道Kinect可以识别的手势。定义在KinectInterop.HandState这个枚举类型中
-
你可以通过KinectManager的GetRightHandState(long UserID)来获取用户的右手手势状态(别问我怎么获取左手→_→)
-
下面发一段给电脑玩剪刀石头布的代码。代码比较粗糙,不过作为学习还是阔仪滴
<( ̄︶ ̄)>
-
1 using UnityEngine; 2 using UnityEngine.UI; 3 using System.Collections; 4 using System; 5 6 7 public class MyGestureListener : MonoBehaviour, KinectGestures.GestureListenerInterface 8 { 9 public Text gestureInfo; 10 private bool state = false;//识别状态,0表示未识别,1表示已识别 11 public float intervalTime = 5.0f; 12 private bool intervalBegin = false; 13 private int quiet = 0; 14 private float quiettime = 5.0f; 15 public enum 手势 16 { 17 剪刀, 18 石头, 19 布 20 } 21 private 手势 RandomShoushi() 22 { 23 System.Random ran = new System.Random(); 24 int randomnum = ran.Next(0, 2); 25 return (手势)randomnum; 26 } 27 28 private string getInfo(KinectInterop.HandState show, 手势 shoushi) 29 { 30 string info = string.Empty; 31 switch (show) 32 { 33 case KinectInterop.HandState.Closed:info= "你出的是石头\n"; 34 break; 35 case KinectInterop.HandState.Lasso: info = "你出的是剪刀\n"; 36 break; 37 case KinectInterop.HandState.Open:info= "你出的是布\n"; 38 break; 39 default: info = "请出招...\n"; 40 return info; 41 } 42 43 switch (shoushi) 44 { 45 case 手势.石头: 46 info += "电脑出的是石头\n"; 47 break; 48 case 手势.剪刀: 49 info += "电脑出的是剪刀\n"; 50 break; 51 case 手势.布: 52 info += "电脑出的是布\n"; 53 break; 54 } 55 int res = contrast(show, shoushi); 56 if (res == 1) 57 { 58 info += "哈哈哈,你赢了\n"; 59 } 60 else if (res == -1) 61 { 62 info += "哈哈哈,你输了\n"; 63 }else if (res == 0) 64 { 65 info += "哈哈哈,平手"; 66 } 67 else 68 { 69 info += "你的手势未识别"; 70 } 71 72 state = true;//识别完成 73 return info; 74 75 } 76 77 78 private int contrast(KinectInterop.HandState show,手势 shoushi) 79 { 80 int rssult = 0; 81 82 switch (show) 83 { 84 case KinectInterop.HandState.Closed: 85 switch (shoushi) 86 { 87 case 手势.石头:rssult = 0; 88 break; 89 case 手势.剪刀: 90 rssult = 1; 91 break; 92 case 手势.布: 93 rssult = -1; 94 break; 95 } 96 break; 97 case KinectInterop.HandState.Lasso: 98 switch (shoushi) 99 { 100 case 手势.石头: 101 rssult = -1; 102 break; 103 case 手势.剪刀: 104 rssult = 0; 105 break; 106 case 手势.布: 107 rssult = 1; 108 break; 109 } 110 break; 111 case KinectInterop.HandState.Open: 112 switch (shoushi) 113 { 114 case 手势.石头: 115 rssult = 1; 116 break; 117 case 手势.剪刀: 118 rssult = -1; 119 break; 120 case 手势.布: 121 rssult = 0; 122 break; 123 } 124 break; 125 default:rssult = 10; 126 break; 127 } 128 return rssult; 129 } 130 void Update() 131 { 132 133 if (intervalBegin) 134 { 135 if (intervalTime > 0) 136 { 137 intervalTime -= Time.deltaTime; 138 } 139 else 140 { 141 intervalBegin = false; 142 intervalTime = 5.0f; 143 state = false; 144 } 145 } 146 147 if (!state) 148 { 149 KinectManager _manager = KinectManager.Instance; 150 long userid = _manager.GetUserIdByIndex(0); 151 gestureInfo.text=getInfo(_manager.GetRightHandState(userid), RandomShoushi()); 152 } 153 if (quiet==1) 154 { 155 gestureInfo.text = "再右挥一次就不跟你玩了..."; 156 if (quiet == 2) 157 { 158 Debug.Log("退出"); 159 Application.Quit(); 160 161 } 162 if (quiettime < 0) 163 { 164 quiet = 0; 165 quiettime = 5.0f; 166 gestureInfo.text = "请出招..."; 167 } 168 else 169 { 170 quiettime -= Time.deltaTime; 171 } 172 } 173 } 174 175 public void UserDetected(long userId, int userIndex) 176 { 177 //throw new NotImplementedException(); 178 KinectManager manager = KinectManager.Instance; 179 manager.DetectGesture(userId, KinectGestures.Gestures.SwipeLeft); 180 } 181 182 public void UserLost(long userId, int userIndex) 183 { 184 //throw new NotImplementedException(); 185 } 186 187 public void GestureInProgress(long userId, int userIndex, KinectGestures.Gestures gesture, float progress, KinectInterop.JointType joint, Vector3 screenPos) 188 { 189 //throw new NotImplementedException(); 190 } 191 192 public bool GestureCompleted(long userId, int userIndex, KinectGestures.Gestures gesture, KinectInterop.JointType joint, Vector3 screenPos) 193 { 194 //throw new NotImplementedException(); 195 if (gesture== KinectGestures.Gestures.SwipeLeft) 196 { 197 intervalBegin = true; 198 gestureInfo.text = "准备出招..."; 199 } 200 if (gesture == KinectGestures.Gestures.SwipeRight) 201 { 202 quiet++; 203 } 204 return true; 205 } 206 207 public bool GestureCancelled(long userId, int userIndex, KinectGestures.Gestures gesture, KinectInterop.JointType joint) 208 { 209 //throw new NotImplementedException(); 210 return true; 211 } 212 }