0

我正在尝试将一些图像附加到用户的头部和拳头,但似乎我无法正确定位它。图像总是在头部和拳头下方太多。

我有这个 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 像素太多。任何想法可能是什么问题?

4

0 回答 0