我正在尝试将一些图像附加到用户的头部和拳头,但似乎我无法正确定位它。图像总是在头部和拳头下方太多。
我有这个 XAML:
<Page x:Class="KinectD.Game1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:k="http://schemas.microsoft.com/kinect/2013"
xmlns:WpfViewers="clr-namespace:Microsoft.Samples.Kinect.WpfViewers;assembly=Microsoft.Samples.Kinect.WpfViewers"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800"
Title="Game1">
<Canvas>
<k:KinectRegion x:Name="kinectRegion" Canvas.Left="630">
<k:KinectCircleButton Label="Menu" HorizontalAlignment="Right" Height="200" VerticalAlignment="Top" Click="MenuButtonOnClick" >
<StackPanel>
<Image Source="Images/smile.png" Height="30"/>
</StackPanel>
</k:KinectCircleButton>
</k:KinectRegion>
<k:KinectUserViewer k:KinectRegion.KinectRegion="{Binding ElementName=kinectRegion}" Height="100" HorizontalAlignment="Center" VerticalAlignment="Top" />
<k:KinectSensorChooserUI HorizontalAlignment="Center" VerticalAlignment="Top" x:Name="sensorChooserUi" /><WpfViewers:KinectColorViewer Canvas.Top="0" Canvas.Left="0" HorizontalAlignment="Left" Height="480" Width="640" Margin="0,0,0,0" VerticalAlignment="Center" Kinect="{Binding ElementName=sensorChooserUi, Path=KinectSensorChooser.Kinect, Mode=OneWay}" BorderThickness="1" BorderBrush="Black"/>
<Image x:Name="rightEllipse" Canvas.Left="670" Source="Images/glove_right.png" Height="100" Width="70" Margin="0,400,10,0" VerticalAlignment="Top" HorizontalAlignment="Right"/>
<Image x:Name="leftEllipse" Canvas.Left="670" Source="Images/glove_left.png" Height="100" Width="70" Margin="0,300,10,0" VerticalAlignment="Top" HorizontalAlignment="Right"/>
<Image x:Name="headImage" Canvas.Left="670" Source="Images/smile.png" Height="70" Width="70" Margin="0,200,10,0" VerticalAlignment="Top" HorizontalAlignment="Right"/>
</Canvas>
而这个 XAML.CS:
public partial class Game1 : Page
{
#region "Kinect"
private KinectSensorChooser sensorChooser;
#endregion
bool closing = false;
const int skeletonCount = 6;
Skeleton[] allSkeletons = new Skeleton[skeletonCount];
public Game1()
{
this.InitializeComponent();
// initialize the sensor chooser and UI
this.sensorChooser = new KinectSensorChooser();
//Assign the sensor chooser with the sensor chooser from the mainwindow.
//We are reusing the sensorchoosing declared in the first window that can in contact with kinect
this.sensorChooser = Generics.GlobalKinectSensorChooser;
//subscribe to the sensorChooserOnKinectChanged event
this.sensorChooser.KinectChanged += SensorChooserOnKinectChanged;
//Assign Kinect Sensorchooser to the sensorchooser we got from our static class
this.sensorChooserUi.KinectSensorChooser = sensorChooser;
var parameters = new TransformSmoothParameters
{
Smoothing = 0.3f,
Correction = 0.0f,
Prediction = 0.0f,
JitterRadius = 1.0f,
MaxDeviationRadius = 0.5f
};
this.sensorChooser.Kinect.SkeletonStream.Enable(parameters);
this.sensorChooserUi.KinectSensorChooser.Kinect.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(sensor_AllFramesReady);
// Bind the sensor chooser's current sensor to the KinectRegion
var regionSensorBinding = new Binding("Kinect") { Source = this.sensorChooser };
BindingOperations.SetBinding(this.kinectRegion, KinectRegion.KinectSensorProperty, regionSensorBinding);
//this.sensorChooser.Kinect.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(sensor_AllFramesReady);
}
private void SensorChooserOnKinectChanged(object sender, KinectChangedEventArgs args)
{
bool error = false;
if (args.OldSensor != null)
{
try
{
args.OldSensor.DepthStream.Range = DepthRange.Default;
args.OldSensor.SkeletonStream.EnableTrackingInNearRange = false;
args.OldSensor.DepthStream.Disable();
args.OldSensor.SkeletonStream.Disable();
args.OldSensor.ColorStream.Disable();
}
catch (InvalidOperationException)
{
// KinectSensor might enter an invalid state while enabling/disabling streams or stream features.
// E.g.: sensor might be abruptly unplugged.
error = true;
}
}
if (args.NewSensor != null)
{
try
{
args.NewSensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
args.NewSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
args.NewSensor.SkeletonStream.Enable();
}
catch (InvalidOperationException)
{
error = true;
// KinectSensor might enter an invalid state while enabling/disabling streams or stream features.
// E.g.: sensor might be abruptly unplugged.
}
}
if (!error)
kinectRegion.KinectSensor = args.NewSensor;
}
void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
if (closing)
{
return;
}
//Get a skeleton
Skeleton first = GetFirstSkeleton(e);
if (first == null)
{
return;
}
//set scaled position
ScalePosition(headImage, first.Joints[JointType.Head]);
ScalePosition(leftEllipse, first.Joints[JointType.HandLeft]);
ScalePosition(rightEllipse, first.Joints[JointType.HandRight]);
GetCameraPoint(first, e);
}
void GetCameraPoint(Skeleton first, AllFramesReadyEventArgs e)
{
using (DepthImageFrame depth = e.OpenDepthImageFrame())
{
if (depth == null ||
this.sensorChooser.Kinect == null)
{
return;
}
//Map a joint location to a point on the depth map
//head
DepthImagePoint headDepthPoint =
this.sensorChooser.Kinect.CoordinateMapper.MapSkeletonPointToDepthPoint(first.Joints[JointType.Head].Position, depth.Format);
//left hand
DepthImagePoint leftDepthPoint =
this.sensorChooser.Kinect.CoordinateMapper.MapSkeletonPointToDepthPoint(first.Joints[JointType.HandLeft].Position, depth.Format);
//right hand
DepthImagePoint rightDepthPoint =
this.sensorChooser.Kinect.CoordinateMapper.MapSkeletonPointToDepthPoint(first.Joints[JointType.HandRight].Position, depth.Format);
//Map a depth point to a point on the color image
//head
ColorImagePoint headColorPoint =
this.sensorChooser.Kinect.CoordinateMapper.MapDepthPointToColorPoint(depth.Format, headDepthPoint, ColorImageFormat.RgbResolution640x480Fps30);
//left hand
ColorImagePoint leftColorPoint =
this.sensorChooser.Kinect.CoordinateMapper.MapDepthPointToColorPoint(depth.Format, leftDepthPoint, ColorImageFormat.RgbResolution640x480Fps30);
//right hand
ColorImagePoint rightColorPoint =
this.sensorChooser.Kinect.CoordinateMapper.MapDepthPointToColorPoint(depth.Format, rightDepthPoint, ColorImageFormat.RgbResolution640x480Fps30);
//Set location
CameraPosition(headImage, headColorPoint);
CameraPosition(leftEllipse, leftColorPoint);
CameraPosition(rightEllipse, rightColorPoint);
}
}
Skeleton GetFirstSkeleton(AllFramesReadyEventArgs e)
{
using (SkeletonFrame skeletonFrameData = e.OpenSkeletonFrame())
{
if (skeletonFrameData == null)
{
return null;
}
skeletonFrameData.CopySkeletonDataTo(allSkeletons);
//get the first tracked skeleton
Skeleton first = (from s in allSkeletons
where s.TrackingState == SkeletonTrackingState.Tracked
select s).FirstOrDefault();
return first;
}
}
private void CameraPosition(FrameworkElement element, ColorImagePoint point)
{
//Divide by 2 for width and height so point is right in the middle
// instead of in top/left corner
Canvas.SetLeft(element, point.X - element.Width / 2);
Canvas.SetTop(element, point.Y - element.Height / 2);
//Canvas.SetLeft(element, point.X - element.Width);
//Canvas.SetTop(element, point.Y - element.Height);
}
private void ScalePosition(FrameworkElement element, Joint joint)
{
//convert the value to X/Y
//Joint scaledJoint = joint.ScaleTo(1280, 720);
//convert & scale (.3 = means 1/3 of joint distance)
//Joint scaledJoint = joint.ScaleTo(640, 480, .3f, .3f);
Joint scaledJoint = joint.ScaleTo(640, 480, .3f, .3f);
Canvas.SetLeft(element, scaledJoint.Position.X);
Canvas.SetTop(element, scaledJoint.Position.Y);
}
private void MenuButtonOnClick(object sender, RoutedEventArgs e)
{
this.sensorChooser.KinectChanged -= SensorChooserOnKinectChanged;
(Application.Current.MainWindow.FindName("_mainFrame") as Frame).Source = new Uri("MainMenu.xaml", UriKind.Relative);
}
}
它似乎正确读取骨架,因为图像立即移动到用户区域但不正确。在我看来,图像可以正确水平移动,但不能垂直移动。它们在用户的头部和拳头下方,但我会说低于 200 像素太多。任何想法可能是什么问题?