Kinect2.0获取关节姿态(Joint Orientation)
- Bones Hierarchy
骨骼层次结构从SpineBase作为根节点开始,一直延伸到肢体末端(头、指尖、脚):

层级结构如下图所示:

通过IBody::GetJointOrientations函数可以获取到关节的姿态:
HRESULT = pBody -> GetJointOrientations(_countof(joints), jointOrientations);
关节姿态是一个结构体,其中包含了代表姿态的四元数部分:
typedef struct _JointOrientation {
JointType JointType;
Vector4 Orientation; // quaternion
} JointOrientation;
这里要搞清楚很关键的一点就是姿态是相对于哪个坐标系来描述的以及坐标系是如何定义的。网上说法不一(根本就找不到一个官方的解释...),MSDN论坛上有些人说是相对于父节点来描述的,那样的话要获得某一节点的绝对姿态必须遍历骨骼层次结构直到根节点,并将遍历路径上的旋转矩阵(四元数)相乘,以获得相对于固定坐标系的姿态矩阵. To calculate the absolute orientation of each bone, multiply the rotation matrix of the bone by the rotation matrices of the parents (up to the root joint). 不过也有讨论说这个姿态就是摄像机坐标下的,而不是相对于父节点的。如果是这样的话就省去了很多中间计算步骤。下面进行测试来看看关节姿态到底是怎么描述的:
1. 末端节点(Head、HandTip、Thumb、Feet)不含有姿态信息,这些关节返回的四元数各分量都为0:

2. 所有的关节姿态描述都以摄像机坐标系为参考,当人体站正朝向Kinect时SpineBase关节处的坐标系如下图所示。此时返回的关节四元数理论上应为(w,x,y,z)=(0,0,1,0),对应的Z-Y-X欧拉角为(180°,0,180°)或(0,180°,0)

站正后进行测试,输出SpineBase关节的四元数,可以看出与理论结果很接近:

下面我保持身体竖直,绕着从头顶到脚底的轴线(Y轴)旋转一定角度,将SpineBase关节的姿态四元数转换成欧拉角并记录在CSV文件中。下图是根据原始数据绘制的曲线图,可以看出我在绕Y轴旋转身体时X轴和Z轴角度是没有太大变化的(由于Kinect精度所限和各种噪声干扰也不可能一直是180°),而Y轴角度数据有明显的线性增长趋势,对应了我身体的匀速转动:

3. 关节坐标系的Y轴沿着骨骼的方向,Z轴为骨骼转动轴( Z-axis points to the direction that makes sense for the joint to rotate),X轴与Y轴和Z轴垂直,构成右手坐标系:
- Bone direction(Y green) - always matches the skeleton.
- Normal(Z blue) - joint roll, perpendicular to the bone
- Binormal(X red) - perpendicular to the bone and norma
比如对于肘关节和膝关节来说,只有一个转动自由度,因此Z轴(平行于冠状轴)朝向身体的两侧,关节带动骨骼绕着Z轴旋转,如下图所示:

当站正朝向kinect时,右肘关节的姿态四元数理论上应为(w,x,y,z)=(0, 0.707, 0, 0.707),下面是站正测试得到的实际值,可以看出还算比较接近:

另外也可以在Kinect Studio中的Monitor 3D View界面上进行设置来查看关节姿态信息:

关节箭头显示的方向就是法向,即旋转轴的指向:

可以看出肩关节和髋关节的Z轴都是指向身体前方。有了这些关节姿态信息我们就可以方便的控制虚拟人物或者实体机器人(当然得到每个关节的三位坐标点然后计算关节夹角也可以)。
参考:
Adventures in Motion Capture: Using Kinect Data (Part 1)
Adventures in Motion Capture: Using Kinect Data (Part 2)
Adventures in Motion Capture: Using Kinect Data (Part 3)
How to interpret JointOrientation data
Meaning of Rotation Data of K4W v2
Kinect2.0获取关节姿态(Joint Orientation)的更多相关文章
- 使用Kinect2.0获取点云以在GLUT中显示
这篇文章用来记录Kinect2.0如何生成点云. 以下示例源自Kinect提供的example修改完成,其名称会在小标题下方注解. 首先,要获取点云需要获取图像的深度数据和颜色数据.最后再将深度数据与 ...
- Kinect2.0获取数据
最近事情真是多,今天抽空研究一下Kinec2.0的数据获取! 系统要求 https://developer.microsoft.com/en-us/windows/kinect/hardware-se ...
- 使用Kinect2.0控制VREP中的虚拟模型
VREP中直接设置物体姿态的函数有3个: simSetObjectOrientation:通过欧拉角设置姿态 simSetObjectQuaternion:通过四元数设置姿态 simSetObject ...
- Kinect2.0点云数据获取
接上一篇:Kinect2.0获取数据 http://blog.csdn.net/jiaojialulu/article/details/53087988 博主好细心,代码基本上帖过来就可以用,注释掉的 ...
- Kinect2.0骨骼跟踪与数据平滑
Kinect v1和Kinect v2传感器的配置比较: Kinect v1 Kinect v2 颜色(Color) 分辨率(Resolution) 640×480 1920× ...
- C#微信公众号开发-高级接口-之网页授权oauth2.0获取用户基本信息(二)
C#微信公众号开发之网页授权oauth2.0获取用户基本信息(一) 中讲解了如果通过微信授权2.0snsapi_base获取已经关注用户的基本信息,然而很多情况下我们经常需要获取非关注用户的信息,方法 ...
- Ext4.0 获取选中行及遍历
var grid= Ext.getCmp('grid'); var records=grid.getSelectionModel().getSelection(); if(records!=null& ...
- 微信公众平台开发—利用OAuth2.0获取微信用户基本信息
在借鉴前两篇获取微信用户基本信息的基础下,本人也总结整理了一些个人笔记:如何通过OAuth2.0获取微信用户信息 1.首先在某微信平台下配置OAuth2.0授权回调页面: 2.通过appid构造url ...
- servlet3.0获取参数与文件上传代码示例
转: servlet3.0获取参数与文件上传代码示例 2018年08月26日 20:25:35 苏凯勇往直前 阅读数:98 package com.igeek.servlet; import ...
随机推荐
- 说说初用 Mock 工具测试碰到的坑
我是一个在校实习生,作为一个程序猿,是个菜鸟中战斗机!对于测试,只写过一点点简单到不能再简单了的 Junit 单元测试的例子(因为当时这足以应付学校课程的内容与要求).这几天在公司里要真枪实弹做测试的 ...
- webrequest HttpWebRequest webclient/HttpClient
webrequest(abstract类,不可直接用) <--- (继承)---- HttpWebRequest(更好的控制请求) <--- (继承)---- webclient (简单快 ...
- rank,dense_rank,row_number使用和区别
rank,dense_rank,row_number区别 一:语法(用法): rank() over([partition by col1] order by col2) dense ...
- Go语言之进阶篇简单版并发服务器
1.简单版并发服务器 示例1: package main import ( "fmt" "net" "strings" ) //处理用户请求 ...
- iOS开发调试篇—Print Description of "string"
Print Description of "string":把 string 的信息输出到控制台.Copy:复制 string 的信息,包含变量名,类名和值.View Value ...
- 查看LINQ Expression編譯後的SQL語法(转)
在用了LINQ語法之後的一個月,我幾乎把SQL語法全部拋到腦後了,不過 LINQ好用歸好用,但是實際上操作資料庫的還是SQL語法,如果不知道LINQ語法 編譯過後產生怎樣的SQL語法,一不小心效能就會 ...
- 绝对定位常见误区:position:absolute相对于谁定位、及当溢出时怎么隐藏
1.绝对定位元素溢出父元素,怎么隐藏问题? 通常,为了让DIV子元素超出部分隐藏,都是在父元素设置overflow:hidden,这样即可防止子元素撑开父元素,使子元素能够溢出隐藏! 但是,对于pos ...
- Android -- queryIntentActivities
某些时候你想要知道某个APP是否有注册了一个明确的intent,比如说你想要检查某个receiver是否存在,然后根据是否存在来这个receiver来在你的AP里面enable某些功能.我们可以通过P ...
- 个人知识点总结——Java并发
Java并发实在是一个非常深的问题,这里仅仅简单记录一下Java并发的知识点.水太深.假设不花大量的时间感觉全然hold不住,可是眼下的精力全然不够,兴趣也不在这 什么是线程安全性 某个类的行为和其规 ...
- esUtil.h中的m变量报错
引用了OpenGL ES自带的esUtil.h, 编译的时候报错: typedef struct { GLfloat m[4][4]; } ESMatrix; ...