Kinect SDK v2预览版的主要功能的使用介绍,基本上完成了。这次,是关于取得Body(人体姿势)方法的说明。

  上一节,是使用Kinect SDK v2预览版从Kinect v2预览版取得BodyIndex(人体区域)的方法。
 这一节,介绍从Kinect取得Body(人体姿势)的方法。

Body

  到目前为止,Kinect能取得Depth(通过传感器的距离信息)和BodyIndex(人体区域)。并且,基于这些数据可以取得人体姿势。
 
  Kinect的人体姿势,是向学习了基于庞大数量的姿势信息的识别器里,输入人体区域的信息来推定的(注:因为男女老少高矮胖瘦体形各不相同,所以必须基于神经网络的数据库才能准确识别人体)。详细还请参考Microsoft Research发表的论文。
  这个论文在IEEE CVPR 2011(计算机视觉及模式认识领域的首位会议)发表,获奖Best Paper。
Microsoft Research“Real-Time Human Pose Recognition in Parts from a Single Depth Image”
  背景技术说不定很复杂,不过开发者通过Kinect SDK可以简单地取得和使用人体姿势。
 
  人体的姿势数据,可以得到头,手,脚等3维的位置,基于这些可以实现姿势的识别。
  这个人体区域,在Kinect SDK v1被称为「Skeleton」,不过,在Kinect SDK v2预览版里更名为「Body」。
 
  这一节,介绍取得Body的方法。
 
示例程序
使用Kinect SDK v2预览版取得Body和Color图像叠加显示为「●(圆点)」的示例程序展示。还有,基于Body数据,Hand State(手的状态)也做了显示。第2节有介绍取得数据的阶段摘录解说,这个示例程序的全部内容,在下面的github里公开。
 
 
图1 Kinect SDK v2预览版的数据取得流程(重发)

「Sensor」
取得「Sensor」
// Sensor
IKinectSensor* pSensor; ……
HRESULT hResult = S_OK;
hResult = GetDefaultKinectSensor( &pSensor ); ……
if( FAILED( hResult ) ){
std::cerr << "Error : GetDefaultKinectSensor" << std::endl;
return -;
}
hResult = pSensor->Open(); ……
if( FAILED( hResult ) ){
std::cerr << "Error : IKinectSensor::Open()" << std::endl;
return -;
}
列表1.1 相当于图1「Source」的部分
1 Kinect v2预览版的Sensor接口。
2 取得默认的Sensor。
3 打开Sensor。
 
「Source」
从「Sensor」取得「Source」。
// Source
IBodyFrameSource* pBodySource; ……
hResult = pSensor->get_BodyFrameSource( &pBodySource ); ……
if( FAILED( hResult ) ){
std::cerr << "Error : IKinectSensor::get_BodyFrameSource()" << std::endl;
return -;
}
列表1.2 相当于图1「Source」的部分
1 Body Frame的Source接口。
2 从Sensor取得Source。
 
  这里只是关于取得Body的源代码解说,不过,为了案例程序的显示,也同时取得了Color。
「Reader」
「Source」从打开「Reader」。
// Reader
IBodyFrameReader* pBodyReader; ……
hResult = pBodySource->OpenReader( &pBodyReader ); ……
if( FAILED( hResult ) ){
std::cerr << "Error : IBodyFrameSource::OpenReader()" << std::endl;
return -;
}
列表1.3 相当于图1「Reader」的部分
1 Body  Frame的Reader接口。
2 从Source打开Reader。
 
「Frame」~「Data」
从「Reader」取得最新的「Frame」(列表1.5)。
 
