如何从可用坐标绘制骨架?

时间:2014-03-01 14:03:15

标签: c# kinect kinect.toolbox

当我输入问题时,我想从可用坐标绘制骨架线(或在两点之间绘制线)。绘制后,完成的手动骨架将如下所示。它与Skeleton Basic一样绘制,但是我们提供的坐标。

http://social.msdn.microsoft.com/Forums/getfile/425774

我在一个文本文件中保存了关节的坐标,这个应用程序将从该文件中获取数据。谁能帮帮我吗 ?我真的需要它。

我确实喜欢这样,但是屏幕上的骨架被冻结了,它没有按照文本文件中的坐标移动。

FileStream fs;
    private void Model_DrawBoneAndJoints(ref Skeleton skeleton, DrawingContext drawingContext)
    {
        fs = new FileStream
            (@"C:\Users\PhucTruongTien\Desktop\datagram.txt", FileMode.Open, FileAccess.Read, FileShare.None);
        StreamReader sr = new StreamReader(fs);
        float[] x = new float[20];
        float[] y = new float[20];

        SkeletonPoint position;
        Array Joint_Types = Enum.GetValues(typeof(JointType));
        //Joint[] joint_array = new Joint[20];

        foreach (JointType j_types in Joint_Types)
        {
            Joint joint = new Joint();
            joint = skeleton.Joints[j_types];
            joint.TrackingState = JointTrackingState.Tracked;
            position = joint.Position;
            position.X = (float)Convert.ToDouble(sr.ReadLine());
            position.Y = (float)Convert.ToDouble(sr.ReadLine());
            position.Z = (float)Convert.ToDouble(sr.ReadLine());
            joint.Position = position;
            skeleton.Joints[j_types] = joint;
        }

}

private void DrawBonesAndJoints(Skeleton skeleton,DrawingContext drawingContext) {         Model_DrawBoneAndJoints(ref skeleton,drawingContext);

        //i++;
        // Render Torso
        this.DrawBone(skeleton, drawingContext, JointType.Head, JointType.ShoulderCenter);
        this.DrawBone(skeleton, drawingContext, JointType.ShoulderCenter, JointType.ShoulderLeft);
        this.DrawBone(skeleton, drawingContext, JointType.ShoulderCenter, JointType.ShoulderRight);
        this.DrawBone(skeleton, drawingContext, JointType.ShoulderCenter, JointType.Spine);
        this.DrawBone(skeleton, drawingContext, JointType.Spine, JointType.HipCenter);
        this.DrawBone(skeleton, drawingContext, JointType.HipCenter, JointType.HipLeft);
        this.DrawBone(skeleton, drawingContext, JointType.HipCenter, JointType.HipRight);

        // Left Arm
        this.DrawBone(skeleton, drawingContext, JointType.ShoulderLeft, JointType.ElbowLeft);
        this.DrawBone(skeleton, drawingContext, JointType.ElbowLeft, JointType.WristLeft);
        this.DrawBone(skeleton, drawingContext, JointType.WristLeft, JointType.HandLeft);

        // Right Arm
        this.DrawBone(skeleton, drawingContext, JointType.ShoulderRight, JointType.ElbowRight);
        this.DrawBone(skeleton, drawingContext, JointType.ElbowRight, JointType.WristRight);
        this.DrawBone(skeleton, drawingContext, JointType.WristRight, JointType.HandRight);

        // Left Leg
        this.DrawBone(skeleton, drawingContext, JointType.HipLeft, JointType.KneeLeft);
        this.DrawBone(skeleton, drawingContext, JointType.KneeLeft, JointType.AnkleLeft);
        this.DrawBone(skeleton, drawingContext, JointType.AnkleLeft, JointType.FootLeft);

        // Right Leg
        this.DrawBone(skeleton, drawingContext, JointType.HipRight, JointType.KneeRight);
        this.DrawBone(skeleton, drawingContext, JointType.KneeRight, JointType.AnkleRight);

        this.DrawBone(skeleton, drawingContext, JointType.AnkleRight, JointType.FootRight);

        // Render Joints
        foreach (Joint joint in skeleton.Joints)
        {
            Brush drawBrush = null;

            if (joint.TrackingState == JointTrackingState.Tracked)
            {
                drawBrush = this.trackedJointBrush;
            }
            else if (joint.TrackingState == JointTrackingState.Inferred)
            {
                drawBrush = this.inferredJointBrush;
            }

            if (drawBrush != null)
            {
                drawingContext.DrawEllipse(drawBrush, null, this.SkeletonPointToScreen(joint.Position), JointThickness, JointThickness);
            }
        }
    }

抱歉我的英文不好!

1 个答案:

答案 0 :(得分:1)

您可以使用StreamWriter,在选定路径初始化它,然后为每个帧,增加帧计数器,将其写入文件,将时间戳写入文件,然后循环关节并写入他们到文件。我会这样做:

using System.IO;

StreamWriter writer = new StreamWriter(@path);
int frames = 0;

...

void AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
    frames++;
    using (SkeletonFrame sFrame = e.OpenSkeletonFrameData())
    {
        if (sFrame == null)
            return;

        skeletonFrame.CopySkeletonDataTo(skeletons);

        Skeleton skeleton = (from s in skeletons
                                where s.TrackingState == SkeletonTrackingState.Tracked
                                select s);
        if (skeleton == null)
            return;

        if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
        {
            foreach (Joint joint in skeleton.Joints)
            {
                writer.Write(joint.Position.X + "," + joint.Position.Y + "," joint.Position.Z + ",");
            }
            writer.Write(Environment.NewLine);
        }
    }
}

然后从文件中读取:

StreamReader reader = new StreamReader(@path);
int frame = -1;
JointCollection joints;

...

string[] lines = reader.ReadAllLines();

...

void AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
    canvas.Children.Clear();
    string[] coords = lines[frame];
    int jointIndex = 0;
    for (int i = 0; i < coords.Length; i += 3)
    {
        joints[jointIndex].Position.X = int.Parse(coords[i]);
        joints[jointIndex].Position.Y = int.Parse(coords[i + 1]);
        joints[jointIndex].Position.X = int.Parse(coords[i + 2]);
        jointIndex++;
    }

    DepthImageFrame depthFrame = e.OpenDepthImageFrame();
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.HipCenter, JointType.Spine, JointType.ShoulderCenter, JointType.Head }, depthFrame, canvas));
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.ShoulderCenter, JointType.ShoulderLeft, JointType.ElbowLeft, JointType.WristLeft, JointType.HandLeft }, depthFrame, canvas));
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.ShoulderCenter, JointType.ShoulderRight, JointType.ElbowRight, JointType.WristRight, JointType.HandRight }, depthFrame, canvas));
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.HipCenter, JointType.HipLeft, JointType.KneeLeft, JointType.AnkleLeft, JointType.FootLeft }, depthFrame, canvas));
    canvas.Children.Add(GetBodySegment(joints, brush, new JointType[] { JointType.HipCenter, JointType.HipRight, JointType.KneeRight, JointType.AnkleRight, JointType.FootRight }, depthFrame, canvas));
    depthFrame.Dispose();

    frame++;
}

Point GetDisplayPosition(Joint joint, DepthImageFrame depthFrame, Canvas skeleton)
{
    float depthX, depthY;
    KinectSensor sensor = KinectSensor.KinectSensors[0];
    DepthImageFormat depthImageFormat = sensor.DepthStream.Format;
    DepthImagePoint depthPoint = sensor.CoordinateMapper.MapSkeletonPointToDepthPoint(joint.Position, depthImageFormat);

    depthX = depthPoint.X;
    depthY = depthPoint.Y;

    depthX = Math.Max(0, Math.Min(depthX * 320, 320));
    depthY = Math.Max(0, Math.Min(depthY * 240, 240));

    int colorX, colorY;
    ColorImagePoint colorPoint = sensor.CoordinateMapper.MapDepthPointToColorPoint(depthImageFormat, depthPoint, ColorImageFormat.RgbResolution640x480Fps30);
    colorX = colorPoint.X;
    colorY = colorPoint.Y;

    return new System.Windows.Point((int)(skeleton.Width * colorX / 640.0), (int)(skeleton.Height * colorY / 480));
}

Polyline GetBodySegment(Joint[] joints, Brush brush, JointType[] ids, DepthImageFrame depthFrame, Canvas canvas)
{
    PointCollection points = new PointCollection(ids.Length);
    for (int i = 0; i < ids.Length; ++i)
    {
        points.Add(GetDisplayPosition(joints[i], depthFrame, canvas));
    }
    Polyline polyline = new Polyline();
    polyline.Points = points;
    polyline.Stroke = brush;
    polyline.StrokeThickness = 5;
    return polyline;
}

虽然你正在做的事情会起作用,但是当我过去这样做时,我已经使用了这种方法。另一种方法是使用类似的设置来处理顶部的帧数,将每个关节写入一行,然后使用多维数组(例如jointCoords = new string[amountOfFrames, 21, 3]),然后每帧增加帧计数器,然后遍历所有关节,然后是x,y和z。从文件中读取的示例就像

        char[] delimiters = new char[] { '|', ' ' };
        //Make sure this file exists.
        string file_name_2 = "C:\\path\\doctor.txt";
        string[] lines = System.IO.File.ReadAllLines(@file_name_2);

        foreach (string line in lines)
        {

            // for the skeleton frame

            string[] seperated = line.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
            seperated.CopyTo(delim, 0);
            skeleton_frames_doctor[total_frames, count, 0] = int.Parse(delim[0]);
            skeleton_frames_doctor[total_frames, count, 1] = int.Parse(delim[1]);
            skeleton_frames_doctor[total_frames, count, 2] = int.Parse(delim[2]);
            count++;

            if (count == 21)
            {
                count = 0;
                total_frames++;
            }

        }

