2012-12-07 40 views
2

我有兩個不同的窗口,一個將顯示圖像上的流並計算用戶的骨架頭位置(窗口A),另一個顯示將使用骨架的3D視覺模型數據放大和翻譯(動畫)(窗口B)。將kinect骨架位置數據傳遞到另一個窗口

但是,我的問題是我怎麼能通過並不斷更新從窗口A到窗口B的這些骨架頭位置數據?我正在使用WPF和M'soft Kinect SDK。我的另一個問題是,如何在視覺模型上顯示像按鈕或菜單這樣的控件,以便在整個屏幕上填充模型。

foreach (Skeleton skeleton in skeletons) 
    { 
     if (skeleton.TrackingState == SkeletonTrackingState.Tracked) 
     { 

      ht.GetHeadPosition(skeleton, out message, out headPosition); 

      this.headPoint.X = headPosition.X; 
      this.headPoint.Y = headPosition.Y; 
      this.headPoint.Z = headPosition.Z; 

      this.StatusTextBlock.Text = message; 

     } 

編輯


public void newSensor_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) 
    { 
     using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame()) 
     { 
      if (skeletonFrame == null) 
       return; 

      GetSkeletons(skeletonFrame, ref skeletons); 

      if (skeletons.All(s => s.TrackingState == SkeletonTrackingState.NotTracked)) 
       return; 

      //skeletonManager.Draw(skeletons); 
     } 

     foreach (Skeleton skeleton in skeletons) 
     { 
      if (skeleton.TrackingState == SkeletonTrackingState.Tracked) 
      { 
       Joint headJoint = skeleton.Joints[JointType.Head]; 
       Joint hipCenter = skeleton.Joints[JointType.HipCenter]; 

       headPosition = headJoint.Position; 

       this.headPoint.X = headPosition.X; 
       this.headPoint.Y = headPosition.Y; 
       this.headPoint.Z = headPosition.Z; 

       message = string.Format("Head: X:{0:0.0} Y:{1:0.0} Z:{2:0.0}", 
       headPoint.X, 
       headPoint.Y, headPoint.Z); 

       //MessageBox.Show(message); 

       this.HeadPosition.Text = message; 
      } 
     } 
    } 

我不能獲得與data.What的HeadPosition.Text更新實際上發生了什麼?

的Kinect在窗口中更改事件處理程序

private void sensorChooser_KinectChanged(object sender, KinectChangedEventArgs e) 
    { 
     KinectSensor oldSensor = (KinectSensor)e.OldSensor; 
     StopKinect(oldSensor); 

     KinectSensor newSensor = (KinectSensor)e.NewSensor; 

     if (newSensor == null) 
     { 
      return; 
     } 

     //Register for event and enable Kinect Sensor features you want 
     newSensor.DepthFrameReady += newSensor_DepthFrameReady; 
     newSensor.SkeletonFrameReady += mw.newSensor_SkeletonFrameReady; 

     //newSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30); 
     newSensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30); 

     .... 

     newSensor.SkeletonStream.Enable(parameter); 

     StartKinect(newSensor); 

    } 

XAML_ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ _

<Grid x:Name="firstGrid"> 
    <Viewport3D x:Name="viewPort" Grid.Column="0" Grid.Row="0" ClipToBounds="False" Width="2048" 
    .... 
    ..... 
    </Viewport3D> 

    <TextBox x:Name="IndexPosition" HorizontalAlignment="Left" Height="23" Margin="485,2,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="69"/> 

    <TextBox x:Name="CameraPosition" HorizontalAlignment="Left" Height="23" Margin="570,2,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="142"/> 

    <TextBlock Name="HeadPosition" HorizontalAlignment="Left" Margin="492,23,0,0" Text="Text" VerticalAlignment="Top" Width="182" Height="29" 
       Foreground="Tomato" FontSize="20"/> 
+0

什麼'ht.GetHeadPoistion'在做什麼?直接訪問'skeleton.Joints [JointType.Head] .Position'對象會得到相同的東西 - 沒有使用'out'參數的奇怪。 –

+0

是的..我改回來直接訪問它。起初我認爲我可以從GetHeadPosition傳遞值。 – user1884304

回答

2

你可以用許多不同的方法之一來做到這一點。這完全取決於你想如何分離程序中的代碼。

選項1:公共事件處理程序

