2012-12-07 36 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

相关问题