Kinect深度图像滤波

from:Kinect深度图像滤波

最近在做机器视觉方面的一点工作,用Kinect作sensor获取深度数据、颜色、手势识别等。非常感激CNBlog上的两篇博文:(1)独钓寒江的http://www.cnblogs.com/yangecnu/archive/2012/03/30/KinectSDK_Geting_Started.html 从中学到了不少关于在WPF平台上使用C#,利用微软Kinect SDK开发自己的应用程序的知识,给了我很大的帮助,在此表示感谢!

但是博主独钓寒江的博文中,针对深度图像滤波,只简要说了取反和用Bgr32表示深度图像,效果不是很理想。

后来,发现了另一篇博文(2)何文西的http://www.cnblogs.com/TravelingLight/archive/2012/05/25/2517680.html介绍了国外的一篇文章,上面介绍了外国作者自己开发的两种滤波方法:像素滤波法,加权移动平均法。效果很好!可惜只有代码片段无法试验,而且滤波算法不是特别容易理解。实在可惜!

前几天偶然跟踪并找到了作者的源代码http://kinectdepthsmoothing.codeplex.com/,下载来看。运行发现,程序要求:VS2012以上、Kinect SDK 1.7以上版本,而根据独钓寒江的博文指导,其中的代码用的是SDK 1.0,进一步发现其中的一些API函数,数据类型都不相同,再者,Kinectdepthsmoothing中xaml代码用的是后台创建,而独钓寒江的博文中xaml用的是布局式,而我对xaml又不懂,如何把这两个程序结合起来呢?

由于独钓寒江的博文给出的程序中,有大量的功能实现,比如保存图像、鼠标单击显示像素深度值、彩色渲染、人体尺寸获取,游戏者索引等等,而外国朋友的kinectdepthsmoothing程序只有滤波和保存图像,那么考虑把滤波模块移植到独钓寒江的程序中,并且不改变原来的布局式界面。在移植的过程中,主要解决了以下几个类型不兼容的问题:

a) 将short[] pixelData类型改成DepthImagePixel[] pixelData,这里注意:SDK 1.8版本中,private DepthImagePixel[] depthPixels;其中获取深度数据为

 1 short depth=depthPixels[i].Depth;  

而SKD 1.0版本中,short[] pixelData获取深度数据的方式为

 1 Int32 depth =this.depthPixels[pIndex] >> DepthImageFrame.PlayerIndexBitmaskWidth; 

需要进行移位操作。而且两种方式的depth类型不一样,一个是short16位,一个是Int32位。

b) 用三通道Bgr32格式的colorBitmap存储深度图像,而不是Gray16格式的depthBitmap。除了深度数组的格式不一样之外,外国朋友的程序中,有这样几行代码值得关注,

 

1                 //获得当前帧最大和最小可用的深度值
2                 short minDepth = (short)lastDepthFrame.MinDepth;
3                 short maxDepth = (short)lastDepthFrame.MaxDepth; 

以及

复制代码
 1      //在这里将depthPixels数组中的深度值,逐元素,转换并存储到colorPixles中                 
 2 
 3                //最后,将colorPixels写入colorBitmap中                 
 4 
 5                int colorPixelIndex = 0;                 
 6 
 7                for (int i = 0; i < depthPixels.Length; i++)                 
 8 
 9                {                     
10 
11                 //获取该元素(点)的深度值                     
12 
13                 short depth = depthPixels[i].Depth;                     
14 
15                 byte intensity = (byte)255;
16 
17                 int newMax = depth - minDepth;                     
18 
19                 if (newMax > 0)                                            
20 
21                      {intensity = (byte)(255 - (255 * newMax / (3150)));  }                   
22 
23                  this.colorPixels[colorPixelIndex++] = intensity;//blue                     
24 
25                 this.colorPixels[colorPixelIndex++] = intensity;//green                     
26 
27                 this.colorPixels[colorPixelIndex++] = intensity;//red                     
28 
29                 ++colorPixelIndex;    
30              }
复制代码

  最后将数据写入colorBitmap时,代码为

1
2
3
4
5
this .colorBitmap.WritePixels(
        new Int32Rect(0, 0, this .colorBitmap.PixelWidth, this .colorBitmap.PixelHeight),
        this .colorPixels,
        this .colorBitmap.PixelWidth * sizeof ( int ),
        0);

  使用了 this.colorBitmap.PixelWidth这个写法,而不是独钓寒江博主的程序中,使用depthStream.FrameHeight创建图像的矩形区域this.depthRect = new Int32Rect(0, 0, depthStream.FrameWidth, depthStream.FrameHeight);

c) 此外,初始化变量(数据容器depthPixels和colorPixels)时,要注意colorPixels的大小

1                 this.depthPixels = new DepthImagePixel[depthStream.FramePixelDataLength];
2                 this.colorPixels = new byte[depthStream.FramePixelDataLength * sizeof(int)];

总之,将两个程序结合起来,要注意两个方面,一是界面的形式,布局还是后台创建,二是,.cs程序中由于使用的SDK版本不同,有很多API和数据类型不一致的地方,需要修改。由于正在做后续的实验,比如加入了自己的利用深度数据进行边缘检测的代码,还有很多想法没有实现,暂时写到这里吧。到时候会将完整代码上传到网络上,供大家参考!谢谢。

下篇文章将介绍基于深度值的目标分割,并附上完整代码。

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值