Kinect for Windows SDK開發初體驗(三)骨骼追蹤

來源:互聯網
上載者:User
文章目錄
  • 初始化代碼
  • 添加代碼
  • 寫到最後

作者:馬寧

我們的Kinect SDK開發開始漸入佳境了,Skeleton Tracking(骨骼追蹤)是Kinect的核心技術,正因為有了這項技術,很多有趣的功能才得以實現。

首先,我們來看一下骨骼追蹤的具體實現。Kinect最多可以追蹤20個骨骼點,而且目前只能追蹤人體,其他的物體或者動物就無能為力了。介紹了Kinect骨骼點的分布情況:

初始化代碼

接下來,我們來看一下骨骼追蹤的代碼是如何編寫的。首先,我們要建立一個新的Visual C#的工程,叫做“SkeletonTracking”,添加Kinect程式集和Coding4Fun程式集的工作,可以參考上一篇“Kinect for Windows SDK開發初體驗(二)操作Camera”的內容,在這裡不再重複。

首先我們還是建立Runtime對象,在初始化時,指定UseSkeletalTracking的RuntimeOptions,然後在SkeletonFrameReady事件中添加處理函數。

Runtime nui; private void Window_Loaded(object sender, RoutedEventArgs e){nui = new Runtime();nui.Initialize(RuntimeOptions.UseSkeletalTracking); nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);}

接下來,表單關閉時的事件處理函數:

private void Window_Closed(object sender, EventArgs e){nui.Uninitialize();}

如果這個時候,我們在空的nui_SkeletonFrameReady事件處理函數中,添加一個斷點:

void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) {}

正確串連Kinect裝置,並且站在Kinect前,讓Kinect能夠正確識別人體時,SkeletonFrameReady事件將被觸發。

我們可以通過看到返回的事件處理參數,其中比較重要的是SkeletonFrame和Skeletons兩個對象。

添加代碼

接下來,我們要準備WPF的介面,在介面上添加五個小球,來跟蹤頭部、雙手和膝蓋的位置。在MainPage.xaml中,添加下列代碼:

<Canvas Name="MainCanvas"><Ellipse Canvas.Left="0" Canvas.Top="0" Height="50" Name="headEllipse" Stroke="Black" Width="50" Fill="Orange" /><Ellipse Canvas.Left="50" Canvas.Top="0" Height="50" Name="rightEllipse" Stroke="Black" Width="50" Fill="SlateGray" /><Ellipse Canvas.Left="100" Canvas.Top="0" Fill="SpringGreen" Height="50" Name="leftEllipse" Stroke="Black" Width="50" /><Ellipse Canvas.Left="150" Canvas.Top="0" Height="50" Name="KneeRightEllipse" Stroke="Black" Width="50" Fill="Salmon" /><Ellipse Canvas.Left="200" Canvas.Top="0" Fill="Navy" Height="50" Name="KneeLeftEllipse" Stroke="Black" Width="50" /></Canvas>

然後,我們在SkeletonFrameReady事件處理函數中添加捕捉SkeletonData的方法:

void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) {SkeletonFrame allSkeletons = e.SkeletonFrame;//get the first tracked skeletonSkeletonData skeleton = (from s in allSkeletons.Skeletonswhere s.TrackingState == SkeletonTrackingState.Trackedselect s).FirstOrDefault();}

我們使用了LINQ來擷取TrackingState等於Tracked的SkeletonData資料。在SkeletonData對象的Joints屬性集合中儲存了所有骨骼點的資訊。每個骨骼點的資訊都是一個Joint對象,其中的Position的X、Y、Z表示了三維位置。其中X和Y的範圍都是-1到1,而Z是Kinect到識別物體的距離。

我們可以用下面的代碼,將Joint的位置縮放到合適的比例:

Joint j = skeleton.Joints[JointID.HandRight].ScaleTo(640, 480, .5f, .5f);

最後兩個參數為原始大小的最大值和最小值,上面的語句相當於將-0.5到0.5的範圍擴大為0到640的範圍。

我們封裝了一個函數,將擷取到的SkeletonData資料,轉換為螢幕上的某一個圓圈:

private void SetEllipsePosition(FrameworkElement ellipse, Joint joint) { var scaledJoint = joint.ScaleTo(640, 480, .5f, .5f);Canvas.SetLeft(ellipse, scaledJoint.Position.X);Canvas.SetTop(ellipse, scaledJoint.Position.Y); }

最後,我們SkeletonFrameReady事件的處理方法會是這樣的:

void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) {SkeletonFrame allSkeletons = e.SkeletonFrame;//get the first tracked skeletonSkeletonData skeleton = (from s in allSkeletons.Skeletonswhere s.TrackingState == SkeletonTrackingState.Trackedselect s).FirstOrDefault();SetEllipsePosition(headEllipse, skeleton.Joints[JointID.Head]); SetEllipsePosition(leftEllipse, skeleton.Joints[JointID.HandLeft]); SetEllipsePosition(rightEllipse, skeleton.Joints[JointID.HandRight]);SetEllipsePosition(KneeLeftEllipse, skeleton.Joints[JointID.KneeLeft]);SetEllipsePosition(KneeRightEllipse, skeleton.Joints[JointID.KneeRight]);}

最後,程式啟動並執行效果如下,貌似膝蓋的識別還是有些問題:

程式運行時,我們會發現小球運動時會有跳動的問題,為了減少這種情況,我們要設定SkeletonEngine引擎的TransformSmooth屬性為true,並指定TransformSmoothParameters參數,根據應用的具體情況,該參數也應該被適當微調。

添加代碼後的Load函數,代碼如下:

private void Window_Loaded(object sender, RoutedEventArgs e){nui = new Runtime();nui.Initialize(RuntimeOptions.UseSkeletalTracking); //Must set to true and set after call to Initializenui.SkeletonEngine.TransformSmooth = true;//Use to transform and reduce jittervar parameters = new TransformSmoothParameters{Smoothing = 0.75f,Correction = 0.0f,Prediction = 0.0f,JitterRadius = 0.05f,MaxDeviationRadius = 0.04f};nui.SkeletonEngine.SmoothParameters = parameters;nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);}

寫到最後

到這裡, Kinect最精華的部分“骨骼追蹤”已經介紹給大家了,大家可以去寫一些有趣的應用了。接下來,我們會介紹另外一個Kinect的核心功能——Depth Data,景深資料。

 

OpenXLive杯Windows Phone遊戲開發大賽

OpenXLive杯Windows Phone遊戲開發大賽,是由OpenXLive聯合國內知名的開發人員社區:DevDiv、智機網、WPMind、Silverlight銀光中國和XNA遊戲世界,一起舉辦的針對Windows Phone遊戲開發的比賽。

http://www.openxlive.net/posts/news/40

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.