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

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

编辑:我试图改变骨架skel身体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); 

调用正文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在哪里计算。

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

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

我们还添加了一个body的列表,所有body / skeleton相关的数据将被保存。 如果您已经开发了Kinect版本1,则会注意到Skeleton类已被Body类取代。 记住MultiSourceFrameReader? 这个课程让我们能够访问每一个stream,包括身体stream! 我们只需要让传感器在初始化阅读器时通过添加一个附加参数来知道我们需要身体跟踪function:

 _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让我们知道关节是否跟踪,hypothsized或不跟踪。 在执行任何关键function之前,检查一个主体是否被跟踪是一个很好的做法。

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

 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第二版 : 身体追踪