Сохранить Kinect v2.0 Движение к файлу BVH

Я хотел бы сохранить данные захвата движения из Kinect 2 в виде файла BVH. Я нашел код, который делает это для Kinect 1, который можно найти здесь. Я прошел через код и нашел несколько вещей, которые я не мог понять. Например, в упомянутом коде я попытался понять, что именно представляет собой объект Skeleton skel, найденный в нескольких местах в коде. Если нет, существует ли известное приложение для выполнения запланированного?

EDIT: Я попытался сменить Skeleton skel на Body skel, который, я думаю, является соответствующим объектом для kinect SDK 2.0. Однако у меня есть ошибка, когда я пытаюсь получить положение тела:

tempMotionVektor[0] = -Math.Round( skel.Position.X * 100,2);
tempMotionVektor[1] = Math.Round( skel.Position.Y * 100,2) + 120;
tempMotionVektor[2] = 300 - Math.Round( skel.Position.Z * 100,2);

У меня возникли ошибки при вызове функции Position for the Body skel. Как я могу получить X, Y, Z скелета в sdk 2.0?? Я попытался изменить следующие три строки:

tempMotionVektor[0] = -Math.Round(skel.Joints[0].Position.X * 100, 2);
tempMotionVektor[1] = Math.Round(skel.Joints[0].Position.Y * 100, 2) + 120;
tempMotionVektor[2] = 300 - Math.Round(skel.Joints[0].Position.Z * 100, 2);

EDIT: В основном мне удалось сохранить файл bvh после объединения bodyBasicsWPF и kinect2bvh. Однако кажется, что скелет, который я храню, неэффективен. В локтях происходят странные движения. Я пытаюсь понять, если мне нужно что-то изменить в файле kinectSkeletonBVH.cp. Более конкретно, каковы изменения в ориентации оси сустава для версии kinect 2. Как изменить следующую строку: skel.BoneOrientations[JointType.ShoulderCenter].AbsoluteRotation.Quaternion; Я попытался изменить эту строку с помощью skel.JointOrientations[JointType.ShoulderCenter].Orientation. Я прав? Я использую следующий код для добавления сустава к объектам BVHBone:

BVHBone hipCenter = new BVHBone(null, JointType.SpineBase.ToString(), 6, TransAxis.None, true);
BVHBone hipCenter2 = new BVHBone(hipCenter, "HipCenter2", 3, TransAxis.Y, false);
BVHBone spine = new BVHBone(hipCenter2, JointType.SpineMid.ToString(), 3, TransAxis.Y, true);
BVHBone shoulderCenter = new BVHBone(spine, JointType.SpineShoulder.ToString(), 3, TransAxis.Y, true);

BVHBone collarLeft = new BVHBone(shoulderCenter, "CollarLeft", 3, TransAxis.X, false);
BVHBone shoulderLeft = new BVHBone(collarLeft, JointType.ShoulderLeft.ToString(), 3, TransAxis.X, true);
BVHBone elbowLeft = new BVHBone(shoulderLeft, JointType.ElbowLeft.ToString(), 3, TransAxis.X, true);
BVHBone wristLeft = new BVHBone(elbowLeft, JointType.WristLeft.ToString(), 3, TransAxis.X, true);
BVHBone handLeft = new BVHBone(wristLeft, JointType.HandLeft.ToString(), 0, TransAxis.X, true);

BVHBone neck = new BVHBone(shoulderCenter, "Neck", 3, TransAxis.Y, false);
BVHBone head = new BVHBone(neck, JointType.Head.ToString(), 3, TransAxis.Y, true);
BVHBone headtop = new BVHBone(head, "Headtop", 0, TransAxis.None, false);

Я не могу понять, где вычисляется код the axis for every Joint.

Ответ 1

Код, который вы использовали для Kinect 1.0 для получения файла BVH, использует информацию о суставах для создания костных векторов, читая Скелет.