阅读看起来像是:

                foreach (Joint joint in data.Joints)
                {

                         Point jointPos = getDisplayPosition(joint);

                        //storing the patients x y coordinates
                        skeleton_frames[totalFrames1, joint_count, 0] = (double)jointPos.X;
                        skeleton_frames[totalFrames1, joint_count, 1] = (double)jointPos.Y;

                        //getting the doctors x y coordinates
                        XPos = (skeleton_frames[totalFrames1, 0, 0]) - (skeleton_frames_doctor[totalFrames1, 0, 0]);
                        YPos = (skeleton_frames[totalFrames1, 0, 1]) - (skeleton_frames_doctor[totalFrames1, 0, 1]);

                        //Scaling and transformation of doctors frame to patients frame
                        skeleton_frames_doctor_new[totalFrames1, joint_count, 0] = skeleton_frames_doctor[totalFrames1, joint_count, 0] + XPos;
                        skeleton_frames_doctor_new[totalFrames1, joint_count, 1] =  skeleton_frames_doctor[totalFrames1, joint_count, 1] + YPos;
                        for (int j = 0; j < 19; j++)
                        {
                            double DistP = Math.Sqrt(Math.Pow((skeleton_frames[totalFrames1, JointNo[j, 0] - 1, 0]) - skeleton_frames[totalFrames1, JointNo[j, 1] - 1, 0], 2) + Math.Pow((skeleton_frames[totalFrames1, JointNo[j, 0] - 1, 1]) - skeleton_frames[totalFrames1, JointNo[j, 1] - 1, 1], 2));
                            double DistD = Math.Sqrt(Math.Pow((skeleton_frames_doctor_new[totalFrames1, JointNo[j, 0] - 1, 0]) - skeleton_frames_doctor_new[totalFrames1, JointNo[j, 1] - 1, 0], 2) + Math.Pow((skeleton_frames_doctor_new[totalFrames1, JointNo[j, 0] - 1, 1]) - skeleton_frames_doctor_new[totalFrames1, JointNo[j, 1] - 1, 1], 2));
                            double alpha = DistP / DistD;
                            skeleton_frames_doctor_new[totalFrames1, JointNo[j, 1]-1, 0] = skeleton_frames_doctor_new[totalFrames1, JointNo[j, 0]-1, 0] + (skeleton_frames_doctor_new[totalFrames1, JointNo[j, 1]-1, 0] - skeleton_frames_doctor_new[totalFrames1, JointNo[j, 0]-1, 0]) * (alpha);
                            skeleton_frames_doctor_new[totalFrames1, JointNo[j, 1]-1, 1] = skeleton_frames_doctor_new[totalFrames1, JointNo[j, 0]-1, 1] + (skeleton_frames_doctor_new[totalFrames1, JointNo[j, 1]-1, 1] - skeleton_frames_doctor_new[totalFrames1, JointNo[j, 0]-1, 1]) * (alpha);
                        }


                    Line jointLine = new Line();
                    jointLine.X1 = jointPos.X - 3;
                    jointLine.X2 = jointLine.X1 + 6;
                    jointLine.Y1 = jointLine.Y2 = jointPos.Y;
                    jointLine.Stroke = jointColors[joint.ID];
                    jointLine.StrokeThickness = 6;
                    skeleton.Children.Add(jointLine);
                    joint_count++;
                }

请注意,JointNo只是一个用于查找某些关节类型索引的数组。这是

        int[,] JointNo = new int[19, 2];

        JointNo[0, 0] = 1;
        JointNo[0, 1] = 2;
        JointNo[1, 0] = 2;
        JointNo[1, 1] = 3;
        JointNo[2, 0] = 3;
        JointNo[2, 1] = 4;
        JointNo[3, 0] = 3;
        JointNo[3, 1] = 9;
        JointNo[4, 0] = 9;
        JointNo[4, 1] = 10;
        JointNo[5, 0] = 10;
        JointNo[5, 1] = 11;
        JointNo[6, 0] = 11;
        JointNo[6, 1] = 12;
        JointNo[7, 0] = 3;
        JointNo[7, 1] = 5;
        JointNo[8, 0] = 5;
        JointNo[8, 1] = 6;
        JointNo[9, 0] = 6;
        JointNo[9, 1] = 7;
        JointNo[10, 0] = 7;
        JointNo[10, 1] = 8;
        JointNo[11, 0] = 1;
        JointNo[11,1] = 13;
        JointNo[12, 0] = 13;
        JointNo[12, 1] = 14;
        JointNo[13,0] = 14;
        JointNo[13, 1] = 15;
        JointNo[14, 0] = 15;
        JointNo[14, 1] = 16;
        JointNo[15, 0] = 1;
        JointNo[15, 1] = 17;
        JointNo[16, 0] = 17;
        JointNo[16, 1] = 18;
        JointNo[17, 0] = 18;
        JointNo[17, 1] = 19;
        JointNo[18, 0] = 19;
        JointNo[18, 1] = 20;

你可以看到this code中的所有内容都是在beta 2中编写的,因此它目前无法编译,但它主要是你应该关注的方法。