Kinect for Windows SDK開發入門(七)骨骼追蹤基礎 下

來源:互聯網
上載者:User

上一篇文章用在UI介面上繪製骨骼資料的例子展示了骨骼追蹤系統涉及的主要對象,然後詳細討論了骨骼追蹤中所涉及的物件模型。但是瞭解了基本概念是一回事,能夠建立一個完整的可用的應用程式又是另外一回事,本文通過介紹一個簡單的Kinect遊戲來詳細討論如何應用這些對象來建立一個完整的Kinect應用,以加深對Kinect骨骼追蹤所涉及的各個對象的瞭解。

1. Kinect連線遊戲

相信大家在小時候都做過一個數學題目,就是在紙上將一些列數字(用一個圓點表示)從小到大用線連起來。遊戲邏輯很簡單,只不過我們在這裡要實現的是動動手將這些點連起來,而不是用筆或者滑鼠。

這個小遊戲顯然沒有第一人稱射擊遊戲那樣複雜,但如果能夠做成那樣更好。我們要使用骨骼追蹤引擎來收集遊戲者的關節資料,執行操作並渲染UI介面。這個小遊戲展示了自然使用者介面(Natural User Interface,NUI)的理念,這正是基於Kinect開發的常見互動介面,就是手部跟蹤。這個連線小遊戲沒有僅僅用到了WPF的繪圖功能,沒有好看的圖片和動畫效果,這些以後可以逐步添加。

在開始寫代碼之前,需要明確定義我們的遊戲目標。連線遊戲是一個智力遊戲,遊戲者需要將數字從小到大連起來。程式可以自訂遊戲上面的數字和位置(合稱一個關卡)。每一個關卡包括一些列的數字(以點表示)及其位置。我們要建立一個DotPuzzle類來管理這些點對象的集合。可能一開始不需要這個類,僅僅需要一個集合就可以,但是為了以後方便添加其他功能,使用類更好一點。這些點在程式中有兩個地方需要用到,一個是最開始的時候在介面上繪製關卡,其次是判斷使用者是否碰到了這些點。

當使用者碰到點時,程式開始繪製,直線以碰到的點為起始點,直線的終點位使用者碰到的下一個點。然後下一個點又作為另一條直線的起點,依次類推。直到最後一個點和第一個點連起來,這樣關卡算是通過了,遊戲結束。

遊戲規則定義好了之後,我們就可以開始編碼了,隨著這個小遊戲的開發進度,可能會添加一些其他的新功能。一開始,建一個WPF工程,然後引用Microsoft.Kinect.dll,和之前的項目一樣,添加發現和初始化Kinect感應器的代碼。然後註冊KinectSensor對象的SkeletonFrameReady事件。

1.1 遊戲的使用者介面

遊戲介面代碼如下,有幾個地方需要說明一下。Polyline對象用來表示點與點之間的連線。當使用者在點和點之間移動手時,程式將點添加到Polyline對象中。PuzzleBoardElement Canvas對象用來作為UI介面上所有點的容器。Grid對象下面的Canvas的順序是有意這樣排列的,我們使用另外一個GameBoardElement Canvas對象來儲存手勢,以Image來表示,並且能夠保證這一層總是在點圖層之上。 將每一類對象放在各自層中的另外一個好處是重新開始一個新的遊戲變得很容易,只需要將PuzzleBoardElement節點下的所有子節點清除,CrayonElement元素和其他的UI對象不會受到影響。

Viewbox和Grid對象對於UI介面很重要。如上一篇文章中討論的,骨骼節點資料是基於骨骼空間的。這意味著我們要將骨骼向量轉化到UI座標系中來才能進行繪製。我們將UI控制項寫入程式碼,不允許它隨著UI表單的變化而浮動。Grid節點將UI空間大小定義為1920*1200。通常這個是顯示器的全屏尺寸,而且他和深度影像資料的長寬比是一致的。這能夠使得座標轉換更加清楚而且能夠有更加流暢的手勢移動體驗。

