zoukankan      html  css  js  c++  java
  • 【翻译】Kinect v2程序设计(C++) BodyIndex篇

    通过Kinect SDK v2预览版,取得BodyIndex(人体区域)的方法和示例代码。

    上一节,介绍了从Kinect v2预览版用Kinect SDK v2预览版获取Depth数据的方法。
     
    这一节,介绍从Kinect取得BodyIndex(人体区域)的方法。
     
    BodyIndex
    基于从Kinect取得的Depth数据(传感器的距离信息)获取人体区域。
     
    因为人体区域基于Depth数据,同时也依赖Depth传感器的分辨率。像上一节介绍的一样,因为Kinect v2 预览版(512×424)的Depth传感器的分辨率大幅提高和Kinect v1相比手指等细小部分的人体区域也变得可以准确的取得但是能检测出的人体区域的数量还是6个人这一点没有发生改变。
     
    关于人体区域,在Kinect SDK v1里被称为「Player」不过到了Kinect SDK v2 预览版里更名为「BodyIndex」。
     
    这一节,介绍取得「BodyIndex」的方法。

    图1 Kinect SDK v2预览版的示例程序(BodyBasics)
    BodyIndex在Color坐标的位置匹配截取手指等细小部分都可以清晰得在人体身上保留下来了。
    (注:因为Color和Depth的Camera位置不同,所以需要进行坐标空间的转换)
     
    样品程序
    使用Kinect SDK v2预览版取得BodyIndex,把每个人体用颜色区分出来并显示的示例程序展示。第2节有介绍的取得数据的阶段摘录解说。这个示例程序的全部内容在下面的github里公开。
     
     
     
    图2 Kinect SDK v2预览版的数据取得流程(重发)
    「Sensor」
    取得「Sensor」
    // Sensor
    IKinectSensor* pSensor;   ……1
    HRESULT hResult = S_OK;
    hResult = GetDefaultKinectSensor( &pSensor );  ……2
    if( FAILED( hResult ) ){
      std::cerr << "Error : GetDefaultKinectSensor" << std::endl;
      return -1;
    }
    hResult = pSensor->Open();  ……3
    if( FAILED( hResult ) ){
      std::cerr << "Error : IKinectSensor::Open()" << std::endl;
      return -1;
    }
    列表1.1 相当于图1「Source」的部分
    1 处理Kinect v2预览版的Sensor接口。
    2 取得默认的Sensor。
    3 打开Sensor。
     
    「Source」
    从「Sensor」取得「Source」。
    // Source
    IBodyIndexFrameSource* pBodyIndexSource;  ……1
    hResult = pSensor->get_BodyIndexFrameSource( &pBodyIndexSource );  ……2
    if( FAILED( hResult ) ){
      std::cerr << "Error : IKinectSensor::get_BodyIndexFrameSource()" << std::endl;
      return -1;
    }
    列表1.2 相当于图1「Source」的部分
    1 取得BodyIndex Frame的Source接口。
    2 从Sensor取得Source。
     
    「Reader」
    「Source」从打开「Reader」。
    // Reader
    IBodyIndexFrameReader* pBodyIndexReader;  ……1
    hResult = pBodyIndexSource->OpenReader( &pBodyIndexReader );  ……2
    if( FAILED( hResult ) ){
      std::cerr << "Error : IBodyIndexFrameSource::OpenReader()" << std::endl;
      return -1;
    }
    列表1.3 相当于图1「Reader」的部分
    1 取得BodyIndex  Frame的Reader接口。
    2 从Source打开Reader。
     
    「Frame」~「Data」
    从「Reader」取得最新的「Frame」。
    int width = 512;  ……1
    int height = 424;  ……1
    cv::Mat bodyIndexMat( height, width, CV_8UC3 );  ……2
    cv::namedWindow( "BodyIndex" );
    // Color Table
    cv::Vec3b color[6];  ……3
    color[0] = cv::Vec3b( 25500 );
    color[1] = cv::Vec3b(   02550 );
    color[2] = cv::Vec3b(   00255 );
    color[3] = cv::Vec3b( 2552550 );
    color[4] = cv::Vec3b( 2550255 );
    color[5] = cv::Vec3b(   0255255 );
    while( 1 ){
      // Frame
      IBodyIndexFrame* pBodyIndexFrame = nullptr;  ……4
      hResult = pBodyIndexReader->AcquireLatestFrame( &pBodyIndexFrame );  ……5
      if( SUCCEEDED( hResult ) ){
        unsigned int bufferSize = 0;
        unsigned char* buffer = nullptr;
        hResult = pBodyIndexFrame->AccessUnderlyingBuffer( &bufferSize, &buffer );  ……6
        if( SUCCEEDED( hResult ) ){
          for( int y = 0; y < height; y++ ){
            for( int x = 0; x < width; x++ ){
              unsigned int index = y * width + x;
              if( buffer[index] != 0xff ){
                bodyIndexMat.at<cv::Vec3b>( y, x ) = color[buffer[index]];  ……7
              }
              else{
                bodyIndexMat.at<cv::Vec3b>( y, x ) = cv::Vec3b( 000 );  ……7
              }
            }
          }
        }
      }
      SafeRelease( pBodyIndexFrame );
      // Show Window
      cv::imshow( "BodyIndex", bodyIndexMat );
      if( cv::waitKey( 30 ) == VK_ESCAPE ){
        break;
      }
    }
    列表1.4 相当于图1「Frame」,「Data」的部分
    1 BodyIndex的尺寸(512×424)。
       这里为了简化说明,画像尺寸用硬代码来设定,示例程序可以Source取得着Frame信息。
    2 为了从BodyIndex获得人体区域来绘制,使用OpenCV的cv::Mat。
    3 绘制人体区域的color table。
    4 取得BodyIndex用的Frame接口。
    5 从Reader取得最新的Frame。
    6 从Frame取得BodyIndex。
       取得保存BodyIndex数组的指针。
    7 绘制BodyIndex的人体区域。
       每个BodyIndex参照color table着色。
     
    如果可以从取得「Frame」的里获取BodyIndex的数据。
     
    取出的BodyIndex的数据像图3一样人体区域和非人体区域的按各自对应的值来填入。
     
    Kinect SDK v1的「Player」是按人体区域是「1」~「6」(因为是6个人)人体区域「0」来填入Kinect SDK v2预览版的「BodyIndex」是按照人体区域「0」~「5」,非人体領域「255(0xff)」来填入(图1)。
    图3 BodyIndex数据
     Kinect SDK v1Kinect SDK v2预览版
    名称 Player BodyIndex
    检测支持人数 6人 6人
    人体領域的値 1~6 0~5
    非人体領域的値 0 255(0xff)
    表1 Kinect SDK v1和Kinect SDK v2预览版的人体区域(Player,BodyIndex)的比较
    示例程序是,把BodyIndex的值人体区域color table的颜色(=「cv::Vec3b(BGR )」)在非人体区域用黑色(=「cv::Vec3b(000)」)进行着色来实现可视化。
     
    运行结果
    运行这个示例程序,就像图4一样,从v2预览版取得的人体区域被着色显示。
    图4 运行结果
    手指的细小形状可以清楚的分割取出。
       
    总结
    这一节是使用Kinect SDK v2预览版取得BodyIndex的示例程序的介绍,下一节是取得Body(人体姿势)的示例程序的介绍。
  • 相关阅读:
    礼物的最大价值
    复杂链表的复制
    全排列(回溯法)
    删除排序数组中的重复项
    三角形最小路径和(经典dp)
    链表中倒数第k个节点
    造成segment fault,产生core dump的可能原因
    wmpnetwk.exe怎么禁启动
    GSM/GPRS/EDGE/WCDMA/HSDPA/HSUPA--辨析
    OSI七层参考模型每一层都有哪些协议
  • 原文地址:https://www.cnblogs.com/TracePlus/p/4136368.html
Copyright © 2011-2022 走看看