Как нарисовать скелет по имеющимся координатам?

когда я набрал вопрос, я хочу нарисовать линию скелета (или нарисовать линию между двумя точками) из доступных координат. После рисования готовый мануал-скелет будет выглядеть так. Он отрисовывается так же, как и 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 (скелет скелета, DrawingContext DrawingContext) { Model_DrawBoneAndJoints (ссылочный скелет, 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);
            }
        }
    }

Извините за мой плохой английский!


person iamatsundere181    schedule 01.03.2014    source источник
comment
Когда вы всегда читаете один и тот же файл с одними и теми же координатами одного скелета, что должно вызывать движение?   -  person Thomas Hetzer    schedule 01.03.2014


Ответы (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;

Вы можете увидеть все это в действии из этого кода, который был написан в бета-версии 2, поэтому он не будет скомпилировать в настоящее время, но в основном это методология, с которой вы должны быть связаны.

person Liam McInroy    schedule 01.03.2014
comment
Спасибо, я заработал и у меня есть еще один вопрос, как изменить цвет скелета с зеленого на красный в kinect? - person iamatsundere181; 02.03.2014
comment
@iamatsundere181 Вы изменили brush - person Liam McInroy; 03.03.2014
comment
Спасибо ! Можете ли вы дать мне свой адрес электронной почты или ваш facebook? - person iamatsundere181; 03.03.2014
comment
@ iamatsundere181 Если это решило вопрос, примите его, и вы можете попробовать начать со мной чат как-нибудь. - person Liam McInroy; 03.03.2014
comment
у меня много вопросов, поэтому, если я смогу начать с вами чат, проблема будет решена проще - person iamatsundere181; 03.03.2014
comment
@iamatsundere181 Да, я могу поговорить через несколько часов или написать мне по электронной почте outlawlemur@gmail. ком - person Liam McInroy; 03.03.2014