kinect基本手勢(shì)識(shí)別_第1頁(yè)
kinect基本手勢(shì)識(shí)別_第2頁(yè)
kinect基本手勢(shì)識(shí)別_第3頁(yè)
kinect基本手勢(shì)識(shí)別_第4頁(yè)
kinect基本手勢(shì)識(shí)別_第5頁(yè)
已閱讀5頁(yè),還剩33頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、譯Kinect for Windows SDK開發(fā)入門(十一):手勢(shì)識(shí)別下:基本手勢(shì)識(shí)別上文簡(jiǎn)要介紹了手勢(shì)識(shí)別的基本概念和手勢(shì)識(shí)別的基本方法,并以八種手勢(shì)中的揮手(wave)為例講解了如何使用算法對(duì)手勢(shì)進(jìn)行識(shí)別,本文接上文,繼續(xù)介紹如何建立一個(gè)手部追蹤類庫(kù),并以此為基礎(chǔ),對(duì)剩余 7中常用的手勢(shì)進(jìn)行識(shí)別做一些介紹。1. 基本的手勢(shì)追蹤手部追蹤在技術(shù)上和手勢(shì)識(shí)別不同,但是它和手勢(shì)識(shí)別中用到的一些基本方法是一 樣的。在開發(fā)一個(gè)具體的手勢(shì)控件之前,我們先建立一個(gè)可重用的追蹤手部運(yùn)動(dòng)的類庫(kù)以方便我們后續(xù)開發(fā)。這個(gè)手部追蹤類庫(kù)包含一個(gè)以動(dòng)態(tài)光標(biāo)顯示的可視化反饋機(jī)制。手部追蹤和手勢(shì)控件之間的交互高度松耦合。

2、首先在 Visual Studio中創(chuàng)建一個(gè)WPF控件類庫(kù)項(xiàng)目。然后添加四個(gè)類:Kin ectCursorEve ntArgs.cs,Kinectln put.cs, CusrorAdorner.cs禾口Kin ectCursorMa nager.cs這四個(gè)類之間通過(guò)相互調(diào)用來(lái)基于用戶手所在的位置來(lái)完成光標(biāo)位置的管理。Kin ectI nput類包含了一些事件,這些事件可以在Kin ectCursorMa nager 和一些控件之間共享。Kin ectCursorEve ntArgs提供了一個(gè)屬性集合,能夠用來(lái)在事件觸發(fā)者和監(jiān)聽者之間傳遞數(shù)據(jù)。KinectCursorManager用來(lái)管理從K

3、inect傳感器中獲取的骨骼數(shù)據(jù) 流,然后將其轉(zhuǎn)換到 WPF坐標(biāo)系統(tǒng),提供關(guān)于轉(zhuǎn)換到屏幕位置的可視化反饋,并尋找屏幕上的控件,將事件傳遞到這些控件上。最后CursorAdorner.cs類包含了代表手的圖標(biāo)的可視化元素。KinectCursorEventArgs 繼承自 RoutedEventArgs 類,它包含四個(gè)屬性: X、Y、Z 和Cursor X、Y、Z是一個(gè)小數(shù),代表待轉(zhuǎn)換的用戶手所在位置的寬度,高度和深度值。Cursor用來(lái)存儲(chǔ) CursorAdorner 類的實(shí)例,后面將會(huì)討論,下面的代碼展示了 Kin ectCursorEve ntArgs 類的基本結(jié)構(gòu),其中包含了一些重載的構(gòu)

4、造器。:RoutedEventArgspublic classKi nectCursorEve ntArgspublic doublepublic doublepublic doubleX get; set ; 丫 get; set ; Z get; set ; get; set ; public CursorAdor ner Cursor publicKinectCursorEventArgs(double x, double y)X = x;丫 = y;public Kin ectCursorEve ntArgs( Point point)X = poi nt.X;丫 = poi nt.Y

