上文簡要介紹了手勢識別的基本概念和手勢識別的基本方法,並以八種手勢中的揮手(wave)為例講解了如何使用演算法對手勢進行識別,本文接上文,繼續介紹如何建立一個手部追蹤類庫,並以此為基礎,對剩餘7中常用的手勢進行識別做一些介紹。
1. 基本的手勢追蹤
手部追蹤在技術上和手勢識別不同,但是它和手勢識別中用到的一些基本方法是一樣的。在開發一個具體的手勢控制項之前,我們先建立一個可重用的追蹤手部運動的類庫以方便我們後續開發。這個手部追蹤類庫包含一個以動態游標顯示的可視化反饋機制。手部追蹤和手勢控制項之間的互動高度松耦合。
首先在Visual Studio中建立一個WPF控制項類庫項目。然後添加四個類: KinectCursorEventArgs.cs,KinectInput.cs,CusrorAdorner.cs和KinectCursorManager.cs這四個類之間通過相互調用來基於使用者手所在的位置來完成游標位置的管理。KinectInput類包含了一些事件,這些事件可以在KinectCursorManager和一些控制項之間共用。KinectCursorEventArgs提供了一個屬性集合,能夠用來在事件觸發者和監聽者之間傳遞資料。KinectCursorManager用來管理從Kinect感應器中擷取的骨骼資料流,然後將其轉換到WPF座標系統,提供關於轉換到螢幕位置的可視化反饋,並尋找螢幕上的控制項,將事件傳遞到這些控制項上。最後CursorAdorner.cs類包含了代表手的表徵圖的可視化元素。
KinectCursorEventArgs繼承自RoutedEventArgs類,它包含四個屬性:X、Y、Z和Cursor。X、Y、Z是一個小數,代表待轉換的使用者手所在位置的寬度,高度和深度值。Cursor用來儲存CursorAdorner類的執行個體,後面將會討論,下面的代碼展示了KinectCursorEventArgs類的基本結構,其中包含了一些重載的構造器。
public class KinectCursorEventArgs:RoutedEventArgs{ public double X { get; set; } public double Y { get; set; } public double Z { get; set; } public CursorAdorner Cursor { get; set; } public KinectCursorEventArgs(double x, double y) { X = x; Y = y; } public KinectCursorEventArgs(Point point) { X = point.X; Y = point.Y; }}
RoutedEventArgs基類有一個建構函式能夠接收RoutedEvent作為參數。這是一個有點特別的簽名,WPF中的UIElement使用這種特殊的文法觸發事件。下面的代碼是KinectCursorEventArgs類對這一簽名的實現,以及其他一些重載方法。
public KinectCursorEventArgs(RoutedEventroutedEvent) : base(routedEvent) { } publicKinectCursorEventArgs(RoutedEventroutedEvent, doublex, doubley, doublez) : base(routedEvent) { X = x; Y = y; Z = z; } publicKinectCursorEventArgs(RoutedEventroutedEvent, Pointpoint) : base(routedEvent) { X = point.X; Y = point.Y; } publicKinectCursorEventArgs(RoutedEventroutedEvent, Pointpoint,doublez) : base(routedEvent) { X = point.X; Y = point.Y; Z = z; } publicKinectCursorEventArgs(RoutedEventroutedEvent, objectsource) : base(routedEvent, source) {} publicKinectCursorEventArgs(RoutedEventroutedEvent,objectsource,doublex,doubley,doublez) : base(routedEvent, source) { X = x; Y = y; Z = z; } publicKinectCursorEventArgs(RoutedEventroutedEvent, objectsource, Pointpoint) : base(routedEvent, source) { X = point.X; Y = point.Y; } publicKinectCursorEventArgs(RoutedEventroutedEvent, objectsource, Pointpoint,doublez) : base(routedEvent, source) { X = point.X; Y = point.Y; Z = z; }