I would like to store the motion capture data from Kinect 2 as a BVH file. I found code which does so for Kinect 1 which can be found here. I went through the code and found several things that I was not able to understand. For example, in the mentioned code I've tried to understand what exactly the Skeleton skel
object, found in several places in the code, actually is. If not, are there any known application available to accomplish the intended?
我想将Kinect 2的动作捕捉数据存储为BVH文件。我找到了Kinect 1的代码可以在这里找到。我检查了代码,发现了一些我无法理解的东西。例如,在上面提到的代码中,我试图理解在代码中的几个地方找到的Skeleton skel对象实际上是什么。如果没有,是否有任何已知的应用程序可用来完成目标?
EDIT: I tried to change Skeleton skel to Body skel which I think is the correspondant object for kinect SDK 2.0. However I've got an error when I try to get the position of the body:
编辑:我尝试将骨架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);
I've gotten errors when calling the function Position for the Body skel. How can I retrieve the X, Y, Z of the skeleton in sdk 2.0?? I tried to change the above three lines to:
我在调用Body skel的函数位置时出错。如何在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);
EDIT: Basically I managed to store the a bvh file after combining bodyBasicsWPF and kinect2bvh. However, it seems that the skeleton I am storing is not efficient. There are strange movements in the elbows. I am trying to understand if I have to change something in the file kinectSkeletonBVH.cp. More specifically, what are the changes in the joint axis orientation for the kinect 2 version. How can I change the following line: skel.BoneOrientations[JointType.ShoulderCenter].AbsoluteRotation.Quaternion;
I tried to change that line with skel.JointOrientations[JointType.ShoulderCenter].Orientation
. Am I right? I am using the following code to add the joint to BVHBone objects:
编辑:在结合bodyBasicsWPF和kinect2bvh之后,基本上我成功地存储了a bvh文件。然而,似乎我所存储的骨架并不是有效的。肘部有奇怪的运动。我正在尝试理解是否我必须在kinectskeleton onbv .cp文件中修改一些东西。更具体地说,kinect 2的关节轴方向的变化是什么?我如何能改变下面的一行:skel.boneori[JointType.ShoulderCenter]. absoluterot.quaternion;我试着用“骨架”(skelttype . shouldercenter)。我说的对吗?我使用以下代码将关节添加到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);
I can't understand where inside the code the axis for every Joint
is calculated.
我不明白代码里面每个关节的轴是怎么计算的。
1 个解决方案
#1
1
The code you used for Kinect 1.0 to obtain a BVH file use the joints information to build bone vectors by reading the Skeleton.
使用Kinect 1.0获取BVH文件的代码使用关节信息通过读取骨架来构建骨向量。
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;
..
Source: Nguyên Lê Đặng - Kinect2BVH.V2
来源:阮黎Đặng——Kinect2BVH.V2
Except in Kinect 2.0, Skeleton class has been replaced by the Body class, so you need to change it to deal with a Body instead, and obtain the joints by following the steps quoted below.
除了在Kinect 2.0中,骨架类已经被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(); }
We also added a list of bodies, where all of the body/skeleton related data will be saved. If you have developed for Kinect version 1, you notice that the Skeleton class has been replaced by the Body class. Remember the MultiSourceFrameReader? This class gives us access on every stream, including the body stream! We simply need to let the sensor know that we need body tracking functionality by adding an additional parameter when initializing the reader:
我们还增加了一个身体列表,其中所有的身体/骨骼相关数据都将被保存。如果您已经为Kinect版本1开发过,您会注意到框架类已经被Body类所取代。还记得MultiSourceFrameReader吗?这个类允许我们访问每个流,包括主体流!我们只需要让传感器知道,我们需要在初始化阅读器时添加一个额外的参数:
_reader = _sensor.OpenMultiSourceFrameReader(FrameSourceTypes.Color | FrameSourceTypes.Depth | FrameSourceTypes.Infrared | FrameSourceTypes.Body); _reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;
The Reader_MultiSourceFrameArrived method will be called whenever a new frame is available. Let’s specify what will happen in terms of the body data:
只要有新的帧可用,就会调用Reader_MultiSourceFrameArrived方法。让我们具体说明将会发生什么关于身体数据:
- Get a reference to the body frame
- 获取对主体框架的引用
- Check whether the body frame is null – this is crucial
- 检查主体框架是否为空——这一点至关重要
- Initialize the _bodies list
- 初始化_bodies列表
- Call the GetAndRefreshBodyData method, so as to copy the body data into the list
- 调用GetAndRefreshBodyData方法,以便将body数据复制到列表中
- Loop through the list of bodies and do awesome stuff!
- 环视身体清单,做一些很棒的事情!
Always remember to check for null values. Kinect provides you with approximately 30 frames per second – anything could be null or missing! Here is the code so far:
记住要检查空值。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... } } } } }
This is it! We now have access to the bodies Kinect identifies. Next step is to display the skeleton information on-screen. Each body consists of 25 joints. The sensor provides us with the position (X, Y, Z) and the rotation information for each one of them. Moreover, Kinect lets us know whether the joints are tracked, hypothsized or not tracked. It’s a good practice to check whether a body is tracked before performing any critical functions.
这是它!我们现在可以进入Kinect识别的身体。下一步是显示屏幕上的骨架信息。每个身体由25个关节组成。传感器提供给我们的位置(X, Y, Z)和每一个的旋转信息。此外,Kinect让我们知道关节是否被跟踪、被缩小还是没有被跟踪。在执行任何关键功能之前,检查身体是否被跟踪是一个很好的实践。
The following code illustrates how we can access the different body joints:
下面的代码演示了我们如何访问不同的身体关节:
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... } }
Source: Vangos Pterneas Blog - KINECT FOR WINDOWS VERSION 2: BODY TRACKING
资料来源:Vangos Pterneas博客- KINECT版本2:身体追踪
#1
1
The code you used for Kinect 1.0 to obtain a BVH file use the joints information to build bone vectors by reading the Skeleton.
使用Kinect 1.0获取BVH文件的代码使用关节信息通过读取骨架来构建骨向量。
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;
..
Source: Nguyên Lê Đặng - Kinect2BVH.V2
来源:阮黎Đặng——Kinect2BVH.V2
Except in Kinect 2.0, Skeleton class has been replaced by the Body class, so you need to change it to deal with a Body instead, and obtain the joints by following the steps quoted below.
除了在Kinect 2.0中,骨架类已经被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(); }
We also added a list of bodies, where all of the body/skeleton related data will be saved. If you have developed for Kinect version 1, you notice that the Skeleton class has been replaced by the Body class. Remember the MultiSourceFrameReader? This class gives us access on every stream, including the body stream! We simply need to let the sensor know that we need body tracking functionality by adding an additional parameter when initializing the reader:
我们还增加了一个身体列表,其中所有的身体/骨骼相关数据都将被保存。如果您已经为Kinect版本1开发过,您会注意到框架类已经被Body类所取代。还记得MultiSourceFrameReader吗?这个类允许我们访问每个流,包括主体流!我们只需要让传感器知道,我们需要在初始化阅读器时添加一个额外的参数:
_reader = _sensor.OpenMultiSourceFrameReader(FrameSourceTypes.Color | FrameSourceTypes.Depth | FrameSourceTypes.Infrared | FrameSourceTypes.Body); _reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;
The Reader_MultiSourceFrameArrived method will be called whenever a new frame is available. Let’s specify what will happen in terms of the body data:
只要有新的帧可用,就会调用Reader_MultiSourceFrameArrived方法。让我们具体说明将会发生什么关于身体数据:
- Get a reference to the body frame
- 获取对主体框架的引用
- Check whether the body frame is null – this is crucial
- 检查主体框架是否为空——这一点至关重要
- Initialize the _bodies list
- 初始化_bodies列表
- Call the GetAndRefreshBodyData method, so as to copy the body data into the list
- 调用GetAndRefreshBodyData方法,以便将body数据复制到列表中
- Loop through the list of bodies and do awesome stuff!
- 环视身体清单,做一些很棒的事情!
Always remember to check for null values. Kinect provides you with approximately 30 frames per second – anything could be null or missing! Here is the code so far:
记住要检查空值。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... } } } } }
This is it! We now have access to the bodies Kinect identifies. Next step is to display the skeleton information on-screen. Each body consists of 25 joints. The sensor provides us with the position (X, Y, Z) and the rotation information for each one of them. Moreover, Kinect lets us know whether the joints are tracked, hypothsized or not tracked. It’s a good practice to check whether a body is tracked before performing any critical functions.
这是它!我们现在可以进入Kinect识别的身体。下一步是显示屏幕上的骨架信息。每个身体由25个关节组成。传感器提供给我们的位置(X, Y, Z)和每一个的旋转信息。此外,Kinect让我们知道关节是否被跟踪、被缩小还是没有被跟踪。在执行任何关键功能之前,检查身体是否被跟踪是一个很好的实践。
The following code illustrates how we can access the different body joints:
下面的代码演示了我们如何访问不同的身体关节:
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... } }
Source: Vangos Pterneas Blog - KINECT FOR WINDOWS VERSION 2: BODY TRACKING
资料来源:Vangos Pterneas博客- KINECT版本2:身体追踪