<Window x:Class="KinectDrawDotsGame.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        Title="MainWindow" Height="600" Width="800" Background="White">    <Viewbox>        <Grid x:Name="LayoutRoot" Width="1920" Height="1200">            <Polyline x:Name="CrayonElement" Stroke="Black" StrokeThickness="3" />            <Canvas x:Name="PuzzleBoardElement" />            <Canvas x:Name="GameBoardElement">                <Image x:Name="HandCursorElement" Source="Images/hand.png" Width="75"                       Height="75" RenderTransformOrigin="0.5,0.5">                    <Image.RenderTransform>                        <TransformGroup>                            <ScaleTransform x:Name="HandCursorScale" ScaleX="1" />                        </TransformGroup>                    </Image.RenderTransform>                </Image>            </Canvas>        </Grid>    </Viewbox></Window>

寫入程式碼UI介面也能夠簡化開發過程,能夠使得從骨骼座標向UI座標的轉化更加簡單和快速,只需要幾行代碼就能完成操作。況且,如果不應編碼,相應主UI表單大小的改變將會增加額外的工作量。通過將Grid嵌入Viewbox節點來讓WPF來幫我們做縮放操作。最後一個UI元素是Image對象,他表示手的位置。在這個小遊戲中,我們使用這麼一個簡單的表徵圖代表手。你可以選擇其他的圖片或者直接用一個Ellipse對象來代替。本遊戲中圖片使用的是右手。在遊戲中,使用者可以選擇使用左手或者右手,如果使用者使用左手,我們將該圖片使用ScaleTransform變換,使得變得看起來像右手。

1.2 手部追蹤

遊戲者使用手進行互動,因此準確判斷是那隻手以及手的位置對於基於Kinect開發的應用程式顯得至關重要。手的位置及動作是手勢識別的基礎。追蹤手的運動是從Kinect擷取資料的最重要用途。在這個應用中,我們將忽視其他關節點資訊。

小時候,我們做這中連線時一般會用鉛筆或者顏料筆,然後用手控制鉛筆或則顏料筆進行連線。我們的這個小遊戲顛覆了這種方式,我們的互動非常自然,就是手。這樣有比較好的沉浸感,使得遊戲更加有趣。當然,開發基於Kinect的應用程式這種互動顯得自然顯得至關重要。幸運的是,我們只需要一點代碼就能實現這一點。

在應用程式中可能有多個遊戲者,我們設定,不論那隻手離Kinect最近,我們使用距離Kinect最近的那個遊戲者的那隻手作為控製程序繪圖的手。當然,在遊戲中,任何時候使用者可以選擇使用左手還是右手,這會使得使用者操作起來比較舒服,SkeletonFrameReady代碼如下:

private void KinectDevice_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e){    using (SkeletonFrame frame = e.OpenSkeletonFrame())    {        if (frame != null)        {            frame.CopySkeletonDataTo(this.frameSkeletons);            Skeleton skeleton = GetPrimarySkeleton(this.frameSkeletons);                Skeleton[] dataSet2 = new Skeleton[this.frameSkeletons.Length];            frame.CopySkeletonDataTo(dataSet2);                if (skeleton == null)            {                HandCursorElement.Visibility = Visibility.Collapsed;            }            else            {                Joint primaryHand = GetPrimaryHand(skeleton);                TrackHand(primaryHand);                TrackPuzzle(primaryHand.Position);            }        }    }}        private static Skeleton GetPrimarySkeleton(Skeleton[] skeletons){    Skeleton skeleton = null;        if (skeletons != null)    {        //尋找最近的遊戲者        for (int i = 0; i < skeletons.Length; i++)        {            if (skeletons[i].TrackingState == SkeletonTrackingState.Tracked)            {                if (skeleton == null)                {                    skeleton = skeletons[i];                }                else                {                    if (skeleton.Position.Z > skeletons[i].Position.Z)                    {                        skeleton = skeletons[i];                    }                }            }        }    }    return skeleton;}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.