将Kinect的v2.0 Motion存储到BVH文件


298

我想将Kinect 2中的运动捕捉数据存储为BVH文件。我找到了针对Kinect 1的代码,可以在此处找到。我遍历了代码,发现了一些我无法理解的东西。例如,在上述代码中,我试图理解skel在代码中多个位置发现的Skeleton 对象究竟是什么。如果不是,是否有任何已知的应用程序可以实现预期的目标?

编辑:我试图将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);

调用Body skel函数Position时出现错误。如何在SDK 2.0中检索骨架的X,Y,Z?我试图将以上三行更改为:

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);

编辑:基本上我结合bodyBasicsWPF和kinect2bvh后设法存储了一个bvh文件。但是,似乎我要存储的框架效率不高。肘部有奇怪的动作。我想了解是否必须更改文件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计算位置。


9
我跳过了这个问题,但是,如果您有任何解决方案,最好将它发布在这里,不仅对我来说,因为我注意到很多人正在搜索将运动存储在bvh文件中。
Jose Ramon

我可以存储txt文件的Kinect v1和v2信息。这个BVH文件是我刚刚阅读的,它将成为我要添加到我们的采集软件中的功能。如果您对* .txt文件感兴趣,请告诉我。我没有适当的BVH解决方案。
16per9 '16


1
我有一种方法可以将Kinect v1和Kinect v2流正确写入txt。如果您使用它,则可以再次检查同一实验的bvh文件。检查我的简历以获取更多信息。
16per9 '16

1
@ Khaled.K如果您发布的链接回答了这个问题,您介意将其形成为这个问题的答案(每个元问题
Matt Thomas

Answers:


2

您用于Kinect 1.0以获得BVH文件的代码使用关节信息通过读取Skeleton来构建骨骼矢量。

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ênLêĐặng-Kinect2BVH.V2

Kinect 2.0之外Skeleton类已由Body类替换,因此您需要对其进行更改以处理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方法。让我们指定根据身体数据会发生什么:

  1. 获取车身框架的参考
  2. 检查身体框架是否为空–这很关键
  3. 初始化_bodies列表
  4. 调用GetAndRefreshBodyData方法,以便将正文数据复制到列表中
  5. 遍历尸体列表并做一些很棒的事情!

始终记得检查空值。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版本KINECT 2:身体追踪

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.