0

我想将一个椭圆映射到手关节。椭圆必须随着我的手关节移动而移动。

请提供一些参考链接,帮助我使用 kinect Sdk 1.5 进行程序。谢谢

4

2 回答 2

3

尽管 @Heisenbug 可以工作,但 WPF 中有一种更简单的方法。您可以在Channel 9 的 Skeleton Fundamentals找到有关它的教程。基本上你需要一个画布,不管你想要多少椭圆。这是代码 XAML

 <Window x:Class="SkeletalTracking.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="600" Width="800" Loaded="Window_Loaded"  
    Closing="Window_Closing" WindowState="Maximized">       
<Canvas Name="MainCanvas">
    <Ellipse Canvas.Left="0" Canvas.Top="0" Height="50" Name="leftEllipse"  Width="50" Fill="#FF4D298D" Opacity="1" Stroke="White" />
    <Ellipse Canvas.Left="100" Canvas.Top="0" Fill="#FF2CACE3" Height="50" Name="rightEllipse" Width="50" Opacity="1" Stroke="White" />
    <Image Canvas.Left="66" Canvas.Top="90" Height="87" Name="headImage" Stretch="Fill" Width="84" Source="/SkeletalTracking;component/c4f-color.png" />
    <Ellipse Canvas.Left="283" Canvas.Top="233" Height="23" Name="leftknee" Stroke="Black" Width="29" />
    <Ellipse Canvas.Left="232" Canvas.Top="233" Height="23" Name="rightknee" Stroke="Black" Width="30" />
</Canvas>
</Window>

在这里,我使用了 4 个椭圆(膝盖、手)和一个图像(头部)。基本代码就在这里:

    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)
        //note you need to have Coding4Fun
        Joint scaledJoint = joint.ScaleTo(1280, 720, .3f, .3f);

        Canvas.SetLeft(element, scaledJoint.Position.X);
        Canvas.SetTop(element, scaledJoint.Position.Y);
    }

这是这个程序的关键。它从关节获取位置并将元素位置更改为那里。下一部分也很重要,您将执行以下操作:

    void GetCameraPoint(Skeleton first, AllFramesReadyEventArgs e)
    {

        using (DepthImageFrame depth = e.OpenDepthImageFrame())
        {
            if (depth == null ||
                kinectSensorChooser1.Kinect == null)
            {
                return;
            }


            //Map a joint location to a point on the depth map
            //head
            DepthImagePoint headDepthPoint =
                depth.MapFromSkeletonPoint(first.Joints[JointType.Head].Position);
            //left hand
            DepthImagePoint leftDepthPoint =
                depth.MapFromSkeletonPoint(first.Joints[JointType.HandLeft].Position);
            //right hand
            DepthImagePoint rightDepthPoint =
                depth.MapFromSkeletonPoint(first.Joints[JointType.HandRight].Position);


            //Map a depth point to a point on the color image
            //head
            ColorImagePoint headColorPoint =
                depth.MapToColorImagePoint(headDepthPoint.X, headDepthPoint.Y,
                ColorImageFormat.RgbResolution640x480Fps30);
            //left hand
            ColorImagePoint leftColorPoint =
                depth.MapToColorImagePoint(leftDepthPoint.X, leftDepthPoint.Y,
                ColorImageFormat.RgbResolution640x480Fps30);
            //right hand
            ColorImagePoint rightColorPoint =
                depth.MapToColorImagePoint(rightDepthPoint.X, rightDepthPoint.Y,
                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;

        }
    }

这只是获取您将选择的骨架的代码。然后,AllFrameReadyEventArgs您将这样做以将它们整合在一起。

    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]);
        ScalePosition(leftknee, first.Joints[JointType.KneeLeft]);
        ScalePosition(rightknee, first.Joints[JointType.KneeRight]);

        GetCameraPoint(first, e);
    }

如果您后面有彩色图像,您的结果将看起来最好,但我决定暂时跳过这部分。希望这可以帮助!

于 2012-08-07T14:02:22.310 回答
2

基本上,在代码中的某个地方,您将拥有一个与 Kinect SDK 交互的类:

private KinectSensor kinectSensor;

您可以通过这种方式初始化 KinectSensor:

public void kinectInit()
{
    KinectSensor.KinectSensors.StatusChanged += (object sender, StatusChangedEventArgs e) =>
    {
        if (e.Sensor == kinectSensor)
        {
            if (e.Status != KinectStatus.Connected)
            {
                SetSensor(null);
            }
        }else if ((kinectSensor == null) && (e.Status == KinectStatus.Connected))
        {
            SetSensor(e.Sensor);
        }
    };

    foreach (var sensor in KinectSensor.KinectSensors)
    {
        if (sensor.Status == KinectStatus.Connected)
        {
            SetSensor(sensor);
         }
    }
}

基本上,您正在定义一个委托来处理 KinectSensor 的状态更改。SetSensor 方法可能是这样的:

private void SetSensor(KinectSensor newSensor)
{
    if (kinectSensor != null)
    {
        kinectSensor.Stop();
    }

    kinectSensor = newSensor;

    if (kinectSensor != null)
    {
        kinectSensor.SkeletonStream.Enable();
        kinectSensor.SkeletonFrameReady += OnSkeletonFrameReady;
        kinectSensor.Start();
     }
}

现在, OnSkeletonFrameReady 它是“更新功能”。每次 Kinect 传感器更新时都会连续调用它。您可以在其中检索有关关节的信息并渲染您想要的内容。

private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{

    skelFrame = e.OpenSkeletonFrame();
    skeletons = new Skeleton[kinectSensor.SkeletonStream.FrameSkeletonArrayLength];          

    if (skelFrame != null)
    {
        skelFrame.CopySkeletonDataTo(skeletons);
        foreach (Skeleton skel in skeletons) {
        if (skel.TrackingState >= SkeletonTrackingState.Tracked)
        {
            //here's get the joints for each tracked skeleton
            SkeletonPoint rightHand = skel.Joints[JointType.HandRight].Position;
            ....    
         }
    }
}

由于您使用的是 C# 和 Kinect,因此可用于渲染椭圆的简单库是XNA

于 2012-08-07T11:29:52.353 回答