Kinect 关节旋转——终极指南
如何测量每个轴 (X、Y、Z) 周围关节的方向
引言
在我之前的博文中,我向你展示了如何使用Kinect和C#测量关节角度。今天,我们将深入探讨一个更复杂的话题:在这篇文章中,你将学习如何测量每个轴 (X, Y, Z
) 周围关节的方向。
测量方向值并非易事,因为它需要一些良好的数学知识。但是,不要害怕!阅读本文后,你将能够使用一行C#代码计算每个关节的方向!
听起来不错?让我们开始吧。
必备组件
要运行本指南中提供的代码和示例,你需要以下内容
- Xbox v2版Kinect传感器 配备 适配器(或 Windows v2版Kinect传感器)
- Kinect for Windows v2 SDK
- Windows 8.1 或更高版本
- Visual Studio 2013 或更高版本
- 一个专用的USB 3.0端口
让我们来算算……
Kinect 读取关节方向值作为四元数。四元数是一组4个值:X
、Y
、Z
和W
。
Kinect SDK 将四元数封装到名为Vector4
的结构中。我们需要将此四元数 (Vector4
) 转换为一组3个数值。
使用方向四元数,我们可以计算关节围绕X
、Y
和Z
轴的旋转。
俯仰角:绕X轴旋转
绕X
轴的旋转称为俯仰角
。以下是测量方法
public static double Pitch(this Vector4 quaternion)
{
double value1 = 2.0 * (quaternion.W * quaternion.X + quaternion.Y * quaternion.Z);
double value2 = 1.0 - 2.0 * (quaternion.X * quaternion.X + quaternion.Y * quaternion.Y);
double roll = Math.Atan2(value1, value2);
return roll * (180.0 / Math.PI);
}
偏航角:绕Y轴旋转
绕Y
轴的旋转称为偏航角
。以下是测量方法
public static double Yaw(this Vector4 quaternion)
{
double value = 2.0 * (quaternion.W * quaternion.Y - quaternion.Z * quaternion.X);
value = value > 1.0 ? 1.0 : value;
value = value < -1.0 ? -1.0 : value;
double pitch = Math.Asin(value);
return pitch * (180.0 / Math.PI);
}
滚转角:绕Z轴旋转
绕Z
轴的旋转称为滚转角
。以下是测量方法
public static double Roll(this Vector4 quaternion)
{
double value1 = 2.0 * (quaternion.W * quaternion.Z + quaternion.X * quaternion.Y);
double value2 = 1.0 - 2.0 * (quaternion.Y * quaternion.Y + quaternion.Z * quaternion.Z);
double yaw = Math.Atan2(value1, value2);
return yaw * (180.0 / Math.PI);
}
Using the Code
这是完整的代码。你只需将以下C#文件导入你的Kinect项目。
using System;
using Microsoft.Kinect;
namespace LightBuzz.Vitruvius
{
/// <summary>
/// Provides extension methods for transforming quaternions to rotations.
/// </summary>
public static class JointOrientationExtensions
{
/// <summary>
/// Rotates the specified quaternion around the X axis.
/// </summary>
/// <param name="quaternion">The orientation quaternion.</param>
/// <returns>The rotation in degrees.</returns>
public static double Pitch(this Vector4 quaternion)
{
double value1 = 2.0 * (quaternion.W * quaternion.X + quaternion.Y * quaternion.Z);
double value2 = 1.0 - 2.0 * (quaternion.X * quaternion.X + quaternion.Y * quaternion.Y);
double roll = Math.Atan2(value1, value2);
return roll * (180.0 / Math.PI);
}
/// <summary>
/// Rotates the specified quaternion around the Y axis.
/// </summary>
/// <param name="quaternion">The orientation quaternion.</param>
/// <returns>The rotation in degrees.</returns>
public static double Yaw(this Vector4 quaternion)
{
double value = 2.0 * (quaternion.W * quaternion.Y - quaternion.Z * quaternion.X);
value = value > 1.0 ? 1.0 : value;
value = value < -1.0 ? -1.0 : value;
double pitch = Math.Asin(value);
return pitch * (180.0 / Math.PI);
}
/// <summary>
/// Rotates the specified quaternion around the Z axis.
/// </summary>
/// <param name="quaternion">The orientation quaternion.</param>
/// <returns>The rotation in degrees.</returns>
public static double Roll(this Vector4 quaternion)
{
double value1 = 2.0 * (quaternion.W * quaternion.Z + quaternion.X * quaternion.Y);
double value2 = 1.0 - 2.0 * (quaternion.Y * quaternion.Y + quaternion.Z * quaternion.Z);
double yaw = Math.Atan2(value1, value2);
return yaw * (180.0 / Math.PI);
}
}
}
然后,在你的主C#文件中,导入以下命名空间
using LightBuzz.Vitruvius;
最后,指定要测量方向的关节并调用Roll
、Pitch
和Yaw
方法
var orientation = body.JointOrientations[JointType.ElbowLeft].Orientation;
var rotationX = orientation.Pitch();
var rotationY = orientation.Yaw();
var rotationZ = orientation.Roll();
支持的关节
测量人体关节的旋转并非易事。不幸的是,Kinect 并没有为头部
、双手
和双脚
提供方向值。这些关节没有“父”关节,因此很难准确测量它们的方向。关于其余关节的方向精度相当好。支持的关节如下:
弦颈
SpineShoulder(脊椎肩部)
SpineBase(脊椎底部)
ShoulderLeft
/ShoulderRight
(左肩/右肩)ElbowLeft
/ElbowRight
(左肘/右肘)WristLeft
/WristRight
(左腕/右腕)HipLeft
/HipRight
(左髋/右髋)KneeLeft
/KneeRight
(左膝/右膝)
本文中描述的方法将帮助你应对大多数用例场景,例如简单的游戏。如果你需要更高的精度(例如医疗保健应用程序),则需要使用更复杂的算法,这涉及大量自定义编码。LightBuzz 在此类算法方面拥有丰富的经验,可以帮助你完成项目。
摘要
在这篇博文中,你学习了如何轻松地测量人体关节围绕X
、Y
和Z
轴的旋转。