Kinect v2深度测量原理

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

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数据的方法。
Kinect v2深度测量原理_第1张图片
图1「Light Coding」方式和「Time of Flight(ToF)」方式的差异(Depth传感器的工作原理的图像)
示例程序
 
Kinect SDK v2 预览版取得Depth数据可视化展示 的示例程序。上一节的介绍的数据取得阶段的摘录解说。这个示例程序的全部内容在下面的github里全部公开了。
https://github.com/UnaNancyOwen/Kinect2Sample
 
Kinect v2深度测量原理_第2张图片
图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( &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)的方式来转化。
Kinect v2深度测量原理_第3张图片
图3 Depth数据的排列
运行结果
运行这个示例程序的话,在 Kinect v2 预览版取得深度图像就像图4一样。
Kinect v2深度测量原理_第4张图片
图4 运行结果
 
总结
本节介绍了通过 Kinect SDK v2 预览版取得Depth数据的示例程序。下一节介绍取得B odyIndex数据的示例程序。

你可能感兴趣的:(ubuntu,basic)