5、;RoutedEventArgs 基類有一個(gè)構(gòu)造函數(shù)能夠接收RoutedEvent作為參數(shù)。這是一個(gè)有點(diǎn)特別的簽名,WPF中的UIEleme nt使用這種特殊的語(yǔ)法觸發(fā)事件。下面的代碼是Kin ectCursorEve ntArgs類對(duì)這一簽名的實(shí)現(xiàn),以及其他一些重載方法。publicKi nectCursorEve ntArgs(RoutedEvent routedEvent)base (routedEve nt) publicKi nectCursorEve ntArgs(RoutedEvent routedEvent,double x, double y, double z)base (

6、routedEve nt) X =x; Y = y; Z =乙publicKi nectCursorEve ntArgs(RoutedEvent routedEvent,Point point)base (routedEve nt) X =poi nt.X; Y = poi nt.Y; publicKi nectCursorEve ntArgs(RoutedEvent routedEvent,Point point, double z)base (routedEve nt) X =point.X; Y = point.Y; Z = z; publicKi nectCursorEve ntArg

7、s(RoutedEvent routedEvent,object source)base(routedEve nt, source) publicKi nectCursorEve ntArgs(RoutedEvent routedEvent,object source,double x, double y,double z)base(routedEve nt, source) X = x; Y = y; Z = z; publicKi nectCursorEve ntArgs(RoutedEvent routedEvent,object source,Point point)base(rout

8、edEve nt,source) X =poi nt.X;Y =poi nt.Y;publicKi nectCursorEve ntArgs(RoutedEvent routedEvent,object source,Point point, double z)base(routedEve nt, source) X = poin t.X; Y = poin t.Y; Z = z; 接下來(lái),要在Kin ect In put類中創(chuàng)建事件來(lái)將消息從Kin ectCursorMa nager 中傳遞到可視化控件中去。這些事件傳遞的數(shù)據(jù)類型為Kin ectCursorEve ntArgs類型。在 Ki

9、n ect In put類中添加一個(gè) Kin ectCursorEve ntHa ndler的代理類型:(1)添加一個(gè)靜態(tài)的 routed event 聲明。(2) 添力口 KinectCursorEnter, KinectCursorLeave,KinectCursorMove , KinectCursorActive 禾口 KinectCursorDeactivated 事件的 add 禾口 remove方法。下面的代碼展示了三個(gè)和cursor相關(guān)的事件,其他的如KinectCursorActivated和Kin ectCursorDeactivated事件和這個(gè)結(jié)構(gòu)相同:public d

10、elegate void KinectCursorEventHandler( object sender, KinectCursorEventArgse);public static classKin ect In putpublicstaticread onlyRoutedEve ntKinectCursorEnterEvent=EventManager .RegisterRoutedEvent(KinectCursorEnter , RoutingStrategy .Bubble,typeof (KinectCursorEventHandler), typeof (KinectInput

11、);public staticvoidAddK in ectCursorE nterHa ndler(Depe nden cyObjecto,Ki nectCursorEve ntHa ndlerhan dler)( UIElement )o).AddHandler(KinectCursorEnterEvent, handler);public static void RemoveKi nectCursorE nterHa ndler( Depe nden cyObject o,Ki nectCursorEve ntHa ndlerhan dler)( UIElement )o).Remove

12、Handler(KinectCursorEnterEvent, handler);publicstaticread onlyRoutedEve ntKinectCursorLeaveEvent=EventManager .RegisterRoutedEvent(KinectCursorLeave , RoutingStrategy .Bubble,typeof (KinectCursorEventHandler), typeof (KinectInput );public static voidAddK in ectCursorLeaveHa ndler(Depe nden cyObjecto

13、,Ki nectCursorEve ntHa ndlerhan dler)( UIElement )o).AddHandler(KinectCursorEnterEvent,handler);public static voidRemoveKi nectCursorLeaveHa ndler(Depe nden cyObject o,Ki nectCursorEve ntHa ndlerhan dler)( UIElement )o).RemoveHandler(KinectCursorEnterEvent, handler);注意到以上代碼中沒有聲明任何GUI編程中的Click事件。這是因?yàn)?/p>

