首页 文章

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

提问于
浏览
295

我想将Kinect 2中的动作捕捉数据存储为BVH文件 . 我找到了Kinect 1的代码,可以找到here . 我查看了代码,发现了一些我无法理解的内容 . 例如,在上面提到的代码中,我试图理解在代码中的几个地方找到的Skeleton skel 对象到底是什么 . 如果没有,是否有任何已知的应用程序可用于完成预期的?

编辑:我试图将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 内部的计算位置 .

1 回答

  • 1

    用于 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ên Lê Đặng - Kinect2BVH.V2

    Kinect 2.0 之外, Skeleton 类已被 Body 类替换,因此您需要更改它以处理 Body ,并按照下面引用的步骤获取关节 .

    // Kinect命名空间
    使用Microsoft.Kinect;

    // ...

    // Kinect传感器和Kinect流读取器对象
    KinectSensor _sensor;
    MultiSourceFrameReader _reader;
    IList <Body> _body;

    // Kinect传感器初始化
    _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();

    //颜色
    // ...

    //深度
    // ...

    //红外线
    // ...

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

    frame.GetAndRefreshBodyData(_bodies);

    foreach(_ body中的var body)
    {
    if(body!= null)
    {
    //对身体做些什么......
    }
    }
    }
    }
    }
    就是这个!我们现在可以访问Kinect标识的机构 . 下一步是在屏幕上显示骨架信息 . 每个身体由25个关节组成 . 传感器为我们提供每个位置(X,Y,Z)和旋转信息 . 此外,Kinect让我们知道关节是否被跟踪,是否被追踪或被跟踪 . 在执行任何关键功能之前检查是否跟踪了主体是一个好习惯 . 以下代码说明了我们如何访问不同的身体关节:if(body!= null)
    {
    如果(body.IsTracked)
    {
    关节头= body.Joints [JointType.Head];

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

    //画关节......
    }
    }

    资料来源:Vangos Pterneas Blog - KINECT FOR WINDOWS VERSION 2: BODY TRACKING

相关问题