Welcome

首页 / 软件开发 / .NET编程技术 / Kinect for Windows SDK开发入门(三)基础知识 下

Kinect for Windows SDK开发入门(三)基础知识 下2014-03-121. 性能改进

上文的代码中,对于每一个彩色图像帧,都会创建一个新的Bitmap对象。由于Kinect视频摄像头默认采集频率为每秒30幅,所以应用程序每秒会创建30个bitmap对象,产生30次的Bitmap内存创建,对象初始化,填充像素数据等操作。这些对象很快就会变成垃圾等待垃圾回收器进行回收。对数据量小的程序来说可能影响不是很明显,但当数据量很大时,其缺点就会显现出来。

改进方法是使用WriteableBitmap对象。它位于System.Windows.Media.Imaging命名空间下面,该对象被用来处理需要频繁更新的像素数据。当创建WriteableBitmap时,应用程序需要指定它的高度,宽度以及格式,以使得能够一次性为WriteableBitmap创建好内存,以后只需根据需要更新像素即可。

使用WriteableBitmap代码改动地方很小。下面的代码中,首先定义三个新的成员变量,一个是实际的WriteableBitmap对象,另外两个用来更新像素数据。每一幅图像的大小都是不变的,因此在创建WriteableBitmap时只需计算一次即可。

InitializeKinect方法中加粗的部分是更改的代码。创建WriteableBitmap对象,准备接收像素数据,图像的范围同时也计算了。在初始化WriteableBitmap的时候,同时也绑定了UI元素(名为ColorImageElement的Image对象)。此时WriteableBitmap中没有像素数据,所以UI上是空的。

private WriteableBitmap colorImageBitmap;private Int32Rect colorImageBitmapRect;private int colorImageStride;private byte[] colorImagePixelData;if (kinectSensor != null){ ColorImageStream colorStream=kinectSensor.ColorStream;colorStream.Enable();this.colorImageBitMap = new WriteableBitmap(colorStream.FrameWidth, colorStream.FrameHeight,96, 96, PixelFormats.Bgr32, null);this.colorImageBitmapRect = new Int32Rect(0, 0, colorStream.FrameWidth, colorStream.FrameHeight);this.colorImageStride = colorStream.FrameWidth * colorStream.FrameBytesPerPixel;ColorImageElement.Source = this.colorImageBitMap;kinectSensor.ColorFrameReady += kinectSensor_ColorFrameReady;kinectSensor.Start();}
还需要进行的一处改动是,对ColorFrameReady事件响应的代码。如下图。首先删除之前创建Bitmap那部分的代码。调用WriteableBitmap对象的WritePixels方法来更新图像。方法使用图像的矩形范围,代码像素数据的数组,图像的Stride,以及偏移(offset).偏移量通常设置为0。

private void Kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e){ using (ColorImageFrame frame = e.OpenColorImageFrame()){ if (frame != null) {byte[] pixelData = new byte[frame.PixelDataLength];frame.CopyPixelDataTo(pixelData);this.colorImageBitmap.WritePixels(this.colorImageBitmapRect, pixelData, this.colorImageStride, 0); } }}
基于Kinect的应用程序在无论是在显示ColorImageStream数据还是显示DepthImageStream数据的时候,都应该使用WriteableBitmap对象来显示帧影像。在最好的情况下,彩色数据流会每秒产生30帧彩色影像,这意味着对内存资源的消耗比较大。WriteableBitmap能够减少这种内存消耗,减少需要更新影响带来的内存开辟和回收操作。毕竟在应用中显示帧数据不是应用程序的最主要功能,所以在这方面减少内像存消耗显得很有必要。

2. 简单的图像处理

每一帧ColorImageFrame都是以字节序列的方式返回原始的像素数据。应用程序必须以这些数据创建图像。这意味这我们可以对这些原始数据进行一定的处理,然后再展示出来。下面来看看如何对获取的原始数据进行一些简单的处理。

void kinectSensor_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e){using (ColorImageFrame frame = e.OpenColorImageFrame()){if (frame != null){byte[] pixelData = new byte[frame.PixelDataLength];frame.CopyPixelDataTo(pixelData);for (int i = 0; i < pixelData.Length; i += frame.BytesPerPixel){ pixelData[i] = 0x00;//蓝色 pixelData[i + 1] = 0x00;//绿色 } this.colorImageBitMap.WritePixels(this.colorImageBitmapRect, pixelData,this.colorImageStride,0);}}}