14、在設(shè)計(jì)控件類庫(kù)時(shí),Kinect中并沒有點(diǎn)擊事件,相反Kinect中兩個(gè)重要的行為是enter和leave。手勢(shì)圖標(biāo)可能會(huì)移入和移出某一個(gè)可視化控件的有效區(qū)域。如果要實(shí)現(xiàn)普通GUI控件的點(diǎn)擊效果的話,必須在Kinect中對(duì)這一事件進(jìn)行模擬,因?yàn)镵inect原生并不支持點(diǎn)擊這一行為。CursorAdorner類用來(lái)保存用戶手勢(shì)圖標(biāo)可視化元素,它繼承自WPF的Adorner類型。之所以使用這個(gè)類型是因?yàn)樗幸粋€(gè)特點(diǎn)就是總是在其他元素之上繪制,這在我們的項(xiàng)目中非常有用,因?yàn)槲覀儾幌M覀兊墓鈽?biāo)會(huì)被其他元素遮擋住。代碼如下所示,我們默認(rèn)的adorner對(duì)象將繪制一個(gè)默認(rèn)的可視化元素來(lái)代表光標(biāo),當(dāng)然也可以

15、傳遞一個(gè)自定義的可視化元素。public class CursorAdor ner : Adorner private read only UlEleme nt _ador nin gEleme nt;privateVisualCollectio n_visualChildre n;privateCan vas _cursorCa nvas;protected FrameworkElement _cursor;StroyBoard _gradie ntStopA ni mati on Storyboard;read only staticColor _backColor = Colors .W

