# 简介
在上一篇[《侦测、追踪人体骨架》](http://www.cnblogs.com/xz816111/p/5187424.html)里,介绍了关节点的使用办法,这一篇记录将关节点与`OpenCV`结合的绘图方法。


代码

#include <iostream>
#include <opencv2\imgproc.hpp>
#include <opencv2\calib3d.hpp>
#include <opencv2\highgui.hpp>
#include <Kinect.h> using namespace std;
using namespace cv; void draw(Mat & img, Joint & r_1, Joint & r_2, ICoordinateMapper * myMapper);
int main(void)
{
IKinectSensor * mySensor = nullptr;
GetDefaultKinectSensor(&mySensor);
mySensor->Open(); IColorFrameSource * myColorSource = nullptr;
mySensor->get_ColorFrameSource(&myColorSource); IColorFrameReader * myColorReader = nullptr;
myColorSource->OpenReader(&myColorReader); int colorHeight = 0, colorWidth = 0;
IFrameDescription * myDescription = nullptr;
myColorSource->get_FrameDescription(&myDescription);
myDescription->get_Height(&colorHeight);
myDescription->get_Width(&colorWidth); IColorFrame * myColorFrame = nullptr;
Mat original(colorHeight, colorWidth, CV_8UC4); //**********************以上为ColorFrame的读取前准备************************** IBodyFrameSource * myBodySource = nullptr;
mySensor->get_BodyFrameSource(&myBodySource); IBodyFrameReader * myBodyReader = nullptr;
myBodySource->OpenReader(&myBodyReader); int myBodyCount = 0;
myBodySource->get_BodyCount(&myBodyCount); IBodyFrame * myBodyFrame = nullptr; ICoordinateMapper * myMapper = nullptr;
mySensor->get_CoordinateMapper(&myMapper); //**********************以上为BodyFrame以及Mapper的准备***********************
while (1)
{ while (myColorReader->AcquireLatestFrame(&myColorFrame) != S_OK);
myColorFrame->CopyConvertedFrameDataToArray(colorHeight * colorWidth * 4, original.data, ColorImageFormat_Bgra);
Mat copy = original.clone(); //读取彩色图像并输出到矩阵 while (myBodyReader->AcquireLatestFrame(&myBodyFrame) != S_OK); //读取身体图像
IBody ** myBodyArr = new IBody *[myBodyCount]; //为存身体数据的数组做准备
for (int i = 0; i < myBodyCount; i++)
myBodyArr[i] = nullptr; if (myBodyFrame->GetAndRefreshBodyData(myBodyCount, myBodyArr) == S_OK) //把身体数据输入数组
for (int i = 0; i < myBodyCount; i++)
{
BOOLEAN result = false;
if (myBodyArr[i]->get_IsTracked(&result) == S_OK && result) //先判断是否侦测到
{
Joint myJointArr[JointType_Count];
if (myBodyArr[i]->GetJoints(JointType_Count, myJointArr) == S_OK) //如果侦测到就把关节数据输入到数组并画图
{
draw(copy, myJointArr[JointType_Head], myJointArr[JointType_Neck], myMapper);
draw(copy, myJointArr[JointType_Neck], myJointArr[JointType_SpineShoulder], myMapper); draw(copy, myJointArr[JointType_SpineShoulder], myJointArr[JointType_ShoulderLeft], myMapper);
draw(copy, myJointArr[JointType_SpineShoulder], myJointArr[JointType_SpineMid], myMapper);
draw(copy, myJointArr[JointType_SpineShoulder], myJointArr[JointType_ShoulderRight], myMapper); draw(copy, myJointArr[JointType_ShoulderLeft], myJointArr[JointType_ElbowLeft], myMapper);
draw(copy, myJointArr[JointType_SpineMid], myJointArr[JointType_SpineBase], myMapper);
draw(copy, myJointArr[JointType_ShoulderRight], myJointArr[JointType_ElbowRight], myMapper); draw(copy, myJointArr[JointType_ElbowLeft], myJointArr[JointType_WristLeft], myMapper);
draw(copy, myJointArr[JointType_SpineBase], myJointArr[JointType_HipLeft], myMapper);
draw(copy, myJointArr[JointType_SpineBase], myJointArr[JointType_HipRight], myMapper);
draw(copy, myJointArr[JointType_ElbowRight], myJointArr[JointType_WristRight], myMapper); draw(copy, myJointArr[JointType_WristLeft], myJointArr[JointType_ThumbLeft], myMapper);
draw(copy, myJointArr[JointType_WristLeft], myJointArr[JointType_HandLeft], myMapper);
draw(copy, myJointArr[JointType_HipLeft], myJointArr[JointType_KneeLeft], myMapper);
draw(copy, myJointArr[JointType_HipRight], myJointArr[JointType_KneeRight], myMapper);
draw(copy, myJointArr[JointType_WristRight], myJointArr[JointType_ThumbRight], myMapper);
draw(copy, myJointArr[JointType_WristRight], myJointArr[JointType_HandRight], myMapper); draw(copy, myJointArr[JointType_HandLeft], myJointArr[JointType_HandTipLeft], myMapper);
draw(copy, myJointArr[JointType_KneeLeft], myJointArr[JointType_FootLeft], myMapper);
draw(copy, myJointArr[JointType_KneeRight], myJointArr[JointType_FootRight], myMapper);
draw(copy, myJointArr[JointType_HandRight], myJointArr[JointType_HandTipRight], myMapper);
}
}
}
delete[]myBodyArr;
myBodyFrame->Release();
myColorFrame->Release(); imshow("TEST", copy);
if (waitKey(30) == VK_ESCAPE)
break;
}
myMapper->Release(); myDescription->Release();
myColorReader->Release();
myColorSource->Release(); myBodyReader->Release();
myBodySource->Release();
mySensor->Close();
mySensor->Release(); return 0;
} void draw(Mat & img, Joint & r_1, Joint & r_2, ICoordinateMapper * myMapper)
{
//用两个关节点来做线段的两端,并且进行状态过滤
if (r_1.TrackingState == TrackingState_Tracked && r_2.TrackingState == TrackingState_Tracked)
{
ColorSpacePoint t_point; //要把关节点用的摄像机坐标下的点转换成彩色空间的点
Point p_1, p_2;
myMapper->MapCameraPointToColorSpace(r_1.Position, &t_point);
p_1.x = t_point.X;
p_1.y = t_point.Y;
myMapper->MapCameraPointToColorSpace(r_2.Position, &t_point);
p_2.x = t_point.X;
p_2.y = t_point.Y; line(img, p_1, p_2, Vec3b(0, 255, 0), 5);
circle(img, p_1, 10, Vec3b(255, 0, 0), -1);
circle(img, p_2, 10, Vec3b(255, 0, 0), -1);
}
}

详细说明

不难发现代码跟前面一篇非常类似,不同的地方就在于绘图部分。首先要将关节点用的CameraSpace转换到ColorSpace,这一操作可以借助ICoordinateMapper完成,然后就用两个关节点来作为线段的两端画线。这里采用了广度优先的办法,从上到下一层一层选取关节点。


效果图

Kinect For Windows V2开发日志九:侦测并绘制人体骨架的更多相关文章

  1. Kinect For Windows V2开发日志八:侦测、追踪人体骨架

    简介 Kinect一个很强大的功能就是它可以侦测到人体的骨骼信息并追踪,在Kinect V2的SDK 2.0中,它最多可以同时获取到6个人.每个人25个关节点的信息,并且通过深度摄像头,可以同时获取到 ...

  2. Kinect For Windows V2开发日志一:开发环境的配置

    算是正式进军Kinect了,前段时间学的东西现在就忘了,于是从此开始记录一下. 目前为止大部分的学习资料来自于Heresy的博客,写的非常优秀,清晰明了,十分感谢.开发语言为C++,应该会一直使用,但 ...

  3. Kinect For Windows V2开发日志六:人体的轮廓的表示

    Kinect中带了一种数据源,叫做BodyIndex,简单来说就是它利用深度摄像头识别出最多6个人体,并且用数据将属于人体的部分标记,将人体和背景区别开来.利用这一特性,就可以在环境中显示出人体的轮廓 ...

  4. Kinect For Windows V2开发日志五:使用OpenCV显示彩色图像及红外图像

    彩色图像 #include <iostream> #include <Kinect.h> #include <opencv2\highgui.hpp> using ...

  5. Kinect For Windows V2开发日志七:照片合成与背景消除

    上一篇里讲到了Kinect可以从环境中区分出人体来.因此可以利用这个功能,来把摄像头前的人合成进照片里,和利用Photoshop不同的是,这样合成进去的人是动态且实时的. 简单的思路 BodyInde ...

  6. Kinect For Windows V2开发日志四:使用OpenCV显示深度图像

    代码示例: #include <Kinect.h> #include <iostream> #include <opencv2\highgui.hpp> using ...

  7. Kinect For Windows V2开发日志三:简单的深度读取

    代码示例: #include <Kinect.h> #include <iostream> using namespace std; int main(void) { IKin ...

  8. Kinect For Windows V2开发日志二:Kinect V2的基本参数

    以下内容节选自Heresy的博客:   彩色影像:1920 x 1080 @ 30 / 15 FPS(根据环境亮度) 深度影像:512 x 424 @ 30 FPS.16bit 距离值(mm).可侦测 ...

  9. Kinect for Windows V2开发教程

    教程 https://blog.csdn.net/openbug/article/details/80921437 Windows版Kinect SDK https://docs.microsoft. ...

随机推荐

  1. maven profile动态选择配置文件

    一.背景 在开发过程中,我们的软件会面对不同的运行环境,比如开发环境.测试环境.生产环境,而我们的软件在不同的环境中,有的配置可能会不一样,比如数据源配置.日志文件配置.以及一些软件运行过程中的基本配 ...

  2. 用DependanceProperty做Dynamic换Icon

    1:做Icon用Canvas还是DrawingBrush? Canvas的例子:

  3. (剑指Offer)面试题14:调整数组顺序使奇数位于偶数前面

    题目: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 如果去掉约束条件: ...

  4. php网站的定时事件

    提示信息: 1.crontab    (脚本定时.) 2. php    XXX.php(注:xxx.php页面是具体要做的事情.)

  5. javascript数字转汉字中文数字

    /* 工具包 */ var Utils={ /* 单位 */ units:'个十百千万@#%亿^&~', /* 字符 */ chars:'零一二三四五六七八九', /* 数字转中文 @numb ...

  6. thinkphp 3+ 观后详解 (5)

    static public function dispatch() { $varPath = C('VAR_PATHINFO'); $varAddon = C('VAR_ADDON'); $varMo ...

  7. cocos2d-x 用浏览器打开网页

    转自:http://www.xuebuyuan.com/1396292.html,http://www.cocoachina.com/bbs/read.php?tid=88589 First!! 源代 ...

  8. JavaScript的角色巨变和Web技术的发展

    曾经JavaScript是职业程序员看不上眼的脚本语言,如今只有高级程序员才能驾驭它. JavaScript性质和地位的天翻地覆,正是Web技术飞速变化的印证. 最初职业程序员轻视JavaScript ...

  9. Swift2.0 中的String(一):常用属性

    字符串算是平常用的比较多.花样也比较多的一个类型,昨天有空把相关的一些常用操作都写了一遍,总结出来.其实iOS里面的字符串更复杂,还有NSString系列等等,那些API太多将来需要用的时候再慢慢学. ...

  10. Objective-C面向对象的编程

    Objective-C面向对象的编程 目录 对面向对象编程思想的理解 类的声明和定义 类的声明和定义 对关键字super和self的理解 初始化函数 @property声明类成员 类的实例化 继承 组 ...