Kinect2入门+opencv画骨架+骨架数据
Posted 朱铭德
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kinect2入门+opencv画骨架+骨架数据相关的知识,希望对你有一定的参考价值。
准备工作///
首先需要下载安装Kinect2的SDK,下载地址如下:
https://www.microsoft.com/en-us/download/details.aspx?id=44561
建议安装时从官网下载,之前有出现过拷贝的文件无法正常安装的情况。
//注意V2.0以下版本为一代Kinect所用,一代Kinect推荐V1.8
相对于一代的Kinect,二代由于SDK只出过这一个版本,仍有许多瑕疵,但整体性能提升了许多,手部多了几个指关节以及能同时track六个人是最大的亮点。
安装完SDK之后连接Kinect到USB3.0的接口测试是否正常运行。
//Windows SDK的一个优势在于安装一个SDK之后即可
打开SDK Browser v2.0
选择比较直观的Color Basics-D2D应用进行测试
/%由于二代的未连上Kinect不会像一代那样报错,这样的好处是如果接口松动也不会致使程序崩溃,但缺点也很明显,如果Kinect只是作为一个后台检测的部分便会给程序联调带来一点麻烦。%/
当然在这里没有一点麻烦,打开(点击Run按钮)之后如果能正常显示真彩图,那么基本可以说硬件部分没有问题了。
/利用C++以及opencv画出骨架
代码链接:http://download.csdn.net/detail/zmdsjtu/9609472
#include <opencv2/opencv.hpp>
#include <Windows.h>
#include <Kinect.h>
#include<iostream>
#include<time.h>
using namespace std;
using namespace cv;
//释放接口需要自己定义
template<class Interface>
inline void SafeRelease(Interface *& pInterfaceToRelease)
{
if (pInterfaceToRelease != NULL) {
pInterfaceToRelease->Release();
pInterfaceToRelease = NULL;
}
}
void DrawBone(Mat& SkeletonImage, CvPoint pointSet[], const Joint* pJoints, int whichone, JointType joint0, JointType joint1);
void drawSkeleton(Mat& SkeletonImage, CvPoint pointSet[], const Joint* pJoints, int whichone);
int main(int argc, char **argv[])
{
//OpenCV中开启CPU的硬件指令优化功能函数
setUseOptimized(true);
// Sensor
IKinectSensor* pSensor;
HRESULT hResult = S_OK;
hResult = GetDefaultKinectSensor(&pSensor);
hResult = pSensor->Open();
if (FAILED(hResult)) {
std::cerr << "Error : IKinectSensor::Open()" << std::endl;
return -1;
}
//Source
IColorFrameSource* pColorSource;
hResult = pSensor->get_ColorFrameSource(&pColorSource);
if (FAILED(hResult)) {
std::cerr << "Error : IKinectSensor::get_ColorFrameSource()" << std::endl;
return -1;
}
IBodyFrameSource* pBodySource;
hResult = pSensor->get_BodyFrameSource(&pBodySource);
if (FAILED(hResult)) {
std::cerr << "Error : IKinectSensor::get_BodyFrameSource()" << std::endl;
return -1;
}
// Reader
IColorFrameReader* pColorReader;
hResult = pColorSource->OpenReader(&pColorReader);
if (FAILED(hResult)) {
std::cerr << "Error : IColorFrameSource::OpenReader()" << std::endl;
return -1;
}
IBodyFrameReader* pBodyReader;
hResult = pBodySource->OpenReader(&pBodyReader);
if (FAILED(hResult)) {
std::cerr << "Error : IBodyFrameSource::OpenReader()" << std::endl;
return -1;
}
// Description
IFrameDescription* pDescription;
hResult = pColorSource->get_FrameDescription(&pDescription);
if (FAILED(hResult)) {
std::cerr << "Error : IColorFrameSource::get_FrameDescription()" << std::endl;
return -1;
}
int width = 0;
int height = 0;
pDescription->get_Width(&width); // 1920
pDescription->get_Height(&height); // 1080
unsigned int bufferSize = width * height * 4 * sizeof(unsigned char);
cv::Mat bufferMat(height, width, CV_8UC4);
cv::Mat bodyMat(height / 2, width / 2, CV_8UC4);
cv::namedWindow("Body");
// Color Table
cv::Vec3b color[BODY_COUNT];
color[0] = cv::Vec3b(255, 0, 0);
color[1] = cv::Vec3b(0, 255, 0);
color[2] = cv::Vec3b(0, 0, 255);
color[3] = cv::Vec3b(255, 255, 0);
color[4] = cv::Vec3b(255, 0, 255);
color[5] = cv::Vec3b(0, 255, 255);
float Skeletons[6][25][3];
// Coordinate Mapper
ICoordinateMapper* pCoordinateMapper;
hResult = pSensor->get_CoordinateMapper(&pCoordinateMapper);
if (FAILED(hResult)) {
std::cerr << "Error : IKinectSensor::get_CoordinateMapper()" << std::endl;
return -1;
}
while (1) {
// Frame
IColorFrame* pColorFrame = nullptr;
hResult = pColorReader->AcquireLatestFrame(&pColorFrame);
if (SUCCEEDED(hResult)) {
hResult = pColorFrame->CopyConvertedFrameDataToArray(bufferSize, reinterpret_cast<BYTE*>(bufferMat.data), ColorImageFormat::ColorImageFormat_Bgra);
if (SUCCEEDED(hResult)) {
cv::resize(bufferMat, bodyMat, cv::Size(), 0.5, 0.5);
}
}
//更新骨骼帧
IBodyFrame* pBodyFrame = nullptr;
hResult = pBodyReader->AcquireLatestFrame(&pBodyFrame);
if (SUCCEEDED(hResult)) {
IBody* pBody[BODY_COUNT] = { 0 };
//更新骨骼数据
hResult = pBodyFrame->GetAndRefreshBodyData(BODY_COUNT, pBody);
if (SUCCEEDED(hResult)) {
for (int count = 0; count < BODY_COUNT; count++) {
BOOLEAN bTracked = false;
hResult = pBody[count]->get_IsTracked(&bTracked);
if (SUCCEEDED(hResult) && bTracked) {
Joint joint[JointType::JointType_Count];
/
hResult = pBody[count]->GetJoints(JointType::JointType_Count, joint);//joint
if (SUCCEEDED(hResult)) {
// Left Hand State
HandState leftHandState = HandState::HandState_Unknown;
hResult = pBody[count]->get_HandLeftState(&leftHandState);
if (SUCCEEDED(hResult)) {
ColorSpacePoint colorSpacePoint = { 0 };
hResult = pCoordinateMapper->MapCameraPointToColorSpace(joint[JointType::JointType_HandLeft].Position, &colorSpacePoint);
if (SUCCEEDED(hResult)) {
int x = static_cast<int>(colorSpacePoint.X);
int y = static_cast<int>(colorSpacePoint.Y);
if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
if (leftHandState == HandState::HandState_Open) {
cv::circle(bufferMat, cv::Point(x, y), 75, cv::Scalar(0, 128, 0), 5, CV_AA);
}
else if (leftHandState == HandState::HandState_Closed) {
cv::circle(bufferMat, cv::Point(x, y), 75, cv::Scalar(0, 0, 128), 5, CV_AA);
}
else if (leftHandState == HandState::HandState_Lasso) {
cv::circle(bufferMat, cv::Point(x, y), 75, cv::Scalar(128, 128, 0), 5, CV_AA);
}
}
}
}
HandState rightHandState = HandState::HandState_Unknown;
ColorSpacePoint colorSpacePoint = { 0 };
hResult = pBody[count]->get_HandRightState(&rightHandState);
if (SUCCEEDED(hResult)) {
hResult = pCoordinateMapper->MapCameraPointToColorSpace(joint[JointType::JointType_HandRight].Position, &colorSpacePoint);
if (SUCCEEDED(hResult)) {
int x = static_cast<int>(colorSpacePoint.X);
int y = static_cast<int>(colorSpacePoint.Y);
if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
if (rightHandState == HandState::HandState_Open) {
cv::circle(bufferMat, cv::Point(x, y), 75, cv::Scalar(0, 128, 0), 5, CV_AA);
}
else if (rightHandState == HandState::HandState_Closed) {
cv::circle(bufferMat, cv::Point(x, y), 75, cv::Scalar(0, 0, 128), 5, CV_AA);
}
else if (rightHandState == HandState::HandState_Lasso) {
cv::circle(bufferMat, cv::Point(x, y), 75, cv::Scalar(128, 128, 0), 5, CV_AA);
}
}
}
}
CvPoint skeletonPoint[BODY_COUNT][JointType_Count] = { cvPoint(0,0) };
// Joint
for (int type = 0; type < JointType::JointType_Count; type++) {
ColorSpacePoint colorSpacePoint = { 0 };
pCoordinateMapper->MapCameraPointToColorSpace(joint[type].Position, &colorSpacePoint);
int x = static_cast<int>(colorSpacePoint.X);
int y = static_cast<int>(colorSpacePoint.Y);
skeletonPoint[count][type].x = x;
skeletonPoint[count][type].y = y;
if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
cv::circle(bufferMat, cv::Point(x, y), 5, static_cast< cv::Scalar >(color[count]), -1, CV_AA);
}
}
for (int i = 0; i < 25; i++) {
Skeletons[count][i][0] = joint[i].Position.X;
Skeletons[count][i][1] = joint[i].Position.Y;
Skeletons[count][i][2] = joint[i].Position.Z;
}
drawSkeleton(bufferMat, skeletonPoint[count], joint, count);
}
}
}
cv::resize(bufferMat, bodyMat, cv::Size(), 0.5, 0.5);
}
for (int count = 0; count < BODY_COUNT; count++) {
SafeRelease(pBody[count]);
}
}
SafeRelease(pColorFrame);
SafeRelease(pBodyFrame);
waitKey(1);
cv::imshow("Body", bodyMat);
}
SafeRelease(pColorSource);
SafeRelease(pColorReader);
SafeRelease(pDescription);
SafeRelease(pBodySource);
// done with body frame reader
SafeRelease(pBodyReader);
SafeRelease(pDescription);
// done with coordinate mapper
SafeRelease(pCoordinateMapper);
if (pSensor) {
pSensor->Close();
}
SafeRelease(pSensor);
return 0;
}
void DrawBone(Mat& SkeletonImage, CvPoint pointSet[], const Joint* pJoints, int whichone, JointType joint0, JointType joint1)
{
TrackingState joint0State = pJoints[joint0].TrackingState;
TrackingState joint1State = pJoints[joint1].TrackingState;
// If we can't find either of these joints, exit
if ((joint0State == TrackingState_NotTracked) || (joint1State == TrackingState_NotTracked))
{
return;
}
// Don't draw if both points are inferred
if ((joint0State == TrackingState_Inferred) && (joint1State == TrackingState_Inferred))
{
return;
}
CvScalar color;
switch (whichone) //跟踪不同的人显示不同的颜色
{
case 0:
color = cvScalar(255);
break;
case 1:
color = cvScalar(0, 255);
break;
case 2:
color = cvScalar(0, 0, 255);
break;
case 3:
color = cvScalar(255, 255, 0);
break;
case 4:
color = cvScalar(255, 0, 255);
break;
case 5:
color = cvScalar(0, 255, 255);
break;
}
// We assume all drawn bones are inferred unless BOTH joints are tracked
if ((joint0State == TrackingState_Tracked) && (joint1State == TrackingState_Tracked))
{
line(SkeletonImage, pointSet[joint0], pointSet[joint1], color, 2);
}
else
{
line(SkeletonImage, pointSet[joint0], pointSet[joint1], color, 2);
}
}
void drawSkeleton(Mat& SkeletonImage, CvPoint pointSet[], const Joint* pJoints, int whichone)
{
// Draw the bones
// Torso
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_Head, JointType_Neck);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_Neck, JointType_SpineShoulder);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_SpineShoulder, JointType_SpineMid);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_SpineMid, JointType_SpineBase);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_SpineShoulder, JointType_ShoulderRight);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_SpineShoulder, JointType_ShoulderLeft);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_SpineBase, JointType_HipRight);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_SpineBase, JointType_HipLeft);
// Right Arm
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_ShoulderRight, JointType_ElbowRight);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_ElbowRight, JointType_WristRight);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_WristRight, JointType_HandRight);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_HandRight, JointType_HandTipRight);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_WristRight, JointType_ThumbRight);
// Left Arm
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_ShoulderLeft, JointType_ElbowLeft);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_ElbowLeft, JointType_WristLeft);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_WristLeft, JointType_HandLeft);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_HandLeft, JointType_HandTipLeft);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_WristLeft, JointType_ThumbLeft);
// Right Leg
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_HipRight, JointType_KneeRight);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_KneeRight, JointType_AnkleRight);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_AnkleRight, JointType_FootRight);
// Left Leg
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_HipLeft, JointType_KneeLeft);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_KneeLeft, JointType_AnkleLeft);
DrawBone(SkeletonImage, pointSet, pJoints, whichone, JointType_AnkleLeft, JointType_FootLeft);
}
新建一个空白项目,在配置opencv环境的基础之上
包含目录要加上C:\\Program Files\\Microsoft SDKs\\Kinect\\v2.0_1409\\inc
库目录要加上C:\\Program Files\\Microsoft SDKs\\Kinect\\v2.0_1409\\Lib\\x86
输入附加依赖项要加上kinect20.lib
之前配置opencv环境的链接:http://blog.csdn.net/zmdsjtu/article/details/52235056
配合上连接的代码应该可以正常运行了。
注意:因为直接VS调试的环境没有系统默认的opencv环境变量,故而可以生成之后直接点击对应EXE运行,否则会提示缺少Dll,嫌麻烦也可以把指定dll放到编译目录下
为方便后续程序的开发定义了:
float Skeletons[6][25][3];//六副骨架储存的数据,其他功能模块较为直观,也相对简单。
//有一点缺陷,画图的时候股价点有时会跑到(0,0)的位置,如果发现代码里的bug请评论或者私信下哈,谢啦~
运行结果如下:
最后祝大家开发愉快~
附录:各个关节点对应数字
JointType_SpineBase = 0,
JointType_SpineMid = 1,
JointType_Neck = 2,
JointType_Head = 3,
JointType_ShoulderLeft = 4,
JointType_ElbowLeft = 5,
JointType_WristLeft = 6,
JointType_HandLeft = 7,
JointType_ShoulderRight = 8,
JointType_ElbowRight = 9,
JointType_WristRight = 10,
JointType_HandRight = 11,
JointType_HipLeft = 12,
JointType_KneeLeft = 13,
JointType_AnkleLeft = 14,
JointType_FootLeft = 15,
JointType_HipRight = 16,
JointType_KneeRight = 17,
JointType_AnkleRight = 18,
JointType_FootRight = 19,
JointType_SpineShoulder = 20,
JointType_HandTipLeft = 21,
JointType_ThumbLeft = 22,
JointType_HandTipRight = 23,
JointType_ThumbRight = 24,
JointType_Count = ( JointType_ThumbRight + 1 )
以上是关于Kinect2入门+opencv画骨架+骨架数据的主要内容,如果未能解决你的问题,请参考以下文章
Python,OpenCV骨架化图像并显示(skeletonize)
youcans 的 OpenCV 例程200篇128. 形态算法之骨架 (skimage)