在这之前,为了可以和从传感器取得的坐标匹配,取得ICoordinateMapper的接口(列表1.4),由于Color照相机和Depth传感器的位置是分开的,因此需要把body数据和Color图像的位置进行匹配。
// Coordinate Mapper
ICoordinateMapper* pCoordinateMapper; ……
hResult = pSensor->get_CoordinateMapper( &pCoordinateMapper ); ……
if( FAILED( hResult ) ){
std::cerr << "Error : IKinectSensor::get_CoordinateMapper()" << std::endl;
return -;
}
列表1.4,坐标匹配接口的取得
1 Frame之间的坐标匹配的接口。
2 从Sensor获取坐标匹配的接口。
接下来的列表1.5,是和连载第2节一样的方法,表示的是Color图形的取得。
int width = ;
int height = ;
unsigned int bufferSize = width * height * * sizeof( unsigned char );
cv::Mat bufferMat( height, width, CV_8UC4 );
cv::Mat bodyMat( height / , width / , CV_8UC4 );
cv::namedWindow( "Body" );
// Color Table
cv::Vec3b color[];
color[] = cv::Vec3b( , , );
color[] = cv::Vec3b( , , );
color[] = cv::Vec3b( , , );
color[] = cv::Vec3b( , , );
color[] = cv::Vec3b( , , );
color[] = cv::Vec3b( , , );
while( ){
// Color Frame ……1
IColorFrame* pColorFrame = nullptr;
hResult = pColorReader->AcquireLatestFrame( &pColorFrame );
if( SUCCEEDED( hResult ) ){
hResult = pColorFrame->CopyConvertedFrameDataToArray( bufferSize, reinterpret_cast<BYTE*>( bufferMat.data ), ColorImageFormat_Bgra );
if( SUCCEEDED( hResult ) ){
cv::resize( bufferMat, bodyMat, cv::Size(), 0.5, 0.5 );
}
}
SafeRelease( pColorFrame );
/* Body部分在列表1.6 */
// Show Window
cv::imshow( "Body", bodyMat );
if( cv::waitKey( ) == VK_ESCAPE ){
break;
}
}

列表1.5,相当于图1「Frame」,「Data」的部分(第1部分)

1 为了显示Body数据取得Color图像,详细见第2节。
  
列表1.5中的Body部分的代码,在下面的列表1.6里显示。
// Body Frame
IBodyFrame* pBodyFrame = nullptr; ……
hResult = pBodyReader->AcquireLatestFrame( &pBodyFrame ); ……
if( SUCCEEDED( hResult ) ){
IBody* pBody[BODY_COUNT] = { }; ……
hResult = pBodyFrame->GetAndRefreshBodyData( BODY_COUNT, pBody ); ……
if( SUCCEEDED( hResult ) ){
for( int count = ; 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 ); ……
if( SUCCEEDED( hResult ) ){
// Left Hand State
HandState leftHandState = HandState::HandState_Unknown; ……
hResult = pBody[count]->get_HandLeftState( &leftHandState ); ……
if( SUCCEEDED( hResult ) ){
ColorSpacePoint colorSpacePoint = { }; ……
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 >= ) && ( x < width ) && ( y >= ) && ( y < height ) ){
if( leftHandState == HandState::HandState_Open ){ ……
cv::circle( bufferMat, cv::Point( x, y ), , cv::Scalar( , , ), , CV_AA );
}
else if( leftHandState == HandState::HandState_Closed ){ ……
cv::circle( bufferMat, cv::Point( x, y ), , cv::Scalar( , , ), , CV_AA );
}
else if( leftHandState == HandState::HandState_Lasso ){ ……
cv::circle( bufferMat, cv::Point( x, y ), , cv::Scalar( , , ), , CV_AA );
}
}
}
}
// Right Hand State
/* 和左手一样,获取右手Hand State绘制状态。 */
// Joint ……9
for( int type = ; type < JointType::JointType_Count; type++ ){
ColorSpacePoint colorSpacePoint = { };
pCoordinateMapper->MapCameraPointToColorSpace( joint[type].Position, &colorSpacePoint );
int x = static_cast< int >( colorSpacePoint.X );
int y = static_cast< int >( colorSpacePoint.Y );
if( ( x >= ) && ( x < width ) && ( y >= ) && ( y < height ) ){
cv::circle( bufferMat, cv::Point( x, y ), , static_cast<cv::Scalar>( color[count] ), -, CV_AA );
}
}
}
}
}
cv::resize( bufferMat, bodyMat, cv::Size(), 0.5, 0.5 );
}
}
SafeRelease( pBodyFrame );
列表1.6,相当于图1「Frame」,「Data」的部分(第2部分)
1 Body的Frame接口。
2 从Reader里取得最新的Frame。
3 从Frame取得Body。  
   后面,是从人体取得数据。
4 确认能着追踪到人体。
5 取得人体Joint(关节)。
6 取得Hand State。
7 为了绘制,把Body座標向Color座標的坐标匹配。
   匹配的坐标是否超出绘制范围(这里Color图像的尺寸是1920×1080)的检查。
   (注:因为两个Camera位置、FOV和分辨率的不同,在匹配时不可能完全一一对应,所以必须检查坐标的有效性)
8 对应状态绘制相应颜色的○(圆型)做Hand State的可视化。
   用各自对应Open(打开:布),Closed(关闭:拳),Lasso(套索:剪)的颜色绘制。如果检查不出状态就不绘制。
9 对应人体的Joint参照color table的颜色做绘制。
   和Hand State一样,Body坐标向Color坐标坐标匹配来绘制●(圆点)。
 
  使用Kinect SDK v1从人体区域中检测获取的详细人体姿势最多支持2个人。Kinect SDK v2预览版可以检测获取全部人体区域(6人)的详细人体姿势。
  另外,Kinect SDK v1能取得的Joint是全身20个,Kinect SDK v2预览版是追加了「脖子(=NECK)」,「指尖(=HAND_TIP_LEFT,HAND_TIP_RIGHT)」,「大拇指(=THUMB_LEFT,THUMB_RIGHT)」5个,一共25个Joint。
 
  示例程序里,根据Joint位置参考color table的颜色绘制成「●(圆点)」来可视化。
 
  Kinect SDK v1(Kinect Developer Toolkit/Kinect Interaction)可以取得的Hand State,有「Open(打开)」和「Closed(关闭)」的2种类型。
 
  Kinect SDK v2预览版,在「Open」「Closed」基础上又增加了「Lasso(=套索)」这个状态的取得。「Lasso」能检查出竖起两个手指的状态。想象为「猜拳的(拳头,剪刀,布)」就好了。这里还有一个链接扩展阅读,我之后会翻译。
 
  现在,6个人中可以同时获取其中2个人的Hand State。
 
  示例程序里,可以通过手的Joint位置的状态来着色「○(圆环)」的绘制做可视化。「Open」绿色(=「cv::Scalar(0,128,0)」),「Closed」是红色(=「cv::Scalar(0,0,128)」),「Lasso」用淡蓝色(=「cv::Scalar(128,128,0)」)表现。
 
  Kinect SDK v1 Kinect SDK v2预览版
名称 Skeleton Body
人体姿勢可以取得的人数 2人 6人
Joint(关节) 20处 25处
Hand State(手的状態) 2種類 3種類
Hand State可以取得的人数 2人 2人
表1 Kinect SDK v1和Kinect SDK v2预览版的人体姿势(Skeleton,Body)的比较

图2 Kinect v1和Kinect v2预览版的可以取得的Joint
运行结果
运行这个示例程序,就像图3一样,从v2预览版取得的人体姿势和手的状态被可视化了。
图3 运行结果
Joint用●(圆点)来显示,Hand State用来○(圆环)来显示。

图4 Hand State的识别结果
「Open」是绿色,「Closed」是红色,「Lasso」浅蓝色的○(圆环)来显示。 手的状态可以清晰的识别。
 
总结
  这一节是使用Kinect SDK v2预览版取得Body的示例程序的介绍。现在,Kinect SDK v2预览版实现的主要功能基本上都被介绍了。
 
  不过,Kinect SDK v2预览版,在RTM版的发布之前预计会有2~3次的更新。近日,第1次更新被预定公开给早期提供程序的参与者。一旦SDK v2预览版有公开更新,本连载就会追加新的功能介绍。

【翻译】Kinect v2程序设计(C++) Body 篇的更多相关文章

  1. 【翻译】Kinect v2程序设计(C++-) AudioBeam篇

    Kinect v2,Microphone Array可以用来对于水平面音源方向的推测(AudioBeam)和语音识别(Speech Recognition).这一节是介绍如何取得AudioBeam. ...

  2. 【翻译】Kinect v2程序设计(C++) BodyIndex篇

    通过Kinect SDK v2预览版,取得BodyIndex(人体区域)的方法和示例代码. 上一节,介绍了从Kinect v2预览版用Kinect SDK v2预览版获取Depth数据的方法.   这 ...

  3. 【翻译】Kinect v2程序设计(C++) Color篇

    Kinect SDK v2预览版,获取数据的基本流程的说明.以及取得Color图像的示例程序的介绍. 上一节,是关于当前型号Kinect for Windows(后面称作Kinect v1)和次世代型 ...

  4. 【翻译】Kinect v2程序设计(C++) Depth编

    Kinect SDK v2预览版,取得Depth数据的方法说明. 上一节,介绍了通过使用Kinect for Windows SDK v2预览版(以下简称为,Kinect SDK v2预览版)从Kin ...

  5. 【翻译】Kinect v1和Kinect v2的彻底比较

      本连载主要是比较Kinect for Windows的现行版(v1)和次世代型的开发者预览版(v2),以C++开发者为背景介绍进化的硬件和软件.本文主要是对传感的配置和运行条件进行彻底的比较.   ...

  6. 【计算机视觉】深度相机(五)--Kinect v2.0

    原文:http://blog.csdn.NET/qq1175421841/article/details/50412994 ----微软Build2012大会:Kinect for Windows P ...

  7. Kinect v2.0 for windows开发环境说明

    官方文档里是这些: Supported Operating Systems and Architectures The following operating systems and architec ...

  8. Kinect v2(Microsoft Kinect for Windows v2 )配置移动电源解决方案

    Kinect v2配置移动电源解决方案 Kinect v2如果用于移动机器人上(也可以是其他应用场景),为方便有效地展开后续工作,为其配置移动电源是十分必要的. 一.选择移动电源 Kinect v2原 ...

  9. Ubuntu_ROS中应用kinect v2笔记

    Ubuntu_ROS中应用kinect v2笔记 个人觉得最重要的资料如下: 1. Microsoft Kinect v2 Driver Released http://www.ros.org/new ...

随机推荐

  1. Hibernate核心思想—ORM机制(一)

    转:http://blog.csdn.net/wanghuan203/article/details/7566518 hibernate是一个采用ORM(Object/Relation Mapping ...

  2. php 练习

    下拉样式 <select> <?php $a = array( array("n001 汉族"), array("n002 回族"), arr ...

  3. hrbustoj 1161:Leyni(树状数组练习)

    LeyniTime Limit: 3000 MS Memory Limit: 65536 KTotal Submit: 260(59 users) Total Accepted: 80(55 user ...

  4. FileHelper-文件操作辅助类

    using System; using System.Collections.Generic; using System.IO; using System.Text; namespace Whir.S ...

  5. PHP多文件上传类

    <?php class Upload{ var $saveName;// 保存名 var $savePath;// 保存路径 var $fileFormat = array('gif','jpg ...

  6. H.264 基础及 RTP 封包详解

    转自:http://my.oschina.net/u/1431835/blog/393315 一. h264基础概念 1.NAL.Slice与frame意思及相互关系 1 frame的数据可以分为多个 ...

  7. JSP Servlet 路径解析 路径设置

    转自:http://ethen.iteye.com/blog/800415 在用JSP和Servlet编写Web应用时,经常遇到的问题就是找不到.do路径,或者.do路径不能解析,其实归根到底就是Se ...

  8. C/C++函数使用

    1 memset 将s所指向的某一块内存中的前n个 字节的内容全部设置为ch指定的ASCII值, 块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向s的指针. 函数介绍 ...

  9. c# 作业2

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  10. 关于sqoop与datax。 和sqoop to oracle插件OraOop

         之前我还在想了解下datax,是否有可能替换sqoop,但了解后发现,datax和sqoop的业务场景是不同的.前者适合异构数据库的同步,后者适合hdfs与rdbms互相之间的同步.针对sq ...