# 简介
在上一篇[《侦测、追踪人体骨架》](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. php中定义类

    <?php class Person{ //定义了一个Person类 public $name; //定义属性name public $age; //定义属性age function __con ...

  2. 结构类模式(三):组合(Composite)

    定义 将对象组合成树形结构以表示“部分整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客 ...

  3. Error opening trace file: No such file or directory (2)

    想看sharepreference保存的键值对的数据,用到单元测,运行函数总是报这种错,且看不到file explorer-->data>对应工程包的xml文件:

  4. c# 轻量级 ORM 框架 之 Model解析 (四)

    关于orm框架设计,还有必要说的或许就是Model解析了,也是重要的一个环节,在实现上还是相对比较简单的. Model解析,主要用到的技术是反射了,即:把类的属性与表的字段做映射. 把自己的设计及实现 ...

  5. web自己主动保存表单

    note:当中部分源代码来源网络 所用的框架:jquery 实现的功能: 1.自己主动保存表单 2.页面刷新的时候把自己主动保存的值赋值给表单元素 思路: 1.表单值改变的时候自己主动触发函数.保存表 ...

  6. [置顶] Android开发之MediaPlayerService服务详解(一)

    前面一节我们分析了Binder通信相关的两个重要类:ProcessState 和 IPCThreadState.ProcessState负责打开Binder 驱动,每个进程只有一个.而 IPCThre ...

  7. hdu5072 2014 Asia AnShan Regional Contest C Coprime

    最后一次参加亚洲区…… 题意:给出n(3 ≤ n ≤ 105)个数字,每个数ai满足1 ≤ ai ≤ 105,求有多少对(a,b,c)满足[(a, b) = (b, c) = (a, c) = 1] ...

  8. Java对证书的操作

    1 Java程序从证书文件读取证书 import java.io.*; import java.security.cert.*; public class PrintCert{ public stat ...

  9. [Java] 识别图片验证码

    现在大多数网站都采用了验证码来防止暴力破解或恶意提交.但验证码真的就很安全吗?真的就不能被机器识别?? 我先讲讲我是怎么实现站外提交留言到一个网站的程序. 这个网站的留言版大致如下: 我一看这种简单的 ...

  10. js代码的一些小技巧

    1. 数组中通过赋值语句来改变值 var a = 1; var msg = ["value0","value1"]; for(var i = 0;i<10 ...