将 Kinect 的 v2.0 运动存储到 BVH 文件
Posted
技术标签:
【中文标题】将 Kinect 的 v2.0 运动存储到 BVH 文件【英文标题】:Store Kinect's v2.0 Motion to BVH File 【发布时间】:2015-08-07 20:07:33 【问题描述】:我想将 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
是在哪里计算的。
【问题讨论】:
但是我跳过了这个问题 我能够为 txt 文件存储 Kinect v1 和 v2 信息。这个 BVH 文件是我刚刚阅读的内容,它将是我将添加到我们的采集软件中的一个功能。如果您对 *.txt 文件感兴趣,请告诉我。我还没有合适的 BVH 解决方案。 检查:pterneas.com/2014/03/13/… 我有办法将 Kinect v1 和 Kinect v2 流正确写入 txt。也许如果您使用它,您可以仔细检查您的 bvh 文件以进行相同的实验。查看我的简历了解更多信息。 @Khaled.K 如果你发布的链接回答了这个问题,你介意把它变成这个问题的答案吗(每个this meta question) 【参考方案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 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 方法将在任何时候被调用 新框架可用。让我们具体说明会发生什么 身体数据:
获取对主体框架的引用 检查body frame是否为null——这很关键 初始化 _bodies 列表 调用GetAndRefreshBodyData方法,将body数据复制到列表中 遍历身体列表并做一些很棒的事情!
永远记得检查空值。 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
【讨论】:
以上是关于将 Kinect 的 v2.0 运动存储到 BVH 文件的主要内容,如果未能解决你的问题,请参考以下文章