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

时间:2015-05-26 08:42:00

标签: c# kinect motion-detection

我想将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 个答案:

答案 0 :(得分:2)

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

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;
     

每当a调用Reader_MultiSourceFrameArrived方法   新框架可用。让我们来说明将会发生什么   身体数据:

     
      
  1. 获取对框架的引用
  2.   
  3. 检查正文框架是否为空 - 这是至关重要的
  4.   
  5. 初始化_bodies列表
  6.   
  7. 调用GetAndRefreshBodyData方法,以便将正文数据复制到列表中
  8.   
  9. 遍历尸体列表并做一些很棒的东西!
  10.         

    始终记得检查空值。 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 Blog - KINECT FOR WINDOWS VERSION 2: BODY TRACKING