码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2014-12-02 01:32:36      阅读:307      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   ar   color   使用   sp   for   strong   

Kinect SDK v2预览版,取得Depth数据的方法说明。

上一节,介绍了通过使用Kinect for Windows SDK v2预览版(以下简称为Kinect SDK v2预览版)Kinect for Windows v2开发者预览版(后面称Kinect v2 预览版)取得Color的方法。
 
这一节,介绍的是从Kinect取得Depth数据的方法。
 
Depth传感器
Kinect搭载Depth传感器,可以取得Depth数据(和传感器的距离信息)。
 
Kinect v1可以读取投射的红外线pattern,pattern的变形获取Depth的信息搭载了「Light Coding」方式的Depth传感器。
 
Kinect v2预览版,通过从投射的红外线脉冲反射回来的时间来获得Depth的信息,变更为「Time of Flight(ToF)」方式的Depth传感器。
 
「Light Coding」是以色列PrimeSense公司的Depth传感技术。详细请参照专利信息,美国申请专利公开(US 2010/0118123 A1)- Depth Mapping using Projected Patterns。
 
「Time of Flight(ToF)」是美国微软公司收购的拥有Time of Flight(ToF)方式的Depth传感技术的公司(3DV Systems公司,Canesta公司),一般认为使用的是这个技术。
 
Depth数据的分辨率Kinect v1是320×240不过Kinect v2预览版提升为512×424。另外深度方向的分辨率也提高了。
可以取得Depth数据范围Kinect v1是0.8~4.0[m]的范围 Kinect v2预览版可以取得0.5~4.5[m]的范围。
 
上面说的是Default Mode的Depth数据范围。Kinect v1提供了取得近距离的Depth数据的Near Mode(0.4~3.0[m])和取得远距离Depth数据的Extended Depth(~约10.0[m])。但是偏离Default Mode的范围的Depth数据的精度会下降。
 
这节,介绍从Depth传感器取得Depth数据的方法。
bubuko.com,布布扣
图1「Light Coding」方式和「Time of Flight(ToF)」方式的差异(Depth传感器的工作原理的图像)
示例程序
 
Kinect SDK v2预览版取得Depth数据可视化展示的示例程序。上一节的介绍的数据取得阶段的摘录解说。这个示例程序的全部内容在下面的github里全部公开了。
 
bubuko.com,布布扣
图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「Sensor」的部分(重发)
1 处理Kinect v2预览版的Sensor接口。
2 取得默认的Sensor。
3 打开Sensor。
 
「Source」
从「Sensor」取得「Source」。
// Source
IDepthFrameSource* pDepthSource;  ……1
hResult = pSensor->get_DepthFrameSource( &pDepthSource );  ……2
if( FAILED( hResult ) ){
  std::cerr << "Error : IKinectSensor::get_DepthFrameSource()" << std::endl;
  return -1;
}
列表1.2 相当于图1「Source」的部分
1 取得Depth Frame的Source接口。
2 从Sensor取得Source。
 
  Kinect SDK v1要取得Depth数据主要是利用可以同时取得的Depth和Player(人体区域)的「Stream」。因此必须要有Depth数据和Player数据的分割处理。(注:Kinect SDK v1提供2种方式来处理Depth和Player Index,老的方法返回一组USHORT,通过位移分离两者;新的方法返回各为2个USHORT的结构
 
Kinect SDK v2预览版,Depth和BodyIndex(相当于Kinect SDK v1的Player)分别作为「Source」取得,关于BodyIndex在下一节介绍。
 
Kinect SDK v1也准备了取得Depth的「Stream」,因为获取Player和Skeleton(人体姿势)数据的情况也很多,主要可以同时取得Depth和Player的「Stream」。
 
「Reader」
「Source」从打开「Reader」。
// Reader
IDepthFrameReader* pDepthReader;  ……1
hResult = pDepthSource->OpenReader( &pDepthReader );  ……2
if( FAILED( hResult ) ){
  std::cerr << "Error : IDepthFrameSource::OpenReader()" << std::endl;
  return -1;
}
列表1.3 相当于图1「Reader」的部分
1 取得Depth Frame的Reader接口。
2 从Source打开Reader。
 
「Frame」~「Data」
从「Reader」取得最新的「Frame」。
int width = 512;  ……1
int height = 424;  ……1
unsigned int bufferSize = width * height * sizeof( unsigned short );  ……2
cv::Mat bufferMat( height, width, CV_16SC1 );  ……3
cv::Mat depthMat( height, width, CV_8UC1 );  ……3
cv::namedWindow( "Depth" );
while( 1 ){
  // Frame
  IDepthFrame* pDepthFrame = nullptr;  ……4
  hResult = pDepthReader->AcquireLatestFrame( &pDepthFrame );  ……5
  if( SUCCEEDED( hResult ) ){
    hResult = pDepthFrame->AccessUnderlyingBuffer( &bufferSize, reinterpret_cast<UINT16**>( &bufferMat.data ) );  ……6
    if( SUCCEEDED( hResult ) ){
      bufferMat.convertTo( depthMat, CV_8U, -255.0f / 4500.0f255.0f );  ……7
    }
  }
  SafeRelease( pDepthFrame );
  // Show Window
  cv::imshow( "Depth", depthMat );
  if( cv::waitKey( 30 ) == VK_ESCAPE ){
    break;
  }
}
列表1.4 相当于图1「Frame」,「Data」的部分
1 Depth数据的尺寸(512×424)。
   这里为了简化说明,画像尺寸用硬代码来设定,示例程序可以Source取得着Frame信息。
2 Depth数据的尺寸。
3 为了处理Depth数据而准备的OpenCV的cv::Mat类型。
 「bufferMat」是16bit的原始的Depth数据,「depthMat」为了作为图像显示,把Depth数据储存到8bit的范围里的处理。
 「CV_16SC1」,是把无符号16bit整数(16S) 放入1个channel(C1)并列来表现1个像素的数据格式。(注:应该是CV_16UC1才对)
 「CV_8UC1」,是表现无符号8bit整数  (8U)的数据格式。
4 取得Depth数据的Frame接口。
5 从Reader取得最新的Frame。
6 从Frame取得Depth数据。
   取得Depth数据存储数组的指针。这里为了Depth数据可视化,方便变化处理,cv::Mat类型来获取。
7 为了显示Depth数据图像,从16bit转换为8bit。
 
如果得到「Frame」就可以把取出Depth数据作成图像来可视化。
 
取出的Depth数据像图3一样以16bit(0~4500)为1像素来构成。
因为这样的图像不能显示(注:OpenCV只能显示8bit的图像数据),需要把格式转化为8bit(0~255)的范围。示例程序使用cv::Mat的转换命令(cv::Mat::convertTo())把离传感器距离近的显示很白(255)远的显示为很黑(0)的方式来转化。
bubuko.com,布布扣
图3 Depth数据的排列
运行结果
运行这个示例程序的话,在Kinect v2预览版取得深度图像就像图4一样。
bubuko.com,布布扣
图4 运行结果
 
总结
本节介绍了通过Kinect SDK v2预览版取得Depth数据的示例程序。下一节介绍取得BodyIndex数据的示例程序。

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

标签:style   blog   http   ar   color   使用   sp   for   strong   

原文地址:http://www.cnblogs.com/TracePlus/p/4136357.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!