将 Kinect 的 v2.0 运动存储到 BVH 文件
Store Kinect's v2.0 Motion to BVH File
我想将来自 Kinect 2 的动作捕捉数据存储为 BVH 文件。我找到了可以在 here 中找到的适用于 Kinect 1 的代码。我浏览了代码,发现了一些我无法理解的地方。
例如,在提到的代码中,我试图了解代码中多处发现的 Skeleton skel
object 到底是什么。如果没有,是否有任何已知的应用程序可用于实现预期目的?
编辑:我试图将 Skeleton skel 更改为 Body skel,我认为它是 kinect SDK 2.0 对应的 object。但是,当我尝试获取 body:
的位置时出现错误
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 objects:
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 文件使用关节信息通过读取 骷髅.
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 class 已被 Body class,所以你需要将其更改为处理 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:
_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:
- Get a reference to the body frame
- Check whether the body frame is null – this is crucial
- Initialize the _bodies list
- Call the GetAndRefreshBodyData method, so as to copy the body data into the list
- 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:
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.
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...
}
}
来源:Vangos Pterneas Blog - KINECT FOR WINDOWS VERSION 2: BODY TRACKING
我想将来自 Kinect 2 的动作捕捉数据存储为 BVH 文件。我找到了可以在 here 中找到的适用于 Kinect 1 的代码。我浏览了代码,发现了一些我无法理解的地方。
例如,在提到的代码中,我试图了解代码中多处发现的 Skeleton skel
object 到底是什么。如果没有,是否有任何已知的应用程序可用于实现预期目的?
编辑:我试图将 Skeleton skel 更改为 Body skel,我认为它是 kinect SDK 2.0 对应的 object。但是,当我尝试获取 body:
的位置时出现错误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 objects:
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 文件使用关节信息通过读取 骷髅.
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 class 已被 Body class,所以你需要将其更改为处理 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:
_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:
- Get a reference to the body frame
- Check whether the body frame is null – this is crucial
- Initialize the _bodies list
- Call the GetAndRefreshBodyData method, so as to copy the body data into the list
- 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:
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.
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... } }
来源:Vangos Pterneas Blog - KINECT FOR WINDOWS VERSION 2: BODY TRACKING