public static double[] getBoneVectorOutofJointPosition(BVHBone bvhBone, Skeleton skel)
{
    double[] boneVector = new double[3] { 0, 0, 0 };
    double[] boneVectorParent = new double[3] { 0, 0, 0 };
    string boneName = bvhBone.Name;

    JointType Joint;
    if (bvhBone.Root == true)
    {
        boneVector = new double[3] { 0, 0, 0 };
    }
    else
    {
        if (bvhBone.IsKinectJoint == true)
        {
            Joint = KinectSkeletonBVH.String2JointType(boneName);

            boneVector[0] = skel.Joints[Joint].Position.X;
            boneVector[1] = skel.Joints[Joint].Position.Y;
            boneVector[2] = skel.Joints[Joint].Position.Z;
..

Источник: Nguyên Lê Đặng - Kinect2BVH.V2

За исключением Kinect 2.0 класс Skeleton заменен классом Body, поэтому вам нужно изменить его, чтобы иметь дело с Тело, и получить суставы, выполнив шаги, приведенные ниже.

// Kinect namespace
using Microsoft.Kinect;

// ...

// Kinect sensor and Kinect stream reader objects
KinectSensor _sensor;
MultiSourceFrameReader _reader;
IList<Body> _bodies;

// Kinect sensor initialization
_sensor = KinectSensor.GetDefault();

if (_sensor != null)
{
    _sensor.Open();
}

Мы также добавили список тел, где все связанные с телом/скелетом данные будут сохранены. Если вы разработали для Kinect версии 1, вы обратите внимание, что класс Skeleton был заменен классом Body. Помните MultiSourceFrameReader? Этот класс дает нам доступ к каждый поток, включая поток тела! Нам просто нужно датчик знает, что нам нужна функция отслеживания тела, добавляя дополнительный параметр при инициализации считывателя:

_reader = _sensor.OpenMultiSourceFrameReader(FrameSourceTypes.Color |
                                             FrameSourceTypes.Depth |
                                             FrameSourceTypes.Infrared |
                                             FrameSourceTypes.Body);

_reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;

Метод Reader_MultiSourceFrameArrived будет вызываться всякий раз, когда новый кадр доступен. Давайте уточним, что произойдет с точки зрения данные тела:

  • Получить ссылку на рамку тела
  • Проверьте, является ли тело кадра нулевым - это важно
  • Инициализировать список _bodies
  • Вызвать метод GetAndRefreshBodyData, чтобы скопировать данные тела в список
  • Прокрутите список тел и сделайте потрясающий материал!

Всегда помните, что нужно проверить нулевые значения. Kinect предоставляет вам приблизительно 30 кадров в секунду - все может быть нулевым или отсутствует! Вот код:

void Reader_MultiSourceFrameArrived(object sender,
            MultiSourceFrameArrivedEventArgs e)
{
    var reference = e.FrameReference.AcquireFrame();

    // Color
    // ...

    // Depth
    // ...

    // Infrared
    // ...

    // Body
    using (var frame = reference.BodyFrameReference.AcquireFrame())
    {
        if (frame != null)
        {
            _bodies = new Body[frame.BodyFrameSource.BodyCount];

            frame.GetAndRefreshBodyData(_bodies);

            foreach (var body in _bodies)
            {
                if (body != null)
                {
                    // Do something with the body...
                }
            }
        }
    }
}

Вот оно! Теперь у нас есть доступ к телам, которые идентифицирует Kinect. следующий шаг - отобразить информацию о скелете на экране. Каждый орган состоит из 25 суставов. Датчик обеспечивает нам положение (X, Y, Z) и информацию о вращении для каждого из них. Кроме того, Kinect позволяет нам узнать, отслеживаются ли суставы, анализируются или нет отслеживаются. Хорошая практика - проверить, отслеживается ли тело перед выполнением каких-либо критических функций.

Следующий код иллюстрирует, как мы можем получить доступ к разному телу суставы:

if (body != null)
{
    if (body.IsTracked)
    {
        Joint head = body.Joints[JointType.Head];

        float x = head.Position.X;
        float y = head.Position.Y;
        float z = head.Position.Z;

        // Draw the joints...
    }
}

Источник: Блог Vangos Pterneas - ИЗОБРАЖЕНИЕ ДЛЯ WINDOWS ВЕРСИЯ 2: ОТКЛЮЧЕНИЕ ТЕЛА