Kinect for Windows SDK开发入门:景深数据处理 上.docx
《Kinect for Windows SDK开发入门:景深数据处理 上.docx》由会员分享,可在线阅读,更多相关《Kinect for Windows SDK开发入门:景深数据处理 上.docx(13页珍藏版)》请在三一办公上搜索。
1、译Kinect for Windows SDK开发入门(四):景深数据处理 上Kinect传感器的最主要功能之一就是能够产生三维数据,通过这些数据我们能够创建一些很酷的应用。开发Kinect应用程序之前, 最好能够了解Kinect的硬件结构。Kinect红外传感器能够探测人体以及非人体对象例如椅子或者咖啡杯。有很多商业组织和实验室正 在研究使用景深数据来探测物体。本文详细介绍了 Kinect红外传感器,景深数据格式,景深图像的获取与展示,景深图像的增强处理。1. Kinect传感器和许多输入设备不一样,Kinect能够产生三维数据,它有红外发射器和摄像头。和其他Kinect SDK如OpenN
2、I或者libfreenect 等SDK不同,微软的Kinect SDK没有提供获取原始红外数据流的方法,相反,Kinect SDK从红外摄像头获取的红外数据后,对其进 行计算处理,然后产生景深影像数据。景深影像数据从DepthlmageFrame产生,它由DepthlmageStream对象提供。DepthlmageStream 的使用和 ColorImageStream 的使用类似。DepthImageStream 和 ColorImageStream 都继承自 ImageStream。可以像从ColorImageStream获取数据生成图像那样生成景深图像。先看看将景深数据展现出来需要的步
3、骤。下面 的步骤和前面显示彩色影像数据相似:1. 创建一个新的WPF对象。2. 添加 Microsoft.Kinect.dll 对象引用。3. 添加一个Image元素到UI上,将名称改为DepthImage。4. 添加必要的发现和释放KinectSensor对象的代码。可以参照前面的文章5. 修改初始化KinectSensor对象的代码如下:private void InitializeKinectSensor(KinectSensor kinectSensor)if (kinectSensor != null)DepthImageStream depthStream = kinectSens
4、or.DepthStream;depthStream.Enable();depthImageBitMap = new WriteableBitmap(depthStream.FrameWidth, depthStream.FrameHeight,96,96,PixelFormats.Gray16, null);depthImageBitmapRect = new Int32Rect(0, 0, depthStream.FrameWidth, depthStream.FrameHeight);depthImageStride = depthStream.FrameWidth * depthStr
5、eam.FrameBytesPerPixel;DepthImage.Source = depthImageBitMap;kinectSensor.DepthFrameReady += kinectSensor_DepthFrameReady;kinectSensor.Start();6. 修改DepthFrameReady事件,代码如下:void kinectSensor_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)using (DepthImageFrame depthFrame = e.OpenDepthIm
6、ageFrame()if (depthFrame != null)short depthPixelDate = new shortdepthFrame.PixelDataLength;depthFrame.CopyPixelDataTo(depthPixelDate);depthImageBitMap.WritePixels(depthImageBitmapRect, depthPixelDate, depthImageStride, 0);运行程序,将会看到如下结果,由于一手需要截图,一手需要站在Kinect前面所以姿势不是很对,有点挫,不过人物的轮廓还是显示出 来了,在景深数据中,离Kin
7、ect越近,颜色越深,越远,颜色越淡。2. Kinect深度测量原理和其他摄像机一样,近红外摄像机也有视场。Kinect摄像机的视野是有限的,如下图所示如图,红外摄像机的视场是金字塔形状的。离摄像机远的物体比近的物体拥有更大的视场横截面积。这意味着影像的高度和宽度,比 如640X480和摄像机视场的物理位置并不一一对应。但是每个像素的深度值是和视场中物体离摄像机的距离是对应的。深度帧数据中, 每个像素占16位,这样BytesPerPixel属性,即每一个像素占2个字节。每一个像素的深度值只占用了 16个位中的13个位。如下图:0000 1010 1101 011115211187430|Dep
8、th 田饮Player Index获取每一个像素的距离很容易,但是要直接使用还需要做一些位操作。可能大家在实际编程中很少情况会用到位运算。如上图所示, 深度值存储在第3至15位中,要获取能够直接使用的深度数据需要向右移位,将游戏者索引(Player Index)位移除。后面将会介绍游 戏者索引位的重要性。下面的代码简要描述了如何获取像素的深度值。代码中pixelData变量就是从深度帧数据中获取的short数组。 PixelIndex基于待计算像素的位置就算出来的。SDK在DepthImageFrame类中定义了一个常量PlayerIndexBitmaskWidth,它 定义了要获取深度数据值
9、需要向右移动的位数。在编写代码时应该使用这一常量而不是硬编码,因为未来随着软硬件水平的提高,Kinect 可能会增加能够同时识别人数的个数,从而改变PlayerIndexBitmaskWidth常量的值。Int32 pixelIndex = (Int32)(p.X + (Int32)p.Y * frame.Width);Int32 depth = this.depthPixelDatepixelIndex DepthImageFrame.PlayerIndexBitmaskWidth;显示深度数据最简单的方式是将其打印出来。我们要将像素的深度值显示到界面上,当鼠标点击时,显示鼠标点击的位置的像
10、素的深 度值。第一步是在主UI界面上添加一个TextBlock:接着我们要处理鼠标点击事件。在添加该事件前,需要首先添加一个私有变量lastDepthFrame来保存每一次DepthFrameReady 事件触发时获取到的DepthFrame值。因为我们保存了对最后一个DepthFrame对象的引用,所以事件处理代码不会马上释放该对象。 然后,注册DepthFrame图像控件的MouseLeftButtonUp事件。当用户点击深度图像时,DepthImage_MouseLeftButtonUp事件 就会触发,根据鼠标位置获取正确的像素。最后一步将获取到的像素值的深度值显示到界面上,代码如下:v
11、oid kinectSensor_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)if (lastDepthFrame! = null)lastDepthFrame.Dispose();lastDepthFrame = null;lastDepthFrame = e.OpenDepthImageFrame();if (lastDepthFrame != null)depthPixelDate = new shortlastDepthFrame.PixelDataLength;lastDepthFrame.CopyPi
12、xelDataTo(depthPixelDate);depthImageBitMap.WritePixels(depthImageBitmapRect, depthPixelDate, depthImageStride, 0);private void DepthImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)Point p = e.GetPosition(DepthImage);if (depthPixelDate != null & depthPixelDate.Length 0)Int32 pixelIndex
13、= (Int32)(p.X + (Int32)p.Y * this.lastDepthFrame.Width);Int32 depth = this.depthPixelDatepixelIndex DepthImageFrame.PlayerIndexBitmaskWidth;Int32 depthInches = (Int32)(depth * 0.0393700787);Int32 depthFt = depthInches / 12;depthInches = depthInches % 12;PixelDepth.Text = String.Format(0mm12, depth,
14、depthFt, depthInches);有一点值得注意的是,在UI界面中Image空间的属性中,宽度和高度是硬编码的。如果不设置值,那么空间会随着父容器(From窗 体)的大小进行缩放,如果空间的长宽尺寸和深度数据帧的尺寸不一致,当鼠标点击图片时,代码就会返回错误的数据,在某些情况下甚至会抛出异常。像素数组中的数据是固定大小的,它是根据DepthImageStream的Enable方法中的DepthImageFormat参数值 来确定的。如果不设置图像控件的大小,那么他就会根据Form窗体的大小进行缩放,这样就需要进行额外的计算,将鼠标的在Form中的位置换算到深度数据帧的维度上。这种缩放
15、和空间转换操作很常见,在后面的文章中我们将会进行讨论,现在为了简单,对图像控 件的尺寸进行硬编码。结果如下图,由于截屏时截不到鼠标符号,所以用红色点代表鼠标位置,下面最左边图片中的红色点位于墙上,该点距离Kinect 2.905米,中间图的点在我的手上,可以看出手离Kinect距离为1.221米,实际距离和这个很相近,可见Kinect的景深数据还是很准确的。2905mm991221mm44上面最右边图中白色点的深度数据为-1mm。这表示Kinect不能够确定该像素的深度。在处理上数据时,这个值通常是一个特殊值,可 以忽略。-1深度值可能是物体离Kinect传感器太近了的缘故。3.深度影像增强在
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Kinect for Windows SDK开发入门:景深数据处理 SDK 开发 入门 景深 数据处理
链接地址:https://www.31ppt.com/p-4885815.html