我有两个不同的窗口,一个用于在图像上显示流并计算用户的骨架头部位置(窗口A),另一个用于显示3D视觉模型,该模型将使用骨架数据进行缩放和平移(动画) (窗口B)。
然而,我的问题是我怎么能想通过并继续将这些骨架头部位置数据从窗口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;
}
}
}
我无法使用数据获取HeadPosition.Text更新。实际发生了什么?
kinect在窗口A更改了事件处理程序
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 :(得分:2)
您可以通过多种方式之一完成此操作。这一切都取决于你想如何分离程序中的代码。
选项1:公共事件处理程序
您可以在Window B
中设置订阅来自SkeletonFrameReady
的{{1}}事件的公共事件处理程序。例如,在设置KinectSensor
的类中,您可能会遇到类似的内容:
KinectSensor
然后在你的WindowB windowB = new WindowB();
private void InitializeKinectServices(KinectSensor sensor)
{
// some setup code
sensor.SkeletonFrameReady += windowB.OnSkeletonFrameReady;
// some more setup code
}
课程中,您将获得事件回调:
WindowB
选项2:传递传感器
您可以设置窗口以接受对public void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
// do what you need
}
}
的引用。当您从主类打开第二个窗口时,只需将传感器传递到:
KinectSensor
使用WindowB windowB = new WindowB(sensor);
的构造函数获取WindowB
,然后设置上面的回调:
KinectSensor
请注意,这允许您的回调是私有的。
选项3:使用Framework Messenger
您还可以使用框架信使,例如MVVM Light。 MVVM Light提供了一个轻量级的信使系统,允许您轻松地将对象从一个视图传递到下一个视图。虽然这在MVVM结构化程序中更有用,但并不意味着你不能在一个程序之外使用它。
您可以在主要课程public WindowB(KinectSensor sensor) {
sensor.SkeletonFrameReady += OnSkeletonFrameReady;
}
private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
// do what you need
}
}
回调中播放整个SkeletonFrameReadyEventArgs
:
SkeletonFrameReady
然后您只需要向您订阅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
如上所示,您的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
对象所需的操作。
什么是最好的?
由你决定。还有其他几种方法可以最终实现这一目标。这是我想到的前三个。他们都将完成同样的事情 - 你只想使用你最熟悉的程序风格。
最大化窗口
要最大化窗口,您可以在XAML中放置一个按钮并设置回调以在SkeletonFrame
和Maximized
窗口状态之间切换。
XAML:
Normal
代码背后:
<Button Click="MyButton_Click">Click Me</Button>
答案 1 :(得分:0)
您可以将Skeleton传递到第二个窗口(例如在构造函数中)并使用其OnHeadPositionChanged-Event。
只需在xaml中添加控件并设置修复位置,例如Margin="0,10,0,10"
,或使用Canvas作为父级,并通过Canvas.Top="0" Canvas.Left="20"
设置位置。