准備
首先,你需要准備的東西
-
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 }