【问题标题】:mapping an ellipse to a joint in kinect sdk 1.5将椭圆映射到 kinect sdk 1.5 中的关节
【发布时间】:2012-08-07 22:02:22
【问题描述】:

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

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

【问题讨论】:

  • 您是否至少初始化了 kinect,只是想知道如何检索骨架对象?或者您需要有关 kinect 的完整教程?

标签: c# c#-4.0 kinect


【解决方案1】:

虽然 @Heisenbug 可以工作,但 WPF 中有一个更简单的方法。您可以在Channel 9's 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);
    }

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

【讨论】:

  • 很高兴知道:)。几个月前我玩了一点kinect。我没有找到任何关于它的大量文档,所以我只是尝试提出一些工作代码,尝试并查看其他人的代码。
  • 是的,但是很高兴知道如何在 XNA 中做到这一点
【解决方案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

【讨论】:

  • 非常适合使用新的 SDK。互联网上的每个人仍然使用 beta SDK。我有个问题。如何设置位置?当我输入 myjoint.position.X 时,Intellisense 会告诉我它获取并设置 X 的位置。我该如何设置呢?我发现的只是 ScaleTo() 已在较新的 SDK 中删除
  • @macrian: 为什么要修改位置?位置是您通过 Kinect 获取的数据,我看不到修改它们的实用性。 SkeletonPoint 是一个结构。您可以访问该结构的单个元素,例如 rightHand.X = 5f;当然,您正在修改 rigthHand 结构的本地副本。
  • 好的,我拥有的代码是具有 scaleto 功能的 beta sdk 代码。我似乎不明白如何使用新的 sdk 扩展关节(我正在将项目从 beta sdk 转换为新的
  • 我不知道 Scale 方法是做什么的,从未使用过 beta SDK。尺度是什么意思?你能提供一个解释或一个例子吗?
  • 好吧,我也没用过,我有一个学期的项目,代码使用的是 beta SDK。 Anw 您正在做的所有 scaleto 方法是定义真实世界中的哪个位置(ala:Kinect 坐标)等于屏幕的左侧、右侧、顶部和底部。你只是告诉你的应用程序“这个 Kinect 坐标等于这个屏幕像素”。我的代码是这个 Joint scaledRight = jointRight.ScaleTo((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, SkeletonMaxX, SkeletonMaxY);我需要一种方法来对新的 sdk 做同样的事情
猜你喜欢
  • 1970-01-01
  • 2016-04-14
  • 2014-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多