16、hite;read only staticColor _foreColor = Colors .Gray;public CursorAdor ner( FrameworkEleme nt ador nin gEleme nt) base(ador nin gEleme nt)this ._adorningElement = adorningElement;CreateCursorAdor ner();thissHitTestVisible = false ;publicCursorAdor ner( FrameworkEleme ntador nin gEleme nt,FrameworkEl

17、eme ntinn erCursor)base(ador nin gEleme nt)this ._adorningElement = adorningElement;CreateCursorAdorner(i nn erCursor);thissHitTestVisible = false ;public FrameworkEleme nt CursorVisualget return _cursor; public voidCreateCursorAdor ner()var innerCursor = CreateCursor();CreateCursorAdorner(i nn erCu

18、rsor);protectedFrameworkEleme nt CreateCursor()var brush = new LinearGradientBrush();brush.EndPoint =new Point (0,1);brush.StartPoint =new Point (0, 0);brush.Gradie ntStops.Add(new Gradie ntStop (_backColor, 1);brush.Gradie ntStops.Add(new Gradie ntStop (_foreColor, 1);var cursor = new Ellipse ()Wid

19、th=50,Height=50,Fill=brush;retur n cursor;public voidCreateCursorAdor ner(FrameworkEleme nt inn erCursor)visualChildre n =new VisualCollection(this );cursorCa nvas =newCan vas();_cursor = inn erCursor;_cursorCa nvas.Childre n.Add( _visualChildre n.Add(Adorn erLayer layer = layer.Add(this );this ._cu

20、rsorCanvas);this ._cursorCanvas);AdornerLayer .GetAdornerLayer(_adorningElement);因?yàn)槔^承自Adorner基類,我們需要重寫某些基類的方法,下面的代碼展示了基類中的方法如何和 CreateCursorAdorner 方法中實(shí)例化的 _visualChildren和cursorCanvas字段進(jìn)行綁定。protected override intVisualChildre nCou ntgetretur n_visualChildre n. Cou nt;protected override Visual GetVi

21、sualChild( int in dex)retur n_visualChildre ni ndex;protected override Size MeasureOverride( Size constraint) this ._cursorCanvas.Measure(constraint);return this ._cursorCa nvas.DesiredSize;protected overrideSize ArrangeOverride(Size finalSize)this ._cursorCanvas.Arrange(new Rect (finalSize);returnf

22、in alSize;CursorAdorner 對(duì)象也負(fù)責(zé)找到手所在的正確的位置,該對(duì)象的UpdateCursor方法如下,方法接受X,Y坐標(biāo)位置作為參數(shù)。 然后方法在X,Y上加一個(gè)偏移量以使得圖像的中 心在X, Y之上,而不是在圖像的邊上。另外,我們提供了該方法的一個(gè)重載,該重載告訴 光標(biāo)對(duì)象一個(gè)特殊的坐標(biāo)會(huì)傳進(jìn)去,所有的普通方法調(diào)用UpdateCursor將會(huì)被忽略。當(dāng)我們?cè)诖判园粹o中想忽略基本的手部追蹤給用戶更好的手勢(shì)體驗(yàn)時(shí)很有用。public void UpdateCursor( Point position,bool isOverride)_isOverride n = isOver

23、ride;_cursor.SetValue(Can vas.LeftProperty,positi on. X-(_cursor.ActualWidth/2);_cursor.SetValue( Canvas.LeftProperty,position.Y- (_cursor.ActualHeight / 2); public void UpdateCursor( Point position) return ;Can vas.LeftProperty,Can vas.LeftProperty,position.X- (_cursor.ActualWidth / 2);position.Y -

24、 (_cursor.ActualHeight / 2);if (_isOverriden)_cursor.SetValue(_cursor.SetValue(最后,添加光標(biāo)對(duì)象動(dòng)畫效果。 當(dāng)Kinect控件需要懸浮于一個(gè)元素之上, 在用戶等 待的時(shí)候,給用戶反饋一些信息告知正在發(fā)生的事情,這一點(diǎn)很有好處。下面了的代碼展示了如何使用代碼實(shí)現(xiàn)動(dòng)畫效果 :public virtual voidAnimateCursor( double milliSeconds) CreateGradie ntStopA nimatio n(milliSec on ds);if (_gradientStopAnima

25、tionStoryboard !=null )this , true );_gradie ntStopA nimatio nStoryboard.Begi n(public virtual voidStopCursorA nimatio n(double milliSec on ds)if (_gradientStopAnimationStoryboard !=null )_gradientStopAnimationStoryboard.Stop(this );public virtual voidCreateGradie ntStopA ni mati on(double milliSec

26、on ds) NameScopeSetNameScope( this , newNameScopeQ);var cursor = _cursor asShape;if (cursor =null )return ;var brush = cursor.FillasLinearGradientBrushvar stop1 = brush.GradientStopsO;var stop2 = brush.GradientStops1;this .RegisterName( GradientStop1 , stop1); this .RegisterName( GradientStop2 , sto

27、p2);DoubleA ni mati on offsetA ni mati on =n ewDoubleA ni matio n ();offsetA ni mati on. From = 1.0; offsetA ni mati on.To = 0.0;offsetA ni mati on .Durati on =TimeSpa n. FromMillisecon ds(milliSec on ds);Storyboard .SetTargetName(offsetAnimation,GradientStop1);Storyboard .SetTargetProperty(offsetAn

28、imation,n ewPropertyPath (Gradie ntStop .OffsetProperty);DoubleA ni matio n offsetA ni mati on2 =n ewDoubleA ni matio n ();offsetA ni mati on 2.From = 1.0;offsetA nimatio n2.To = 0.0;offsetA nimatio n2.Durati on =TimeSpa n.FromMillisec on ds(milliSec on ds);Storyboard .SetTargetName(offsetAnimation2

29、,GradientStop2);Storyboard .SetTargetProperty(offsetAnimation2,n ewPropertyPath (Gradie ntStop .OffsetProperty);_gradientStopAnimationStoryboard =newStoryboard ();_gradie ntStopA ni matio nStoryboard.Childre n.Add(offsetA nimatio n);_gradie ntStopA nimatio nStoryboard.Childre n.Add(offsetA nimatio n

30、2);_gradie ntStopA ni matio nStoryboard.Completed+=delegate _gradientStopAnimationStoryboard.Stop(this ); ;為了實(shí)現(xiàn)KinectCursorManager類,我們需要幾個(gè)幫助方法,代碼如下,GetElementAtScreenPoint方法告訴我們哪個(gè) WPF對(duì)象位于X,Y坐標(biāo)下面,在這個(gè)高度松散的結(jié)構(gòu)中,GetEleme ntAtScree nPoi nt方法是主要的引擎,用來(lái)從Kin ectCurosrMa nager 傳遞消息到自定義控件,并接受這些事件。另外,我們使用兩個(gè)方法來(lái)確定

31、我們想要追蹤的骨 骼數(shù)據(jù)以及我們想要追蹤的手。private staticUIEleme nt GetEleme ntAtScree nPoint(Poi nt point, Win dow wi ndow)if (!wi ndow .1 sVisible)return n ull;Poi nt win dowPo int = wi ndow.Poi ntFromScree n(poi nt);lln putEleme nteleme nt = wi ndow .In putHitTest(wi ndowPoi nt);if (elementis UIElement )return ( UIE

32、lement )element;elsereturn n ull;private staticSkeletonGetPrimarySkeleton( IEnumerable skeletons)Skeleton primarySkeleton = null ;foreach(Skelet onskelet onin skelet ons)if (skelet on. Track in gState !=Skelet on Track in gState.Tracked)continue ;if (primarySkeleton = null )primarySkelet on = skelet

33、 on;else if(primarySkeleto n.Positio n.Z skelet on .Positi on.Z)primarySkelet on = skelet on;returnprimarySkelet on;private static Joint ? GetPrimaryHand( Skeletonskeleton) JointType .HandLeft;JointType .HandRight;Joi ntTrack in gState.Tracked)Joint leftHa nd=skelet on.Join tsJoint rightHa nd=skelet

34、 on.Joints if (rightHa nd.Tracki ngState =if (leftHa nd.Tracki ngState !=Joi ntTracki ngState .Tracked)retur nrightHa nd;else if(leftHa nd.Positi on.Z rightHa nd.Positi on.Z)retur nrightHa nd;elsereturnleftHa nd;if (leftHa nd.Tracki ngState =Joi ntTracki ngState.Tracked)return leftHa nd;elsereturn n

35、 ull;Kin ectCursorMa nager應(yīng)該是一個(gè)單例類。這樣設(shè)計(jì)是能夠使得代碼實(shí)例化起來(lái)簡(jiǎn)單。任何和KinectCursorManager 工作的控件在KinectCursorManager 沒有實(shí)例化的情況下 可以獨(dú)立的進(jìn)行 KinectCursorManager的實(shí)例化。這意味著任何開發(fā)者使用這些控件不需要 了解KinectCursorManager對(duì)象本身。相反,開發(fā)者能夠簡(jiǎn)單的將控件拖動(dòng)到應(yīng)用程序中, 控件負(fù)責(zé)實(shí)例化 KinectCursorManager對(duì)象。為了使得這種自服務(wù)功能能和KinectCursorMange類一起使用,我們需要?jiǎng)?chuàng)建一個(gè)重載的Create方法來(lái)

36、將應(yīng)用程序的主窗體類傳進(jìn)來(lái)。下面的代碼展示了重載的構(gòu)造函數(shù)以及特殊的單例模式的實(shí)現(xiàn)方法。public classKi nectCursorMa nagerprivateKi nectSe nsorkin ectSe nsor;privateCursorAdor nercursorAdor ner;private read only Window win dow;private UIEleme nt lastEleme ntOver;private boolisSkelet on Track in gActivated;private static boolisln itialized;priv

37、ate staticKin ectCursorMa nagerin sta nee;Create( Window window)new Ki nectCursorMa nager (win dow); true ;public static voidif (!is In itialized)in sta nee =isl nitialized =public static voidCreate( Window window, FrameworkElement cursor)if (!is In itialized)in sta nee =new Ki nectCursorMa nager (w

38、i ndow,cursor);islnitialized =true ;public static voidif (!is In itialized)in sta nee =isI nitialized =Create( Window window, KinectSensorsensor)new Ki nectCursorMa nager (win dow, sen sor); true ;public static void cursor)if (!is In itialized)in sta nee =isl nitialized =Create( Window window, Kinec

39、tSensornew Ki nectCursorMa nager true ;sen sor,FrameworkEleme nt(win dow, sen sor, cursor);public staticKi nectCursorMa nagerIn sta neeget returninstanee; privateKin ectCursorMa nager(Win dowwi ndow)this(wi ndow,Ki nectSe nsor.KinectSensors0) privateKi nectCursorMa nager(Win dow win dow,FrameworkEle

40、ment cursor):this(wi ndow,Ki nectSe nsor.Kin ectSe nsors0, cursor) privateKi nectCursorMa nager(Win dow wi ndow,Kin ectSe nsorsen sor):this(wi ndow,sen sor,n ull) privateKi nectCursorMa nager(Win dow win dow,Ki nectSe nsorsen sor, FrameworkEleme ntcursor)this .window = window;if (KinectSensor .Kinec

41、tSensors.Count 0)wi ndow.U nloaded +=if (this this ;delegate.ki nectSe nsor.Skeleto nStrea m.lsEn abled).kin ectSe nsor.Skelet on Stream.Disable();win dow.Loaded +=delegateif (cursor = null )cursorAdor ner=newCursorAdorner ( FrameworkElement )window.Content);elsecursorAdor ner=newCursorAdorner ( Fra

42、meworkElement )window.Content, cursor);this .kinectSensor = sensor;this .kinectSensor.SkeletonFrameReady += SkeletonFrameReady;this .kinectSensor.SkeletonStream.Enable(newTran sformSmoothParameters ();this .kinectSensor.Start();下面的代碼展示了Kin ectCursorMa nager 如何和窗體上的可視化元素進(jìn)行交互。當(dāng)用戶的手位于應(yīng)用程序可視化元素之上時(shí),Kin e

43、ctCursorMa nager對(duì)象始終保持對(duì)當(dāng)前手所在的可視化元素以及之前手所在的可視化元素的追蹤。當(dāng)這一點(diǎn)發(fā)生改變時(shí), KinectCursorManager會(huì)觸發(fā)之前控件的leave事件和當(dāng)前控件的enter事件。我們也保持對(duì)KinectSensor 對(duì)象的追蹤,并觸發(fā) activated 和deactivated 事件。private voidSetSkeleto nTracki ngActivated()if (lastElementOver !=null & isSkeletonTrackingActivated =false )lastEleme ntOver.RaiseEve

44、nt(newRoutedEve ntArgs ( Kin ect In put .Ki nectCursorActivatedEve nt);isSkelet on Track in gActivated =true ;private voidSetSkeleto nTracki ngDeactivated()if (lastElementOver !=null & isSkeletonTrackingActivated =false )lastEleme ntOver.RaiseEve nt(newRoutedEve ntArgs ( Kin ect In put .Kin ectCurso

45、rDeactivatedEve nt);isSkelet on Tracki ngActivated =false ; private void Han dleCursorEve nts( Point point, double z) UIElement element = GetElementAtScreenPoint(point, window); if (element != null )eleme nt.RaiseEve nt(newpoi nt,z)point, z) Cursor =point, z) Cursor =Kin ectCursorEve ntArgs(Kin ect

46、In put .Kin ectCursorMoveEve nt,Cursor=cursorAdor ner );if (eleme nt != lastEleme ntOver)if (lastElementOver != null )lastEleme ntOver.RaiseEve nt(newKin ectCursorEve ntArgs(Kin ect In put .Kin ectCursorLeaveEve nt,cursorAdor ner );eleme nt.RaiseEve nt(newKin ectCursorEve ntArgs(Kin ect In put .Ki n

47、ectCursorE nterEve nt,cursorAdor ner );lastEleme ntOver = eleme nt;最后需要兩個(gè)核心的方法來(lái)管理KinectCursorManger 類。SkeletonFrameReady 方法與之前一樣,用來(lái)從Kinect獲取骨骼數(shù)據(jù)幀時(shí)觸發(fā)的事件。在這個(gè)項(xiàng)目中, SkeletonFrameReady方法負(fù)責(zé)獲取合適的骨骼數(shù)據(jù),然后獲取合適的手部關(guān)節(jié)點(diǎn)數(shù)據(jù)。然 后將手部關(guān)節(jié)點(diǎn)數(shù)據(jù)傳到UpdateCusror方法中,UpdateCursor方法執(zhí)行一系列方法將Kinect骨骼空間坐標(biāo)系轉(zhuǎn)化到WPF的坐標(biāo)系統(tǒng)中,Kinect SDK中MapSk

48、eletonPointToDepth方法提供了這一功能。SkeletonToDepthlmage方法返回的X,Y值,然后轉(zhuǎn)換到應(yīng)用程序中 實(shí)際的寬和高。和 X,Y不一樣,Z值進(jìn)行了不同的縮放操作。簡(jiǎn)單的從Kinect深度攝像機(jī)中獲取的毫米數(shù)據(jù)。代碼如下,一旦這些坐標(biāo)系定義好了之后,將他們傳遞到 HandleCursorEvents 方法然后 CursorAdorner對(duì)象將會(huì)給用戶以反饋。相關(guān)代碼如下:private voidSkeletonFrameReady( object sender, SkeletonFrameReadyEventArgs e)using (SkeletonFrame

49、 frame = e.OpenSkeletonFrame()if (frame = null | frame.SkeletonArrayLength = 0)return ;Skeleton skeletons =newSkeleton frame.SkeletonArrayLength;frame.CopySkelet on DataTo(skelet on s);Skeleton skeleton = GetPrimarySkeleton(skeletons);if (skeleton = null )SetHa ndTrack in gDeactivated();elseJoint ?

50、primaryHand = GetPrimaryHand(skeleton);if (primaryHand.HasValue)UpdateCursor(primaryHa nd.Value);elseSetHa ndTrack in gDeactivated();private voidSetHa ndTrack in gDeactivated()cursorAdorner.SetVisibility(false );if (lastElementOver !=null & isHandTrackingActivated = true )lastEleme ntOver.RaiseEve n

51、t(n ewRoutedEve ntArgs (Kin ect In put.Ki nectCursorDeactivatedEve nt); ;isHandTrackingActivated =false ;private void UpdateCursor( Joint hand)var point=kinectSensor.MapSkeletonPointToDepth(hand.Position,ki nectSe nsor.DepthStream.Format);float x = point.X;float y = point.Y;float z = point.Depth;x =

52、 ( float )(x * window.ActualWidth / kinectSensor.DepthStream.FrameWidth);y = ( float )(y * window.ActualHeight / kinectSensor.DepthStream.FrameHeight);Point cursorPoint =newPoint (x, y);Han dleCursorEve nts(cursorPo int, z); cursorAdor ner.UpdateCursor(cursorPoi nt);至此,我們已經(jīng)簡(jiǎn)單實(shí)現(xiàn)了一些基礎(chǔ)結(jié)構(gòu),這些僅僅是實(shí)現(xiàn)了將用戶手部的

53、運(yùn)動(dòng)顯示在屏幕上?,F(xiàn)在我們要?jiǎng)?chuàng)建一個(gè)基類來(lái)監(jiān)聽光標(biāo)對(duì)象的事件,首先創(chuàng)建一個(gè)Kin ectButt on 對(duì)象,該對(duì)象繼承自WPFButton類型。定義三個(gè)之前在Kin ectI nput中定義好的事件,同時(shí)創(chuàng)建這些事件的添加刪除方法,代碼如下:public classKin ectButt on: Butt onpublicstaticread only RoutedEve nt Ki nectCursorE nterEve ntKin ect In put .Kin ectCursorE nterEve nt.AddOw ner(typeof (Kin ectButt on );publicstaticread only RoutedEve nt Kin ectCursorLeaveEve ntKin ect In put .Ki nectCursorLeaveEve nt.AddOw ner(typeof (Ki nectButt on );publicstaticread only RoutedEve nt Kin ectCursorMoveEve ntKin ectI nput .Kin ectCursorMoveEve nt.AddOw ner(typeof ( Kin ec

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論