65.9K
CodeProject 正在变化。 阅读更多。
Home

Kinect 关节旋转——终极指南

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2019 年 1 月 28 日

CPOL

2分钟阅读

viewsIcon

9450

如何测量每个轴 (X、Y、Z) 周围关节的方向

引言

在我之前的博文中,我向你展示了如何使用Kinect和C#测量关节角度。今天,我们将深入探讨一个更复杂的话题:在这篇文章中,你将学习如何测量每个轴 (X, Y, Z) 周围关节的方向。

测量方向值并非易事,因为它需要一些良好的数学知识。但是,不要害怕!阅读本文后,你将能够使用一行C#代码计算每个关节的方向!

听起来不错?让我们开始吧。

必备组件

要运行本指南中提供的代码和示例,你需要以下内容

让我们来算算……

Kinect 读取关节方向值作为四元数。四元数是一组4个值:XYZW

Kinect SDK 将四元数封装到名为Vector4的结构中。我们需要将此四元数 (Vector4) 转换为一组3个数值。

使用方向四元数,我们可以计算关节围绕XYZ轴的旋转。

俯仰角:绕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;

最后,指定要测量方向的关节并调用RollPitchYaw方法

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 在此类算法方面拥有丰富的经验,可以帮助你完成项目。

摘要

在这篇博文中,你学习了如何轻松地测量人体关节围绕XYZ轴的旋转。

© . All rights reserved.