Kinect for Windows SDK开发入门十四进阶指引 上.docx
- 文档编号:2592286
- 上传时间:2023-05-04
- 格式:DOCX
- 页数:24
- 大小:231.02KB
Kinect for Windows SDK开发入门十四进阶指引 上.docx
《Kinect for Windows SDK开发入门十四进阶指引 上.docx》由会员分享,可在线阅读,更多相关《Kinect for Windows SDK开发入门十四进阶指引 上.docx(24页珍藏版)》请在冰点文库上搜索。
KinectforWindowsSDK开发入门十四进阶指引上
[译]KinectforWindowsSDK开发入门(十四):
进阶指引上
前面十三篇文章介绍了KinectSDK开发中的各个方面的最基础的知识。
正如本系列博闻标题那样,这些知识只是KinectforwindowsSDK开发的入门知识。
本文将会介绍Kinect进阶开发需要了解一些知识(beyondthebasic)。
读者可能会注意到,在学习了前面十三篇文章中关于Kinect开发的方方面面,如影像数据流、景深摄像机、骨骼追踪、麦克风阵列、语音识别等这些知识后,离开发出一些我们在网上看到的那些具有良好用户体验的Kinect应用程序还是显得捉襟见肘。
KinectSDK在某种意义上只是提供了一些其它Kinect类库的相同或者更好的功能。
为了进一步提高KinectforWindows应用程序的应用体验,我们需要了解一些其他的和Kinect有关的开发技术和类库。
Kinect的真正应用潜力是和其他技术进行整合。
本文将会介绍一些第三方类库如何来帮助处理Kinect传感器提供的数据。
使用不同的技术进行Kinect开发,可以发掘出Kinect应用的强大功能。
另一方面如果不使用这些为了特定处理目的而开发的一些类库,而是自己实现这些逻辑的话,代码可能会比较混乱和不稳定。
本文只是简单的介绍这些第三方类库并给以适当的引导。
Kinect开发最大的困难不是什么技术,而是知道什么样技术能够被用到Kinect开发中。
一旦了解了什么技术能够使用,Kinect可能开发的应用就会出现巨大的潜力。
本文中介绍的一些技术可能覆盖面不够广,有可能有些类库很重要但是本文没有涉及到,Kinect开发方面的技术变化的非常快,这一点也难以避免,欢迎大家能够补充。
但是通过介绍一些基本的帮助类库,图像处理类库等,希望大家了解到这些技术的重要性以及对Kinect开发的作用。
可能随着技术的发展,这些类库可能有些变化,但是相关的技术领域相信还是一样的,本文只是起到一个抛砖引玉的作用。
本文及下篇文章将会介绍几个有用的工具及类库,包括Coding4FunKinectToolkit,Emgu(OpenCV计算机视觉库的C#版本)和Blender。
只是非常简单的介绍了Unity3D游戏框架,FAAST手势识别中间件以及MicrosoftRoboticsDeveloperStudio。
这些知识如果大家感兴趣的话可能要花一定的精力去了解和掌握,这里只是简单介绍。
1.影像处理帮助类
有很多影像处理相关的类库可以使用。
单单在.NETFramework中,就有PresentationCore.dll中的System.Windows.Media.Drawing抽象类以及System.Drawing.dll中System.Drawing命名空间下的类可以使用。
更复杂的是,在System.Windows和System.Drawing命名空间下有一些相互独立的处理形状(shape)和颜色(color)的类。
有时候一个类库中的方法能够进行一些图像处理而其它类库中却没有类似的方法。
为了方便,各种图形对象之间的转换显得很有必要。
当引入Kinect后,情况变得更加复杂。
Kinect有自己的影像数据流,如ImageFrame。
为了能够使Kinect这些专有的影像对象能够和WPF一同使用,ImageFrame对象必须转换为ImageSource类型,该对象在System.Windows.Media.Imaging命名空间中。
第三方影像处理库并不知道System.Windows.Media命名空间中的对象,但是知道System.Drawing命名空间,为了能够使用Emgu处理Kinect中产生的数据,需要将Microsoft.Kinect中的某些数据类型转化为System.Drawing类型,然后将System.Drawing类型转换到Emgu中的类型,在Emgu中处理完之后,再转换回System.Drawing类型,最后再转换为System.Windows.Media类型来共WPF使用。
1.1Coding4FunKinect工具类
Coding4FunKinectToolkit为将一些类型从一种类库转换到其他类库中的对应类型的提供了一些便利。
这个工具集可以从该开源工具集官网 上下载。
它包括3个独立的dll。
其中Coding4Fun.Kinect.Wpf.dll提供了一系列扩展方法来在Microsoft.Kinect和System.Windows.Media之间进行转换。
而Coding4Fun.Kinect.WinForm.dll提供了一系列扩展方法来在Microsoft.Kinect和System.Drawing之间进行转换。
System.Drawing是.NET图形库中的dll。
他包含了WinForm中用来进行绘图和展现所需的元素,而WPF中所需要的展现元素包含在System.Windows.Media中。
遗憾的是Coding4FunKinectToolkit并没有提供在System.Drawing命名空间和System.Windows.Media命名空间之间对应对象的转换方法。
这是因为Toolkit的最初目的是方便简单的编写KinectDemo程序而不是提供一个通用的在不同的图像类型之间进行转换的类库。
所以,一些可能在WPF中要用到的方法可能存在于WinForm的dll中。
一些非常有用的,复杂的处理景深数据流中景深影像数据的方法被封装到了一些简单的将Kinect图像类型转换为WPFImageSource的对象中去了。
但是Coding4FunKinectToolKit有两个比较好的地方可以取消上面的疑虑。
一个就是,他是开源的,源代码可以下载并查看。
可以通过源码查看Coding4Fun团队是如何在图像处理内部使用字节数组的。
你可以在这些代码中看到前面博文中代码的影子,类库中的一些小的技巧非常有帮助。
第二就是这些方法都是扩展方法,可以很方便的进行扩充。
扩展方法是一种语法糖,它使得一个独立的方法看起来像是被附加到一个类型上一样。
比如,有一个方法AddOne可以将当前的值加1。
这个方法可以改写为一个扩展方法。
只需要简单的将该方法设置为静态的,并在Int32类型前加this即可。
代码如下,然后调用AddOne(3)这个方法可以简单的改写为3.AddOne()
publicintAddOne(inti)
{
returni+1;
}
publicstaticclassmyExtensions
{
publicstaticintAddOne(thisinti)
{
returni+1;
}
}
为了使用扩展方法库,必须引用这个方法所在的类库。
包含扩展方法的静态类(myExtensions类)实际是被忽略的。
使用扩展方法将一种image类型转换到另外一种image类型,可以简单的使用如下类似的代码进行操作。
varbitmapSource=imageFrame.ToBitmapSource();
image1.Source=bitmapSource;
下图是Coding4FunKinectToolkit中的一些扩展方法,使用这些方法可以简化我们的Kinect开发。
但是在开发实践中,我们应该考虑建立我们自己的帮助方法类库。
这可以扩充Coding4Fun类库中所没有提供的功能。
更重要的是,因为Coding4Fun的一些方法隐藏了处理深度影像数据的复杂性,有时候可能并不像你所期望的那样工作。
隐藏复杂性是这些类库设计的初衷,但是当你使用时可能会感到困惑,比如当你使用Coding4FunToolkit中提供的方法来处理景深数据流时,e.ImageFrame.ToBitmapSource()返回的值可能和e.ImageFrame.Bits.ToBitmapSource(e.ImageFrame.Image.With,e.ImageFrame.Image.Height)产生的返回值不同。
可以建立自己的扩展方法类库来方便Kinect开发,可以使你明确的使用自己的扩展方法来达到自己想要的结果。
1.2创建自己的扩展方法库
我们可以建立自己的扩展方法。
在前面的文章中我们讲述了如何建立一个图像操作项目的扩展方法。
这些方法的目的是帮助我们从经常用的System.Drawing命名空间的类型转换到WPF中的System.Windows.Media命名空间中去,这能够为第三方图像处理类库和WPF应用程序之间提供桥梁。
这些扩展方法是一些标准的处理Bitmap和BitmapSource对象的方法。
一些方法也可以在Coding4FunKinectToolkit中找到。
为了演示方便,我们在这里建立一个类而不是类库来包含我们想要的扩展方法,在其他项目中如果需要使用这个类中的扩展方法,只需要将该类拷贝过去即可。
1.2.1创建一个WPF项目
现在我们创建一个简单的WPF项目来建立对扩展方法类的测试。
项目的MainWindows.xaml前台代码如下,页面上包含有名为rgbImage和depthImage的两个Image对象。
Class="ImageLibrarySamples.MainWindow" xmlns=" xmlns: x=" Title="ImageLibrarySamples"> 现在来编写后台代码,与之前的类似,首先添加对Microsoft.Kinect.dll引用,然后声明KinectSensor对象并在MainWindows的构造函数中实例化,代码如下所示。 实例化KinectSensor对象,处理ColorFrameReady和DepthFrameReady事件,然后打开color和depth数据流。 Microsoft.Kinect.KinectSensor_kinectSensor; publicMainWindow() { InitializeComponent(); this.Unloaded+=delegate { _kinectSensor.ColorStream.Disable(); _kinectSensor.DepthStream.Disable(); }; this.Loaded+=delegate { _kinectSensor=KinectSensor.KinectSensors[0]; _kinectSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30); _kinectSensor.DepthStream.Enable(DepthImageFormat.Resolution320x240Fps30); _kinectSensor.ColorFrameReady+=ColorFrameReady; _kinectSensor.DepthFrameReady+=DepthFrameReady; _kinectSensor.Start(); }; } voidDepthFrameReady(objectsender,DepthImageFrameReadyEventArgse) { } voidColorFrameReady(objectsender,ColorImageFrameReadyEventArgse) { } 1.2.2创建类及扩展方法 在项目中创建一个新的名为ImageExtensions.cs的类来包含扩展方法。 这个类的实际名字并不重要,需要用到的只是命名空间。 在下面的代码中,我们使用的命名空间是ImageManipulationExtensionMethods。 另外,还需要添加对System.Drawing.dll的引用。 如前所述,System.Drawing和System.Windows.Media中有些类的名称是一样的。 为了消除命名空间的冲突,我们必须选取一个作为默认的命名空间。 在下面的代码中,我们将System.Drawing作为默认的命名空间,而给System.Windows.Media起了一个名为Media的别名。 最后,我们为最重要的两个图像转换创建了扩展方法。 一个是将字节序列(bytearray)转换为Bitmap对象,另一个是将字节序列(bytearray)转换为BitmapSource对象。 这两个扩展方法会用到彩色图像的显示中。 我们还创建了另外两个扩展方法,通过这些方法中的字节序列替换短字节序列(shortarray)来对深度影像进行变换,因为深度影像数据是由short类型而不是byte类型组成的。 namespaceImageManipulationExtensionMethods { publicstaticclassImageExtensions { publicstaticBitmapToBitmap(thisbyte[]data,intwidth,intheight PixelFormatformat) { varbitmap=newBitmap(width,height,format); varbitmapData=bitmap.LockBits( newSystem.Drawing.Rectangle(0,0,bitmap.Width,bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); Marshal.Copy(data,0,bitmapData.Scan0,data.Length); bitmap.UnlockBits(bitmapData); returnbitmap; } publicstaticBitmapToBitmap(thisshort[]data,intwidth,intheight PixelFormatformat) { varbitmap=newBitmap(width,height,format); varbitmapData=bitmap.LockBits( newSystem.Drawing.Rectangle(0,0,bitmap.Width,bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); Marshal.Copy(data,0,bitmapData.Scan0,data.Length); bitmap.UnlockBits(bitmapData); returnbitmap; } publicstaticMedia.Imaging.BitmapSourceToBitmapSource(thisbyte[]data Media.PixelFormatformat,intwidth,intheight) { returnMedia.Imaging.BitmapSource.Create(width,height,96,96 format,null,data,width*format.BitsPerPixel/8); } publicstaticMedia.Imaging.BitmapSourceToBitmapSource(thisshort[]data Media.PixelFormatformat,intwidth,intheight) { returnMedia.Imaging.BitmapSource.Create(width,height,96,96 format,null,data,width*format.BitsPerPixel/8); } } } 1.2.3创建其它的扩展方法 现在影像流和深度流数据的字节序列都可以通过从ColorImageFrame和DepthImageFrame类型获取。 我们还可以创建一些额外的扩展方法来处理这些类型而不是字节序列。 获取bit序列数据并将其转换为Bitmap或者BitmapSource类型过程中,最重要的因素是考虑像元的格式。 影像数据流返回的是一系列32位的RGB影像,深度数据流返回的是一系列16位的RGB影像。 在下面的代码中,我们使用没有透明值的32个字节的影像数据作为默认的数据类型,也就是说,影像数据流可以简单的调用ToBitmap或者ToBitmapSource方法,其他扩展方法的名称应该给予影像数据格式一些提示。 //bitmapmethods publicstaticBitmapToBitmap(thisColorImageFrameimage,PixelFormatformat) { if(image==null||image.PixelDataLength==0) returnnull; vardata=newbyte[image.PixelDataLength]; image.CopyPixelDataTo(data); returndata.ToBitmap(image.Width,image.Height format); } publicstaticBitmapToBitmap(thisDepthImageFrameimage,PixelFormatformat) { if(image==null||image.PixelDataLength==0) returnnull; vardata=newshort[image.PixelDataLength]; image.CopyPixelDataTo(data); returndata.ToBitmap(image.Width,image.Height format); } publicstaticBitmapToBitmap(thisColorImageFrameimage) { returnimage.ToBitmap(PixelFormat.Format32bppRgb); } publicstaticBitmapToBitmap(thisDepthImageFrameimage) { returnimage.ToBitmap(PixelFormat.Format16bppRgb565); } //bitmapsourcemethods publicstaticMedia.Imaging.BitmapSourceToBitmapSource(thisColorImageFrameimage) { if(image==null||image.PixelDataLength==0) returnnull; vardata=newbyte[image.PixelDataLength]; image.CopyPixelDataTo(data); returndata.ToBitmapSource(Media.PixelFormats.Bgr32,image.Width,image.Height); } publicstaticMedia.Imaging.BitmapSourceToBitmapSource(thisDepthImageFrameimage) { if(image==null||image.PixelDataLength==0) returnnull; vardata=newshort[image.PixelDataLength]; image.CopyPixelDataTo(data); returndata.ToBitmapSource(Media.PixelFormats.Bgr555,image.Width,image.Height); } publicstaticMedia.Imaging.BitmapSourceToTransparentBitmapSource(thisbyte[]data intwidth,intheight) { returndata.ToBitmapSource(Media.PixelFormats.Bgra32,width,height); } 注意到上面的代码中有三种不同的像元格式。 Bgr32格式就是32位彩色影像,它由RGB三个通道。 Bgra32也是32位,但是她使用了第四个称之为alpha的通道,用来表示透明度。 最后Bgr555是16位影像格式。 在之前的深度影像处理那篇文章中,深度影像中的每一个像元都代表2个字节,555代表红绿蓝三个通道每一个通道占用5位。 在深度影像处理中,也可以使用Bgr565格式,这种格式中绿色通道占用6位,你也可以添加一个使用这种格式的扩展方法。 1.2.4调用扩展方法 为了在之前的MainWindows的后台代码中使用之前写的扩展方法,我们首先需要添加ImageManipulationExtensionMethods命名空间,这是扩展方法所在的命名空间。 现在利用这些扩展方法,我们能够方便的将影像和深度数据转换为字节数组了,如下代码: voidDepthFrameReady(objectsender,DepthImageFrameReadyEventArgse) { this.depthImage.Source=e.OpenDepthImageFrame().ToBitmap().ToBitmapSource(); } voidColorFrameReady(objectsender,ColorImageFrameReadyEventArgse) { this.rgbImage.Source=e.OpenColo
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Kinect for Windows SDK开发入门十四进阶指引 SDK 开发 入门 十四 进阶 指引