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. mysql多实例(个人的情况,不是大众的)里面有配置好的脚本+主从复制

    [root@DB-S ~]# ll /usr/local/|grep mysql lrwxrwxrwx. 1 root root 21 Jun 14 01:52 mysql -> /alidat ...

  2. 9.装饰者模式(Decorator Pattern)

    using System; namespace ConsoleApplication7 { class Program { static void Main(string[] args) { // 我 ...

  3. C#的面向对象特性之封装

    在C#语言中,共有五种访问修饰符:public.private.protected.internal.protected internal. public 公有访问.不受任何限制.private 私有 ...

  4. Striiv Myland 攻略

    推荐一款IOS平台上的运动APP:Striiv.可以记录平时的步数,路程,卡路里,运动时间.如果购买相应的硬件,还可以记录每天爬了多少台阶(这是专门为爬楼者用的么...). 其中比较吸引我的是里面有个 ...

  5. AndroidManifest.xml相关知识

    AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest  ...

  6. SqlServer 函数 大全

    sql server使用convert来取得datetime日期数据 sql server使用convert来取得datetime日期数据,以下实例包含各种日期格式的转换 语句及查询结果: Selec ...

  7. MySQL监控系统MySQL MTOP的搭建

    MySQLMTOP是一个由Python+PHP开发的MySQL企业级监控系统.系统由Python实现多进程数据采集和告警,PHP实现WEB展示和管理.最重要是MySQL服务器无需安装任何Agent,只 ...

  8. [LintCode] Word Break

    Given a string s and a dictionary of words dict, determine if s can be break into a space-separated ...

  9. C#:代表(delegate)和事件(event)

    代表(delegate): 它是C#语言里面的函数指针,代表可以指向某一个函数,在运行的时候调用这个函数的实现.下面来看看它的实现步骤: 声明一个delegate对象. 实现和delegate具有相同 ...

  10. Edmond_Karp算法

    核心思想:通过bfs不断在网络中寻找最短的增广路,从而求得最大流.时间复杂度O(VE^) 算法模板: int Edmond_Karp(int s,int t) { ; memset(flow,,siz ...