存储Kinect's v2.0运动到BVH文件

本文关键字:运动 BVH 文件 v2 Kinect 存储 | 更新日期: 2023-09-27 17:50:42

我想将Kinect 2的动作捕捉数据存储为BVH文件。我在这里找到了Kinect 1的代码。我浏览了代码,发现了一些我无法理解的东西。例如,在上述代码中,我试图理解在代码中的几个地方发现的Skeleton skel 对象实际上是什么。如果没有,是否有任何已知的应用程序可以实现预期的目标?

编辑:我尝试将Skeleton skkel更改为Body skkel,我认为这是kinect SDK 2.0的对应对象。然而,当我试图获取body的位置时,出现了一个错误:

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

我已经得到错误时,调用函数位置的身体骨架。我如何检索的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);

编辑:基本上我设法存储一个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的计算

存储Kinect's v2.0运动到BVH文件

您用于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 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. 获取body frame的引用
  2. 检查body frame是否为null -这是至关重要的
  3. 初始化_bodies列表
  4. 调用GetAndRefreshBodyData方法,以便将body数据复制到列表中
  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 Blog - KINECT FOR WINDOWS VERSION 2: BODY TRACKING