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

Jos*_*mon 297 c# motion-detection kinect

我想将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);
Run Code Online (Sandbox Code Playgroud)

调用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);
Run Code Online (Sandbox Code Playgroud)

编辑:基本上我设法在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);
Run Code Online (Sandbox Code Playgroud)

我无法理解代码内部的the axis for every Joint计算位置.

Kha*_*d.K 2

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

\n\n
public static double[] getBoneVectorOutofJointPosition(BVHBone bvhBone, Skeleton skel)\n{\n    double[] boneVector = new double[3] { 0, 0, 0 };\n    double[] boneVectorParent = new double[3] { 0, 0, 0 };\n    string boneName = bvhBone.Name;\n\n    JointType Joint;\n    if (bvhBone.Root == true)\n    {\n        boneVector = new double[3] { 0, 0, 0 };\n    }\n    else\n    {\n        if (bvhBone.IsKinectJoint == true)\n        {\n            Joint = KinectSkeletonBVH.String2JointType(boneName);\n\n            boneVector[0] = skel.Joints[Joint].Position.X;\n            boneVector[1] = skel.Joints[Joint].Position.Y;\n            boneVector[2] = skel.Joints[Joint].Position.Z;\n..\n
Run Code Online (Sandbox Code Playgroud)\n\n

来源:Nguy\xc3\xaan L\xc3\xaa\xc4\x90\xe1\xba\xb7ng - Kinect2BVH.V2

\n\n

除Kinect 2.0外,Skeleton类已被Body类取代,因此您需要将其更改为处理Body,并按照下面引用的步骤获取关节。

\n\n
\n
// Kinect namespace\nusing Microsoft.Kinect;\n\n// ...\n\n// Kinect sensor and Kinect stream reader objects\nKinectSensor _sensor;\nMultiSourceFrameReader _reader;\nIList<Body> _bodies;\n\n// Kinect sensor initialization\n_sensor = KinectSensor.GetDefault();\n\nif (_sensor != null)\n{\n    _sensor.Open();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们还添加了一个身体列表,其中将保存所有与身体/骨骼相关的数据。如果您是针对 Kinect 版本 1 进行开发的,您\n 会注意到 Skeleton 类已被 Body 类取代。\n 还记得 MultiSourceFrameReader 吗?这个类让我们可以访问每个流,包括主体流!我们只需在初始化读取器时添加一个附加参数,让传感器知道我们需要人体跟踪功能:

\n\n
_reader = _sensor.OpenMultiSourceFrameReader(FrameSourceTypes.Color |\n                                             FrameSourceTypes.Depth |\n                                             FrameSourceTypes.Infrared |\n                                             FrameSourceTypes.Body);\n\n_reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;\n
Run Code Online (Sandbox Code Playgroud)\n\n

只要有新帧可用,就会调用 Reader_MultiSourceFrameArrived 方法。让\xe2\x80\x99s 指定主体数据会发生什么:

\n\n
    \n
  1. 获取身体框架的参考
  2. \n
  3. 检查主体框架是否为空 \xe2\x80\x93 这很关键
  4. \n
  5. 初始化_body列表
  6. \n
  7. 调用GetAndRefreshBodyData方法,将body数据复制到列表中
  8. \n
  9. 循环浏览尸体列表并做一些很棒的事情!
  10. \n
\n\n

始终记住检查空值。Kinect 为您提供\n 大约每秒 30 帧\xe2\x80\x93 任何内容都可能为空或\n 丢失!这是到目前为止的代码:

\n\n
void Reader_MultiSourceFrameArrived(object sender,\n            MultiSourceFrameArrivedEventArgs e)\n{\n    var reference = e.FrameReference.AcquireFrame();\n\n    // Color\n    // ...\n\n    // Depth\n    // ...\n\n    // Infrared\n    // ...\n\n    // Body\n    using (var frame = reference.BodyFrameReference.AcquireFrame())\n    {\n        if (frame != null)\n        {\n            _bodies = new Body[frame.BodyFrameSource.BodyCount];\n\n            frame.GetAndRefreshBodyData(_bodies);\n\n            foreach (var body in _bodies)\n            {\n                if (body != null)\n                {\n                    // Do something with the body...\n                }\n            }\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

就是这个!我们现在可以访问 Kinect 识别的身体。下一步是在屏幕上显示骨架信息。每个身体由 25 个关节组成。传感器为我们提供位置(X、Y、\n Z)和每个位置的旋转信息。此外,Kinect 让我们知道关节是否被跟踪、假设或未被跟踪。在执行任何关键功能之前检查身体是否被跟踪是一个很好的做法。

\n\n

下面的代码说明了我们如何访问不同的身体关节:

\n\n
if (body != null)\n{\n    if (body.IsTracked)\n    {\n        Joint head = body.Joints[JointType.Head];\n\n        float x = head.Position.X;\n        float y = head.Position.Y;\n        float z = head.Position.Z;\n\n        // Draw the joints...\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

来源:Vangos Pterneas 博客 - KINECT FOR WINDOWS 版本 2:身体跟踪

\n