透过 OpneNI 合并 Kinect 深度以及彩色影像数据

在前一篇的《透过OpneNI 读取Kinect 深度影像数据》里,已经解释过如何在 PC 上透过 OpenNI 来读取Kinect 的深度图了。而这一篇,则是进一步、同时读取它的深度图,以及一般的彩色影像、并将之做位置上的校正、合并。为了做到这个目的,除了上一篇有用到的 xn::DepthGenerator 外,这一篇还会用到 xn::ImageGenerator 来读取Kinect 的彩色影像数据;而另外为了修正两个摄影机的视角不同,也会用到 xn::AlternativeViewPointCapability 这个特别的Capability。

而由于这边的程序代码是基于上一个程序所修改的,所以在重复的地方,Heresy 不打算重复说明了,请自行回去参考上一篇文章的部分。而接下来,就直接先看程序代码的内容:

#include <stdlib.h>
#include <iostream>
#include <string>
#include <XnCppWrapper.h>
  
using namespace std;
void CheckOpenNIError( XnStatus eResult, string sStatus )
{
  if( eResult != XN_STATUS_OK )
    cerr << sStatus << " Error : " << xnGetStatusString( eResult ) << endl;
}
int main( int argc, char** argv )
{
  XnStatus eResult = XN_STATUS_OK;
  // 2. initial context
  xn::Context mContext;
  eResult = mContext.Init();
  CheckOpenNIError( eResult, "initialize context" );
  // 3. create depth generator
  xn::DepthGenerator mDepthGenerator;
  eResult = mDepthGenerator.Create( mContext );
  CheckOpenNIError( eResult, "Create depth generator" );
 
  // 4. create image generator
  xn::ImageGenerator mImageGenerator;
  eResult = mImageGenerator.Create( mContext );
  CheckOpenNIError( eResult, "Create image generator" );
 
  // 5. set map mode
  XnMapOutputMode mapMode;
  mapMode.nXRes = 640;
  mapMode.nYRes = 480;
  mapMode.nFPS = 30;
  eResult = mDepthGenerator.SetMapOutputMode( mapMode );
  eResult = mImageGenerator.SetMapOutputMode( mapMode );
  // 6. correct view port
  mDepthGenerator.GetAlternativeViewPointCap().SetViewPoint( mImageGenerator );
  // 7. tart generate data
  eResult = mContext.StartGeneratingAll();
  // 8. read data
  eResult = mContext.WaitNoneUpdateAll();
  if( eResult == XN_STATUS_OK )
  {
    // 9a. get the depth map
    const XnDepthPixel*  pDepthMap = mDepthGenerator.GetDepthMap();
    // 9b. get the image map
    const XnUInt8*    pImageMap = mImageGenerator.GetImageMap();
  }
  
  // 10. stop
  mContext.StopGeneratingAll();
  mContext.Shutdown();
  return 0;
}
ImageGenerator

基本上,这边的程序架构和之前单纯读取深度影像的范例是相同的。不同的地方在于,这边除了建立用来读取深度的 xn::DepthGenerator 这个node、mDepthGenerator 外,也另外建立了一个用来读取彩色影像用的 node,也就是形别是 xn::ImageGenerator 的物件 mImageGenerator。而它的使用方法基本上和 xn::DepthGenerator是相同的,一样是先宣告出他的对象后,再透过 Create() 这个成员函式来建立;程序写法的部分,可以参考上方「4. create image generator」的部分。

而同样的,在这边 Heresy 也是把彩色影像的输出模式,设定为 640 x480 @ 30FPS;而 xn::ImageGenerator 设定输出模式的方法和 xn::DepthGenerator 一样,也是呼叫 SetMapOutputMode() 做设定就可以了。(上方「5. set map mode」的部分。)

 

取得影像数据

相较于 xn::DepthGenerator 是透过 GetDepthMap() 这个函式来取得深度的影像,xn::ImageGenerator 则是透过 GetImageMap() 这个函式来取得彩色的影像数据。而在默认的情况下,这样取得的影像数据会是一个型别是XnUInt8(实际上就是 unsigned char)的const 指标,指向一个一维数组。而这个数组的大小会是 640 x 480 x 3,每三个为一组、分别代表他的 RGB 的值。

另外,也可以透过 GetRGB24ImageMap() 这个函式,来取得 XnRGB24Pixel 这种封装好的格式,不过实际使用上差异不大就是了。而如果有需要的话,image generator 也可以透过 SetPixelFormat(),来修改每一个像素的数据形式,不过在这边就不细提。

 

视角修正

接下来比较特别的地方,则是「6. correct view port 」 的部分。这边程序的目的,是要修正两个传感器取得的画面坐标,让两者画面的视角一致。为什么要做这件事呢?因为 Kinect 的深度摄影机和彩色摄影机是在不同的位置,而且镜头本身的参数也不完全相同,所以其实两个摄影机所取得的画面,是会有些微的差异的。下面就是在不修正的情况下,所抓到的画面(左边是彩色、右边是深度):

直接看的话感觉好像差不多?不过仔细看的话,是可以发现两张图的可视范围是不一样的~彩色摄影机的可视范围,基本上是比深度摄影机大一些的;而如果把两张图重迭在一起,看起来会更明显。右边的图就是直接把两张图重迭在一起的结果,可以很明显地看出来,有很多地方都没有办法对应得很好,像是天花板上的日光灯罩 和机柜上的东西,都很明显地看的出来有出入。

 

为了解决这个问题,OpenNI 有提供一个名为「Alternative View」的 Capability,可以帮助使用 OpenNI 的程序开发者,快速地修正这种视角上的不同;不过这项功能,基本上是要有支持的 production node 才可以用的就是了。

Alternative View 这个capability 的型别是 xn::AlternativeViewPointCapability,可以直接透过呼叫 ProductionNode 的「GetAlternativeViewPointCap()」来取得用来操作这项 capability 的对象;基本上 OpenNI 的所有 capability,都是以这样的形式来使用的。而以 xn::AlternativeViewPointCapability 来说,他有提供SetViewPoint() 这个函式,可以把其他的 production node 传进去、把目前这个 node 的视角改为指定 node 的视角。

而 Heresy 这边实际写成程序代码,就是:

mDepthGenerator.GetAlternativeViewPointCap().SetViewPoint( mImageGenerator );

这样写的意思,就是把 mDepthGenerator 这个 depth generator 的视角、设定成和 mImageGenerator 一样了。(注:反过来想让 image generator 根据 depth generator 调整的话,OpenNI 会当掉…)

而加上这一行后, depth generator 所抓到的画面,就会变成左下方这样的图。如果和之前没有执行过视角调整的结果相比,可以发现调整过后的结果周围的黑边明显地比较大,同时也有一些几何上的修正(四边有稍微内凹);而这样取得的结果再和彩色影像重迭在一起(右下图),则可以发现位置变得相当一致,不会有之前画面内东西不一致的问题了!

所以如果有需要要将深度和彩色影像做整合的话,应该就要记得做视角修正的动作,以避免对应的位置出错。

这一篇文章大概就先写到这里了。基本上,这边主要应该算是在讲 Alternative View 这个 capability 了~而实际上,如果有需要的话,可能也可以考虑使用 Frame-Sync 这个 capability,来让深度影像与彩色影像之间的时间差更小;不过就 Heresy 目前简单的测试看来,应该差异不大就是了,如果有需要的人,可以自己玩看看了~

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值