Unity使用Kinect初級教程


准備

首先,你需要准備的東西

  1. Windows 8以上系統的電腦,當然,配置不要太渣⊙︿⊙
  2. Kinect for Windows開發套件
  3. 安裝好Kinect for Windows SDK,這個應該屬於開發套件里的吧╮(╯▽╰)╭
  4. 安裝好了Unity5.X,並且確定可以使用
  5. Kinect For Windows Wrapper。這是使用unity開發Kinect的中間插件,網上有很多種版本。但是基本都推薦卡耐基梅隆的,我這里也用的是卡耐基梅隆,版本是v2.9。2.7和2.8我都試過,但是使用總有一些問題沒有在其他電腦上試過,不知道其他電腦可不可用。反正在這里推薦2.9,至少我用着沒問題<( ̄︶ ̄)>。

  可以點擊后面那坨雲下載2.9版插件 點擊下載 密碼:6abd

  版本更新了,點擊后面那坨雲下載2.13版插件 點擊下載 密碼:e4uw

入門

上面如果都沒有問題的話下面我們可以着手入門開發了

  1. 新建一個unity項目
  2. 導入Kinect For Windows Wrapper
  3. 導入之后可以運行一些Demo,看看我們可以拿這個Kinect做些什么

  4. 開發的第一步當然是看他的幫助文檔,這里面講述了使用的步驟

  5. 英文看不懂?我這里有一個翻譯得非常粗糙的版本。點我跳過去。作為一個四級沒過的能翻譯成這樣還要啥自行車
  6. 至此你可以把鼠標移到右上角點×關掉去看幫助文檔了。懶癌患者可以繼續往下瀏覽。但是這里我不打算講太多,還是推薦去看文檔,英文原版那個<( ̄︶ ̄)>。
  7. 好吧,繼續。首先配置好你准備角色的Avatar。至於怎么配置我這里說不清楚,去看看這方面的教程,最好是視頻的。下圖是我在Asset Store里下載的一個角色模型。我們就用它了

  8. 把角色拖入場景,不要有Rigibody,不要有Collider,Animator里不要有Controller。因為這些可能會影響角色的動畫,但我們需要角色的各個節點都能自由移動
  9. 然后把AvatarController腳本拖給角色

  10. 新建一個空物體,命名為KinectManager,然后把KinectManager腳本拖給他
  11. 然后你可以運行測試一下了,這個機器人將會同步你的動作。沒錯,就是這么簡單(>﹏<)。至於具體的參數什么的還是去看文檔。這里不多說。

     

再入門

上面我們已經能讓模型反映真實人的動作了,下面來講解一下動作識別

  1. 首先,需要把KinectGestures腳本添加到KinectManager這個物體上。
  2. 新建一個空物體,命名為GestureListener。
  3. 新建一個腳本MyGestureListener.cs。這個腳本需要繼承MonoBehaviour類並且實現KinectGestures.GestureListenerInterface接口。
  4. 具體函數的功能什么的在幫助文檔里面有。先看關於手勢識別的幫助文檔,然后在來看下面的代碼

    代碼:

     

      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 }

     

  5. 這個代碼我直接用的官方的實例修改的。為了顯示出效果,可以新建一個空物體,添加上GUI Text組件,讓他顯示識別的效果

  6. 好了,你可以測試一下了

 

下面來講關於手勢識別的,上面講的手勢其實是Gesture的翻譯,是全身的;下面講的手勢是針對於手的

好了,咋們。。。。︿( ̄︶ ̄)

繼續入門

  1. 首先要知道Kinect可以識別的手勢。定義在KinectInterop.HandState這個枚舉類型中

  2. 你可以通過KinectManager的GetRightHandState(long UserID)來獲取用戶的右手手勢狀態(別問我怎么獲取左手→_→)
  3. 下面發一段給電腦玩剪刀石頭布的代碼。代碼比較粗糙,不過作為學習還是闊儀滴

    <( ̄︶ ̄)>

  4.   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 }

     


     

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM