通过Kinect获取到关节的三维坐标点后可以根据向量点积或叉积公式计算出关节角度:

$$\vec{a}\cdot \vec{b} = |\vec{a}||\vec{b}|cos\theta$$

vector1.Normalize();
vector2.Normalize();
double cosinus = DotProduct(vector1, vector2); double angle = (Math.Acos(cosinus) * (180.0 / Math.PI));

  在DirectXMath数学库中也有现成的计算向量夹角的函数XMVector3AngleBetweenVectors

XMVECTOR  XMVector3AngleBetweenVectors( XMVECTOR V1, XMVECTOR V2 ); //返回向量V1、V2间的夹角[angle, angle,angle, angle],单位为弧度

  下面的部分代码将获取到的骨骼数据进行平滑,然后计算出关节角度:

/// Handle new body data
void CBodyBasics::ProcessBody(IBody* pBody)
{
HRESULT hr;
BOOLEAN bTracked = false;
hr = pBody->get_IsTracked(&bTracked); // Retrieves a boolean value that indicates if the body is tracked if (SUCCEEDED(hr) && bTracked) // 判断是否追踪到骨骼
{
Joint joints[JointType_Count];
HandState leftHandState = HandState_Unknown;
HandState rightHandState = HandState_Unknown; DepthSpacePoint *depthSpacePosition = new DepthSpacePoint[_countof(joints)]; // 存储深度坐标系中的关节点位置 pBody->get_HandLeftState(&leftHandState); // 获取左右手状态
pBody->get_HandRightState(&rightHandState); hr = pBody->GetJoints(_countof(joints), joints); // 获得25个关节点
if (SUCCEEDED(hr))
{
// Filtered Joint
filter.Update(joints);
const DirectX::XMVECTOR* vec = filter.GetFilteredJoints(); // Retrive Filtered Joints float angle = Angle(vec, JointType_WristRight, JointType_ElbowRight, JointType_ShoulderRight); // Get ElbowRight joint angle
char s[];
sprintf_s(s, "%.0f", angle);
std::string strAngleInfo = s;
putText(skeletonImg, strAngleInfo, cvPoint(, ), CV_FONT_HERSHEY_COMPLEX, 0.5, cvScalar(, , )); // 屏幕上显示角度信息 for (int type = ; type < JointType_Count; type++)
{
if (joints[type].TrackingState != TrackingState::TrackingState_NotTracked)
{
float x = 0.0f, y = 0.0f, z = 0.0f;
// Retrieve the x/y/z component of an XMVECTOR Data and storing that component's value in an instance of float referred to by a pointer
DirectX::XMVectorGetXPtr(&x, vec[type]);
DirectX::XMVectorGetYPtr(&y, vec[type]);
DirectX::XMVectorGetZPtr(&z, vec[type]); CameraSpacePoint cameraSpacePoint = { x, y, z };
m_pCoordinateMapper->MapCameraPointToDepthSpace(cameraSpacePoint, &depthSpacePosition[type]); //将关节点坐标从摄像机坐标系转到深度坐标系以显示
}
} DrawBody(joints, depthSpacePosition);
DrawHandState(depthSpacePosition[JointType_HandLeft], leftHandState);
DrawHandState(depthSpacePosition[JointType_HandRight], rightHandState);
} delete[] depthSpacePosition;
} cv::imshow("skeletonImg", skeletonImg);
cv::waitKey(); // 延时5ms
} FLOAT CBodyBasics::Angle(const DirectX::XMVECTOR* vec, JointType jointA, JointType jointB, JointType jointC)
{
float angle = 0.0; XMVECTOR vBA = XMVectorSubtract(vec[jointB], vec[jointA]);
XMVECTOR vBC = XMVectorSubtract(vec[jointB], vec[jointC]); XMVECTOR vAngle = XMVector3AngleBetweenVectors(vBA, vBC); angle = XMVectorGetX(vAngle) * 180.0 * XM_1DIVPI; // XM_1DIVPI: An optimal representation of 1 / π return angle;
}

  国外有个公司vitruvius已经将关节角度获取、背景去除、手势识别、Avateering等功能做的简单易用,可以在其网站上下载免费的版本试用:

参考:

https://vitruviuskinect.com/

DirectXMath Library 3D Vector Geometric Functions

Using the Kinect Sensor to Calculate Body Segment Angles

Find the angle between two line segments

LightBuzz.Vitruvius/Core/Vector3.cs

How to select the users to track in C++

【D3D11游戏编程】学习笔记二:XNAMath之XMVECTOR

Kinect2.0关节角度获取的更多相关文章

  1. 使用Kinect2.0获取点云以在GLUT中显示

    这篇文章用来记录Kinect2.0如何生成点云. 以下示例源自Kinect提供的example修改完成,其名称会在小标题下方注解. 首先,要获取点云需要获取图像的深度数据和颜色数据.最后再将深度数据与 ...

  2. Kinect2.0获取数据

    最近事情真是多,今天抽空研究一下Kinec2.0的数据获取! 系统要求 https://developer.microsoft.com/en-us/windows/kinect/hardware-se ...

  3. 使用Kinect2.0控制VREP中的虚拟模型

    VREP中直接设置物体姿态的函数有3个: simSetObjectOrientation:通过欧拉角设置姿态 simSetObjectQuaternion:通过四元数设置姿态 simSetObject ...

  4. Kinect2.0骨骼跟踪与数据平滑

    Kinect v1和Kinect v2传感器的配置比较:   Kinect v1 Kinect v2           颜色(Color) 分辨率(Resolution) 640×480 1920× ...

  5. Kinect2.0点云数据获取

    接上一篇:Kinect2.0获取数据 http://blog.csdn.net/jiaojialulu/article/details/53087988 博主好细心,代码基本上帖过来就可以用,注释掉的 ...

  6. Swift3.0语言教程获取字符串编码与哈希地址

    Swift3.0语言教程获取字符串编码与哈希地址 Swift3.0语言教程获取字符串编码与哈希地址,以下将讲解字符串中其它内容的获取方法. 1.获取字符串编码 在NSString中可以使用2个属性获取 ...

  7. Swift3.0语言教程获取C字符串

    Swift3.0语言教程获取C字符串 Swift3.0语言教程获取C字符串,为了让Swift和C语言可以实现很好的交互,开发者可以使用NSString的cString(using:)方法在指定编码格式 ...

  8. Swift3.0语言教程获取字符

    Swift3.0语言教程获取字符 Swift3.0语言教程获取字符,在字符串中获取某一下标位置(下标索引)处的字符是很常见的功能,在NSString中使用character(at:)方法实现,其语法形 ...

  9. Swift3.0语言教程获取字符串长度

    Swift3.0语言教程获取字符串长度 Swift3.0语言教程获取字符串长度,当在一个字符串中存在很多的字符时,如果想要计算字符串的长度时相当麻烦的一件事情,在NSString中可以使用length ...

随机推荐

  1. [转] OpenStack IPSec VPNaaS

    OpenStack IPSec VPNaaS ( by quqi99 ) 作者:张华  发表于:2013-08-03版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声 ...

  2. ThinkPHP错误信息处理

    index.php入口文件中打开APP_DEBUG// 开启调试模式define('APP_DEBUG', TRUE); // 开启Trace信息 'SHOW_PAGE_TRACE' =>tru ...

  3. Android studio 编译失败Error:Could not read entry &#39;:app:processDebugManifest&#39; from cache taskArtifacts.b

    Android studio 编译失败 Error:Could not read entry ':app:processDebugManifest' from cache taskArtifacts. ...

  4. FastReport.Net 入门

    任何一门编程技术入门体验都是以“Hello World”开始的,但我想再复杂一点的“Hello World”,才能算真正的入门.   FastReport.Net V1.2.76 ,vs2008 在 ...

  5. 已知(x,y,z,yaw,pitch,roll)如何得到4*4的转换矩阵?

    作者:Nicholas链接:https://www.zhihu.com/question/41514206/answer/104827395来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商 ...

  6. Java-JUC(六):创建线程的4种方式

    Java创建线程的4种方式: Java使用Thread类代表线程,所有线程对象都必须是Thread类或者其子类的实例.Java可以用以下4种方式来创建线程: 1)继承Thread类创建线程: 2)实现 ...

  7. VS2008 解决Unable to copy file 对路径的访问被拒绝。

    在VS2008 + WINDOWS 7 环境下重新生成解决方案时遇到以下问题 Unable to delete file "F:\XX.exe". 对路径"F:\XX.e ...

  8. sqrt函数的实现

    原文:http://blog.csdn.net/legend050709/article/details/39394381 sqrt算法实现: (一)int sqrt1(int n);求取整数x的平方 ...

  9. Pandas DataFrame笔记

    1.属性方式,可以用于列,不能用于行 2.可以用整数切片选择行,但不能用单个整数索引(当索引不是整数时) 3.直接索引可以使用列.列集合,但不能用索引名索引行 用iloc取行,得到的series: d ...

  10. 红米除线刷的另外一种救砖方法fastboot

    原文来自:https://jingyan.baidu.com/article/48a42057e945bca9242504d7.html , 按照它操做了一下,虽然没有救活我的红米1,但是让我更好的了 ...