你可以在Window B預訂了從KinectSensorSkeletonFrameReady事件設置公共事件處理程序。例如,在課堂上,設置了您的KinectSensor你可能有這樣的:

WindowB windowB = new WindowB(); 

private void InitializeKinectServices(KinectSensor sensor) 
{ 
    // some setup code 

    sensor.SkeletonFrameReady += windowB.OnSkeletonFrameReady; 

    // some more setup code 
} 

然後在您的WindowB類,你將有事件回調:

public void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) 
{ 
    using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame()) 
    { 
     // do what you need 
    } 
} 

方案2:通過傳感器

您可以設置您的窗口接受對KinectSensor的引用。當您打開您的主類的第二個窗口,只是通過在傳感器:

WindowB windowB = new WindowB(sensor); 

有了您的WindowB構造採取KinectSensor,然後從上面設置回調:

public WindowB(KinectSensor sensor) { 
    sensor.SkeletonFrameReady += OnSkeletonFrameReady; 
} 

private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) 
{ 
    using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame()) 
    { 
     // do what you need 
    } 
} 

聲明本允許你的回調是私人的。

選項3:使用一個框架信使

你也可以使用一個框架信使,如MVVM Light。 MVVM Light提供了一個輕量級的信使系統,允許您輕鬆地將對象從一個視圖傳遞到下一個視圖。雖然這在MVVM結構化程序中更有用,並不意味着您不能在一個之外使用它。

您可以從主班列廣播整個SkeletonFrameReadyEventArgsSkeletonFrameReady回調:

private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) 
{ 
    Messenger.Default.Send<SkeletonFrameReadyEventArgs>(e); 

    // do more stuff 
} 

然後你只需要在你WindowB訂閱它:

public WindowB() { 
    Messenger.Default.Register<SkeletonFrameReadyEventArgs>(this, OnSkeletonFrameReady); 
} 

private void OnSkeletonFrameReady(SkeletonFrameReadyEventArgs e) 
{ 
    // do what you need with the event arg, just as you would in a regular callback 
} 

或者你可以只發個人Skeleton,fromo your main class:

private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) 
{ 
    using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame()) 
    { 
     // do checks for capturing the appropriate skeleton. 

     Messenger.Default.Send<SkeletonFrame>(skeletonFrame); 

     // do more stuff if you need. 
    } 
} 

然後,您的WindowB將如上所示註冊到SkeletonFrame而不是事件參數。回調將執行與SkeletonFrame對象相關的操作。

什麼是最好的?

由你決定。還有其他幾種方法可以最終做到這一點。這是我想到的前三個。他們都會完成同樣的事情 - 你只是想用你最適合你的程序風格。

最大化窗口

要最大化窗口,你可以放置一個按鈕,在你的XAML和設置回調到MaximizedNormal窗口狀態之間切換。

XAML:

<Button Click="MyButton_Click">Click Me</Button> 

代碼背後:

bool _isMaxed = false; 
public void MyButton_Click(object sender, RoutedEventArgs e) 
{ 
    if (_isMaxed) 
     this.WindowState = WindowState.Normal; 
    else 
     this.WindowState = WindowState.Maximized; 

    _isMaxed = !_isMaxed; 
} 
+0

我嘗試了第一個選項,我想我設法得到了頭部位置,但發生了一些奇怪的事情。我分配了一個文本塊來顯示和跟蹤頭部位置,但它不會顯示值,但是當我使用messagebox.show時,它顯示出來了。 – user1884304

+0

我上面更新了我的代碼..如何在評論中發佈代碼? – user1884304

+0

你也需要包含你的XAML。代碼本身看起來很好,但是你的文章中缺少一半圖片(即XAML)。 –

0
  1. 您可以將骨架傳遞到第二個窗口(例如在構造函數中)並使用其OnHeadPositionChanged事件。

  2. 只需添加在XAML控制,並設置固定的位置,像Margin="0,10,0,10",或使用帆布作爲親和通過Canvas.Top="0" Canvas.Left="20"設定的位置。

+0

將'Skeleton'傳遞給窗口構造函數將不起作用,因爲它是一個沒有事件的簡單數據對象。 –

+0

@Florian嗨..我試着通過構造函數之前,但似乎不能工作..hmm .. – user1884304

+0

@Evil Closet猴子..你對我的第一個問題有什麼想法嗎?編輯:剛纔看到答覆是你的..哈哈..反正。 – user1884304

相關問題