Сохраните движение Kinect v2. 0 в файл BVH


Я хотел бы сохранить данные захвата движения из Kinect 2 в виде файла BVH. Я нашел код, который делает это для Kinect 1, который можно найти здесь. Я прошел через код и нашел несколько вещей, которые я не смог понять. Например, в упомянутом коде я попытался понять, что именно скелет 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 для тела 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: в основном мне удалось сохранить файл a 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 294

1 ответ:

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

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,каркас класс был заменен на тело класс, так что вы должны изменить его, чтобы иметь дело с тело вместо этого, и получить суставы, выполнив действия, указанные ниже.

// 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, Вы обратите внимание, что класс скелета был заменен классом тела. Помните MultiSourceFrameReader? Этот класс дает нам доступ каждый поток, включая поток тела! Мы просто должны позволить датчик знает что нам нужна функциональность тела отслеживая мимо добавление дополнительный параметр при инициализации считывателя:

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

_reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;

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

  1. получить ссылку на каркас кузова
  2. проверьте, является ли рамка тела нулевой - это имеет решающее значение
  3. инициализировать список _bodies
  4. вызов метода GetAndRefreshBodyData, чтобы скопировать данные тела в список
  5. цикл через список тел и делать удивительные вещи!

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

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-KINECT для ВЕРСИЯ WINDOWS 2: ОТСЛЕЖИВАНИЕ ТЕЛА