Kinect學習
標籤:Kinect Windows
買了Kinect之後學習了好久,姑且做個階段性的總結吧。之後的實踐部分單獨再出一篇文章。
參考資料:
遇到的問題:
一、Kinect2.0概述以及Kinect數據源預覽
基本介紹了Kinect2.0的大概內容,以及開發好的Kinect SDK for windows,以及將來要和Unity團隊共同開發的插件。
Kinect擁有包括深度信息、紅外信息在內的一系列信息,其中深度信息非常的精確。
kinect Unity plugin
參考資料
- 寫的很好地博客:Unity2017使用Kinect v2簡單介紹及基本操作
- Unity for kinect的開發教程
- Unity + Kinect Document
- Unity Kinect中創建自定義手勢,然後用於Unity
- Kinect Manager詳細API
- Kinect Manager概要API,與註釋十分類似
Kinect Manager
Kinect手勢識別實踐
視頻課程筆記
微軟:快速入門Kinect for windows v2開發
6.1 介紹Kinect Studio
Kinect Studio教學
操作,在Kinect Studio中錄製動作
6.2 手勢識別
打開了C#的Body Basic的代碼,進行了修改實例。還不錯,但是Unity中用到的組件和這裏的似乎不太一樣。
Visual Gesture Builder的培訓步驟:通過Kinect Studio記錄手勢,使用Gesture Builder打標記,使用GestureBuilder去構建和分析手勢,在Gesture Builder中預覽手勢。最終,將自定義的手勢所存儲的數據庫整合到程序之中。
8.1 自定義手勢,錄製與回放
Visual Gesture Builder,使用Machine learning製作自定義動作
8.2 使用Kinect Gesture Builder
8.3 將創建的動作植入程序
9.1 瞭解離散手勢和連貫手勢
9.2 創建連貫手勢
9.3 使用Visual Gesture Builder創建自動標記片段
官方文檔學習
如何處理離散的手勢,像是揮手和舉手
- 在腳本的
UserDetected()
函數中添加下列語句manager.DetectGesture(userId, KinectGestures.Gestures.xxxxx);
- 在
GestureCompleted()
函數中提那家如何處理離散手勢,比如
if(gesture == KinectGestures.Gestures.xxxxx)
{
// gesture is detected - process it (for instance, set a flag or execute an action)
}
- 在
GestureCancelled()
函數中,處理如果連續手勢被取消了該怎麼做
if(gesture == KinectGestures.Gestures.xxxxx)
{
// gesture is cancelled - process it (for instance, clear the flag)
}
- 對於需要檢測新的手勢或動作的實例,需要將它作爲KinectController的組件。
如何處理連續的手勢,像是放大、縮小和轉方向盤
連續手勢並不會返回一個完全完成的布爾值,而是一個百分比,如果大於50%則報告。
- 在
UserDetected()
函數中,添加下面的內容manager.DetectGesture(userId, KinectGestures.Gestures.xxxxx);
- 在
GestureInProgress()
函數中,添加下面的內容
if(gesture == KinectGestures.Gestures.xxxxx)
{
if(progress > 0.5f)
{
// gesture is detected - process it (for instance, set a flag, get zoom factor or angle)
}
else
{
// gesture is no more detected - process it (for instance, clear the flag)
}
}
- 在
GestureCancelled()
函數中,添加下面的內容
if(gesture == KinectGestures.Gestures.xxxxx)
{
// gesture is cancelled - process it (for instance, clear the flag)
}
- 將其作爲KinectController的組件
如何在K2-assert中使用VGB手勢
Visual Gesture Builder創建額VGB對象也可以被用在K2-assert中。遵循下面的步驟:
- 將手勢數據庫(xxx.gbd)拷貝到
Resources-folder
並重命名它爲xxx.gbd.bytes
- 將VisualGestureManager-script作爲場景中一個gameobject的組件
- 設置VisualGestureManager-component中
Gesture Database
的值設爲第一步中的xxx.gbd
- 創建一個visual-gesture-listener來處理手勢,並將它作爲場景中Gameobject的一個組件(參考
SimpleVisualGestureListener-script
) - 在
GestureInProgress()
函數中添加手勢監聽器的代碼來檢測連續手勢,並在GestureCompleted()
函數中加入代碼來檢測離散手勢
如何創建屬於你的手勢
對於手勢識別而言,有兩種選擇:Visual gesture(用Visual Gesture Builder創建),或是預編程的手勢(被包括在KinectGestures.cs中)。對於自己的預編程手勢的創建可以參考這裏
用來證明編程性手勢的檢測的demo放在KinectDemos/GesturesDemo-folder
中。第一個KinectGesturesDemo1-scene
展示瞭如何使用離散手勢,第二個KinectGesturesDemo2-scene
展示瞭如何使用連續手勢
這裏有一個創建和檢查visual gesture的視頻,也可以查看KinectDemos/GestureDemo/VisualGesturesDemo-scene
來學習如何在Unity中使用Visual Gestrues。不過visual gesture只在32-bit下順利工作。
如何創建自己的程序性手勢
如上文所說,程序性手勢一般被定義在KinectScripts/KinectGestures.cs
中或是其他的擴展這個文件的類中。手勢的檢測包括了對不同手勢狀態下手勢動作的檢查。
- 打開
KinectScripts/KinectGestures.cs
,將你的手勢名稱添加到Gestures-enum
中。你需要知道,C#中enum對象時不能夠被繼承的,因此你只能夠在這裏進行修改。當然,如果你不想修改這個文件的話,可以爲你的手勢使用predefinedUserGestureX-names
- 在打開的文件中找到
CheckForGesture()
方法,添加新手勢的例子,在內部switch代碼的結尾。這裏會包含着檢測手勢的代碼。 - 在
gesture-case
中,提那家內部的switch代碼來檢測用戶在不同階段下的手勢。如果你需要例子的話,可以查看其他的簡單手勢,比如舉左手、舉右手等。
在CheckForGestures()
方法中,你會訪問到jointsPos-array
,這裏包含了所有的關節位置。以及jointsTracked-array
,包含了關節是否被檢測到。關節位置使用的是以米爲單位的世界座標。
手勢識別代碼通常包括了對用戶在當前手勢狀態下姿態的檢測。手勢檢測總是從初始狀態0開始,你可以用初始狀態檢測手勢是否開始。比如,如果被檢測到的關節(手、腳踝等)與其他關節足夠的靠近,這意味着手勢已經開始。第暗涌SetGestureJoint()
方法,保存下被檢測關節與狀態1在位置和時間上的增量。
這樣,在狀態1,你應該可以成功的檢測到手勢是否成功。比如,如果被檢測的關節移動到與其他關節的期望位置,且在預期的時間範圍之內,則成功檢測。不然的話,取消所有的手勢檢測並回到狀態0。取消可以通過調用SetGestureCancelled()
方法來實現。
如果這是最後的期望狀態,那麼手勢就會結束,調用CheckPoseComplete()
方法,其中最後一個參數爲0(不等待)來標記這個手勢爲完成。這樣子手勢監聽器會收到提示信息。
如果手勢已經成功了很久,但是還沒有完成,重新調用SetGestureJoint()
來保存當前關節的位置和時間戳,開始再次進行手勢的增量計算。這樣就和繼續下一個手勢狀態過程,直到手勢完成。當手勢由多於兩個狀態組成時,也可以設置gestureData-structure
中的progress屬性。
demo中與編程性手勢相關的場景在KinectDemos/GestureDemo-folder
中。第一個時冠以如何使用離散型手勢的,第二個是關於連續性手勢的使用。
demo的學習
KinectGestureDemo1
SimpleVisualGestureListener.cs
位置爲KinectScripts-Sampels
,被KinectDemos-GesturesDemo
下第一個場景使用,作爲監聽器,一同使用的還有VisualGestureManager.cs
using UnityEngine;
using System.Collections;
//實現上需要繼承VisualGestureListenerInterface接口,並且實現GestureInProgress,GestureCompleted等函數(可選的樣子)
//這個文件從效果上是實現了demo裏的GUI部分,具體還需要拿到設備之後再做實驗
public class SimpleVisualGestureListener : MonoBehaviour, VisualGestureListenerInterface
{
[Tooltip("GUI-Text to display the discrete gesture information.")]
public GUIText discreteInfo;
[Tooltip("GUI-Text to display the continuous gesture information.")]
public GUIText continuousInfo;
private bool discreteGestureDisplayed;
private bool continuousGestureDisplayed;
private float discreteGestureTime;
private float continuousGestureTime;
public void GestureInProgress(long userId, int userIndex, string gesture, float progress)
{
if(continuousInfo != null)
{
string sGestureText = string.Format ("{0} {1:F0}%", gesture, progress * 100f);
continuousInfo.GetComponent<GUIText>().text = sGestureText;
continuousGestureDisplayed = true;
continuousGestureTime = Time.realtimeSinceStartup;
}
}
public bool GestureCompleted(long userId, int userIndex, string gesture, float confidence)
{
if(discreteInfo != null)
{
string sGestureText = string.Format ("{0}-gesture detected, confidence: {1:F0}%", gesture, confidence * 100f);
discreteInfo.GetComponent<GUIText>().text = sGestureText;
discreteGestureDisplayed = true;
discreteGestureTime = Time.realtimeSinceStartup;
}
// reset the gesture
return true;
}
public void Update()
{
// clear gesture infos after a while
if(continuousGestureDisplayed && ((Time.realtimeSinceStartup - continuousGestureTime) > 1f))
{
continuousGestureDisplayed = false;
if(continuousInfo != null)
{
continuousInfo.GetComponent<GUIText>().text = string.Empty;
}
}
if(discreteGestureDisplayed && ((Time.realtimeSinceStartup - discreteGestureTime) > 1f))
{
discreteGestureDisplayed = false;
if(discreteInfo != null)
{
discreteInfo.GetComponent<GUIText>().text = string.Empty;
}
}
}
}
VisualGestureManager.cs
這個是與上面那個一起在同一個demo裏面出現的,但看了好幾遍我都沒有明白這個VS的Manager是用來幹什麼的。
CubeGestureListener.cs
這個是掛載在方塊KinectController上的,與KinectManager腳本掛在同一個對象上。
這裏面的CubeGestureListener實現了KinectGestures.GestureListenerInterface
,如果想要學習動作監聽器實現的話還是要看這代碼
核心部分就是三個布爾值swipeLeft/Right/Up
,表示是否發生了這三個動作,其他的代碼都是爲更新這三個值並根據這三個值的變化進行動作。
可以看到,程序具體實現了GestureInProgress
和GestureCompleted
等函數,這些函數在KinectGestures.cs
中被定義,且在KinectManager.cs
中作爲監聽器的方法被調用。
KinectManager.cs
的實現方法:
- 所有實現了GestureListenerInterface的MonoBehaviour對象全部被自動加入到gestureListeners列表之中。
- 在Update函數中,週期性的檢查拿到的gestureData,如果gestureData.complete,則調用監聽器的GestureCompleted方法。其他如此類推。