您的位置:首页 > 其它

Kinect深度图像滤波

2015-06-19 00:49 183 查看
最近在做机器视觉方面的一点工作,用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;其中获取深度数据为

short depth=depthPixels[i].Depth;

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

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

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

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

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


以及

//在这里将depthPixels数组中的深度值,逐元素,转换并存储到colorPixles中

//最后,将colorPixels写入colorBitmap中

int colorPixelIndex = 0;

for (int i = 0; i < depthPixels.Length; i++)

{

//获取该元素(点)的深度值

short depth = depthPixels[i].Depth;

byte intensity = (byte)255;

int newMax = depth - minDepth;

if (newMax > 0)

{intensity = (byte)(255 - (255 * newMax / (3150)));  }

this.colorPixels[colorPixelIndex++] = intensity;//blue

this.colorPixels[colorPixelIndex++] = intensity;//green

this.colorPixels[colorPixelIndex++] = intensity;//red

++colorPixelIndex;
}


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

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的大小

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


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

下篇文章将介绍基于深度值的目标分割,并附上完整代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: