Kinect for Windows SDK开发初体验(四)景深数据

简介:

终于可以坐下来继续这个系列了,在微博和博客园里,已经有无数人催过了,实在抱歉,一个人的精力毕竟是有限的,但我会抽出一切可用的时间,尽可能尽快完成。

这一章我们来说说景深数据Depth Data,这是Kinect的Depth Camera为我们提供的全新功能,以往的技术只能够通过图像识别来完成的一些工作,我们可以借助景深来帮我们完成了。比如,前景与背景的分离,以前只能将背景设置为蓝屏或者绿屏,但是现在有了景深数据,我们就可以很容易地将前景物体从背景中分离出来。当然,需要特别说明的是,Depth Camera技术是由以色列公司PrimeSense提供的。

程序布局

在这一章里,我们要完成的工作非常简单,根据物体距离Kinect的远近,设置成不同的颜色。首先,我们要创建一个新的WPF工程,然后添加一个Image控件:

<Image Height="240" HorizontalAlignment="Left" Margin="62,41,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="320" />

然后是MainWindow.xaml.cs中的核心代码,这部分代码与之前的代码大体一致,所以不做过多解释了:

//Kinect RuntimeRuntime 

Runtime nui = new Runtime(); 

private void Window_Loaded(object sender, RoutedEventArgs e)

{

//UseDepthAndPlayerIndex and UseSkeletalTracking

nui.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking);

//register for event

nui.DepthFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_DepthFrameReady);

//DepthAndPlayerIndex ImageType

nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240,

ImageType.DepthAndPlayerIndex);

}

private void Window_Closed(object sender, EventArgs e)

{

nui.Uninitialize();

}

 

唯一需要大家注意的是,我们在初始化函数中传递的参数是RuntimeOptions.UseDepthAndPlayerIndex,这表示景深信息中会包含PlayerIndex的信息。接下来,我们就要花点时间来理解DepthAndPlayerIndex的实际结构。

理解DepthAndPlayerIndex

先来看DepthFrameReady事件处理函数,如下:

void nui_DepthFrameReady(object sender, ImageFrameReadyEventArgs e)

{

// Convert depth information for a pixel into color information 

byte[] ColoredBytes = GenerateColoredBytes(e.ImageFrame); 

// create an image based on the colored bytes 

PlanarImage image = e.ImageFrame.Image;

image1.Source = BitmapSource.Create( 

image.Width, image.Height, 96, 96, PixelFormats.Bgr32, 

null, ColoredBytes, image.Width * PixelFormats.Bgr32.BitsPerPixel / 8); 

}

 

DepthFrameReady事件会返回一个ImageFrame对象,其中会包含一个PlanarImage对象。PlanarImage对象会包含一个byte[]数组,这个数组中包含每个像素的深度信息。这个数组的特点是,从图像左上角开始、从左到右,然后从上到下。

该数组中每个像素由两个bytes表示,我们需要通过位运算的办法来获取每个像素的位置信息。

如果是Depth Image Type,将第二个bytes左移8位即可。

Distance (0,0) = (int)(Bits[0] | Bits[1] << 8 );
 

如果是DepthAndPlayerIndex Image Type,第一个bytes右移三位去掉Player Index信息,第二个bytes左移5位。

Distance (0,0) =(int)(Bits[0] >> 3 | Bits[1] << 5);
 

DepthAndPlayerIndex image类型的第一个bytes前三位包括Player Index信息。Player Index最多包含六个可能值:

0, 没有玩家;1,玩家1;2,玩家2,以此类推。

我们可以用下面的方法来获取Player Index信息:

private static int GetPlayerIndex(byte firstFrame)

{

//returns 0 = no player, 1 = 1st player, 2 = 2nd player...

return (int)firstFrame & 7; 

}

 

设置颜色

接下来,我们创建一个bytes数组,用来存储颜色值。

if (distance <= 900)

{

//we are very close

colorFrame[index + BlueIndex] = 255;

colorFrame[index + GreenIndex] = 0;

colorFrame[index + RedIndex] = 0;

}

if (GetPlayerIndex(depthData[depthIndex]) > 0)

{

//we are the farthest

colorFrame[index + BlueIndex] = 0;

colorFrame[index + GreenIndex] = 255;

colorFrame[index + RedIndex] = 255;

}

当然,我们最好是设置几个边界值,来定义不同距离的不同颜色:

//equal coloring for monochromatic histogram

var intensity = CalculateIntensityFromDepth(distance);

colorFrame[index + BlueIndex] = intensity;

colorFrame[index + GreenIndex] = intensity;

colorFrame[index + RedIndex] = intensity;

const float MaxDepthDistance = 4000; // max value returned

const float MinDepthDistance = 850; // min value returned

const float MaxDepthDistanceOffset = MaxDepthDistance - MinDepthDistance;

public static byte CalculateIntensityFromDepth(int distance)

{

//formula for calculating monochrome intensity for histogram

return (byte)(255 - (255 * Math.Max(distance - MinDepthDistance, 0) / (MaxDepthDistanceOffset)));

}

最后,把所有代码放在一起,我们设定的颜色值为:

蓝色,小于900;900到2000,绿色;大于2000,红色

代码如下:

        private byte[] GenerateColoredBytes(ImageFrame imageFrame)
        {    
            int height = imageFrame.Image.Height;    
            int width = imageFrame.Image.Width;     
            
            //Depth data for each pixel    
            Byte[] depthData = imageFrame.Image.Bits;      
            
            //colorFrame contains color information for all pixels in image    
            //Height x Width x 4 (Red, Green, Blue, empty byte)    
            Byte[] colorFrame = new byte[imageFrame.Image.Height * imageFrame.Image.Width * 4];     
            
            //Bgr32  - Blue, Green, Red, empty byte    
            //Bgra32 - Blue, Green, Red, transparency     
            //You must set transparency for Bgra as .NET defaults a byte to 0 = fully transparent     
            //hardcoded locations to Blue, Green, Red (BGR) index positions           
            const int BlueIndex = 0;    
            const int GreenIndex = 1;    
            const int RedIndex = 2;     
            var depthIndex = 0;    
            
            for (var y = 0; y < height; y++)    
            {                
                var heightOffset = y * width;         
                
                for (var x = 0; x < width; x++)        
                {            
                    var index = ((width - x - 1) + heightOffset) * 4;             
                    
                    //var distance = GetDistance(depthData[depthIndex], depthData[depthIndex + 1]);            
                    var distance = GetDistanceWithPlayerIndex(depthData[depthIndex], depthData[depthIndex + 1]);             
                    
                    if (distance <= 900)            
                    {                
                        //we are very close                
                        colorFrame[index + BlueIndex] = 255;                
                        colorFrame[index + GreenIndex] = 0;                
                        colorFrame[index + RedIndex] = 0;                   
                    }            
                    else if (distance > 900 && distance < 2000)            
                    {                
                        //we are a bit further away                
                        colorFrame[index + BlueIndex] = 0;                
                        colorFrame[index + GreenIndex] = 255;                
                        colorFrame[index + RedIndex] = 0;            
                    }            
                    else if (distance > 2000)            
                    {                
                        //we are the farthest                
                        colorFrame[index + BlueIndex] = 0;                
                        colorFrame[index + GreenIndex] = 0;                
                        colorFrame[index + RedIndex] = 255;            
                    }             
                    
                    //Color a player            
                    if (GetPlayerIndex(depthData[depthIndex]) > 0)            
                    {                
                        //we are the farthest                
                        colorFrame[index + BlueIndex] = 0;                
                        colorFrame[index + GreenIndex] = 255;                
                        colorFrame[index + RedIndex] = 255;            
                    }             
                    
                    //jump two bytes at a time            
                    depthIndex += 2;        
                
                }    
            }     
            
            return colorFrame;
        }

程序的现实效果如下图:

clip_image001

写到最后

到这里,我们就将Kinect SDK中NUI的基本内容介绍完了,接下来,我们要介绍Audio部分,或者借助一些实际的例子,来看一下Kinect SDK的实际应用。


本文转自马宁博客园博客,原文链接:http://www.cnblogs.com/aawolf/archive/2011/08/25/2153827.html,如需转载请自行联系原作者

相关文章
|
10月前
|
开发工具 Android开发
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
928 11
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
1126 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
人工智能 自然语言处理 开发工具
HarmonyOS NEXT~鸿蒙开发能力:HarmonyOS SDK AI 全解析
本文深入解析HarmonyOS SDK中的AI功能集,涵盖分布式AI引擎、核心组件(NLP、计算机视觉等)及智能决策能力。通过代码示例与开发实践指南,帮助开发者掌握环境配置、性能调优及多场景应用(智能家居、移动办公等)。同时探讨性能优化策略与未来演进方向,助力构建高效分布式智能应用。
1416 9
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
1037 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
前端开发 JavaScript 开发工具
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
1113 5
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
存储 开发工具 开发者
揭秘 Microsoft.Docker.SDK:让容器开发更轻松的强大工具揭秘
随着云计算和容器技术的快速发展,`Docker` 已经成为容器化技术的事实标准。`Microsoft` 作为 `Docker` 的主要支持者和参与者,推出了 `Microsoft.Docker.SDK`,旨在帮助开发者更轻松地进行容器开发。本文将深入揭秘 Microsoft.Docker.SDK 的功能、使用方法以及它在容器开发中的应用。
430 13
|
JavaScript 编译器 开发工具
【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
876 2
【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
JavaScript 前端开发 Java
[Android][Framework]系统jar包,sdk的制作及引用
[Android][Framework]系统jar包,sdk的制作及引用
654 0
|
程序员 开发工具 Android开发
Android|使用阿里云推流 SDK 实现双路推流不同画面
本文记录了一种使用没有原生支持多路推流的阿里云推流 Android SDK,实现同时推送两路不同画面的流的方法。
479 7
|
Java Linux API
Android SDK
【10月更文挑战第21天】
600 1