Kinect 开发 —— ColorBasic
创建一个Kincet项目通常需要:
1. 创建一个VS项目,一般为了展示通常创建一个wpf项目。
2. 添加Microsoft.Kinect.dll引用,如果是早期版本的SDK,这个名称可能不同。
3. 引入Kinect命名空间。
Kinect支持3中类型的托管应用程序,分别是:控制台应用程序,WPF以及Windows Form应用程序。
首先来创建一个Windows 控制台应用程序,然后在Main函数所在的代码中引入Kinect命名控件,代码如下:
using Microsoft.Kinect;
static void Main(string[] args)
{
//初始化sensor实例
KinectSensor sensor = KinectSensor.KinectSensors[]; //初始化照相机
sensor.DepthStream.Enable();
sensor.DepthFrameReady += new EventHandler<DepthImageFrameReadyEventArgs>(sensor_DepthFrameReady); // 注册事件,sensor_DepthFrameReady事件函数 Console.ForegroundColor=ConsoleColor.Green; //打开数据流
sensor.Start(); while (Console.ReadKey().Key != ConsoleKey.Spacebar)
{ }
} static void sensor_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
using (var depthFrame=e.OpenDepthImageFrame())
{
if (depthFrame == null) return;
short[] bits = new short[depthFrame.PixelDataLength];
depthFrame.CopyPixelDataTo(bits);
foreach (var bit in bits)
Console.Write(bit);
}
}
基于Kinect开发的应用程序最开始需要用到的对象就是KinectSensor对象,该对象直接表示Kinect硬件设备。KinectSensor对象是我们想要获取数据,包括彩色影像数据,景深数据和骨骼追踪数据的源头。
从KinectSensor获取数据最常用的方式是通过监听该对象的一系列事件。每一种数据流都有对应的事件,当改类型数据流可用时,就会触发改时间。
每一种数据流(Color,Depth,Skeleton)都是以数据点的方式在不同的坐标系中显示的,在后面的讨论中我们能够清楚的看到这一点。将一个数据流中的点数据转换到另一个数据流中是一个很常见的操作,KinectSensor对象有一些列的方法能够进行数据流到数据点阵的转换,他们是MapDepthToColorImagePoint,MapDepthToSkeletonPoint以及MapSkeletonPointToDepth。
1,发现连接的Kinect设备
KinectObject对象没有公共的构造器,应用程序不能直接创建它。相反,该对象是SDK在探测到有连接的Kinect设备时创建的。当有Kinect设备连接到计算机上时,应用程序应该得到通知或者提醒。KinectSeneor对象有一个静态的属性KinectSensors,该属性是一个KinectSensorCollection集合,该集合继承自ReadOnlyCollection,ReadOnlyCollection集合很简单,他只有一个索引器和一个称之为StatusChanged的事件。
只有设备在Connected状态下时,KinectSensor对象才能初始化。在应用的整个生命周期中,传感器的状态可能会发生变化,这意味着我们开发的应用程序必须监控设备的连接状态,并且在设备连接状态发生变化时能够采取相应的措施来提高用户体验。
public partial class MainWindow : Window
{
//私有Kinectsensor对象
private KinectSensor kinect; public KinectSensor Kinect // 为私有变量提供存取接口
{
get { return this.kinect;}
set {
//如果带赋值的传感器和目前的不一样
if (this.kinect!=value)
{
//如果当前的传感对象不为null
if (this.kinect!=null)
{
//uninitailize当前对象
this.kinect=null;
}
//如果传入的对象不为空,且状态为连接状态
if (value!=null&&value.Status==KinectStatus.Connected)
{
this.kinect=value;
}
}
}
} public MainWindow() //构造函数
{
InitializeComponent();
this.Loaded += (s, e) => DiscoverKinectSensor();
this.Unloaded += (s, e) => this.kinect = null;
} private void DiscoverKinectSensor()
{
KinectSensor.KinectSensors.StatusChanged += KinectSensors_StatusChanged;
this.Kinect = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
} private void KinectSensors_StatusChanged(object sender, StatusChangedEventArgs e)
{
switch (e.Status)
{
case KinectStatus.Connected:
if (this.kinect == null)
this.kinect = e.Sensor;
break;
case KinectStatus.Disconnected:
if (this.kinect == e.Sensor)
{
this.kinect = null;
this.kinect = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
if (this.kinect == null)
{
//TODO:通知用于Kinect已拔出
}
}
break;
//TODO:处理其他情况下的状态
}
}
}
在构造函数中有两个匿名方法,一个用来监听Loaded事件,一个用来监听Unloaded事件。当卸载时应该将Kinect属性置为空。在窗口的Loaded事件中程序通过DiscoverKinectSensor方法试图调用一个连接了的传感器。在窗体的Loaded和Unloaded事件中注册这两个事件用来初始化和释放Kinect对象,如果应用程序没有找到Kinect对象,将会通知用户。
this.Loaded += (s, e) => DiscoverKinectSensor();
DiscoverKinectSensor方法只有两行代码,第一行代码注册StatusChanged事件,第二行代码通过lambda表达式查询集合中第一个处在Connected状态的传感器对象,并将该对象复制给Kinect属性。Kinect属性的set方法确保能都赋值一个合法的Kinect对象。
StatusChanged事件中值得注意的是,当状态为KinectSensor.Connected的时候,if语句限制了应用程序只能有一个kinect传感器,他忽略了电脑中可能连接的其他Kinect传感器。
2 打开传感器
一旦发现了传感器,在应用程序能够使用传感器之前必须对其进行初始化。传感器的初始化包括三个步骤。首先,应用程序必须设置需要使用的数据流,并将其状态设为可用。每一中类型的数据流都有一个Enable方法,该方法可以初始化数据流。每一种数据流都完全不同,在使用之前需要进行一些列的设置。在一些情况下这些设置都在Enable方法中处理了。
初始化之后,接下来就是要确定应用程序如何使用产生的数据流。最常用的方式是使用Kinect对象的一些列事件,每一种数据流都有对应的事件,他们是:ColorImageStream对应ColorFrameReady事件、DepthImageStream对应DepthFrameReady事件、SkeletonStream对象对应SkeletonFrameReady事件。以及AllFramesReady事件。各自对应的事件只有在对应的数据流enabled后才能使用,AllFramesReady事件在任何一个数据流状态enabled时就能使用。
最后,应用程序调用KinectSensor对象的Start方法后,frame-ready事件就会触发从而产生数据。
3 停止传感器
一旦传感器打开后,可以使用KinectSensor对象的Stop方法停止。这样所有的数据产生都会停止,因此在监听frameready事件时要先检查传感器是否不为null。
KinectSensor对象以及数据流都会使用系统资源,应用程序在不需要使用KinectSensor对象时必须能够合理的释放这些资源。在这种情况下,程序不仅要停止传单器,还用注销frameready事件。注意,不要去调用KinectSensor对象的Dispose方法。这将会阻止应用程序再次获取传感器。应用程序必须从启或者将Kinect从新拔出然后插入才能再次获得并使用对象。
private void WindowLoaded(object sender, RoutedEventArgs e) // 窗口加载事件函数
{
foreach (var potentialSensor in KinectSensor.KinectSensors)
{
if (potentialSensor.Status == KinectStatus.Connected)
{
this.sensor = potentialSensor;
break;
}
} if (null != this.sensor)
{
// Turn on the color stream to receive color frames
this.sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30); // Allocate space to put the pixels we'll receive
this.colorPixels = new byte[this.sensor.ColorStream.FramePixelDataLength]; // This is the bitmap we'll display on-screen
this.colorBitmap = new WriteableBitmap(this.sensor.ColorStream.FrameWidth, this.sensor.ColorStream.FrameHeight, 96.0, 96.0, PixelFormats.Bgr32, null);
// 位图宽度,高度,水平分辨率,垂直分辨率,System.Windows.Media.PixelFormat,Palette // Set the image we display to point to the bitmap where we'll put the image data
this.Image.Source = this.colorBitmap; // Add an event handler to be called whenever there is new color frame data
this.sensor.ColorFrameReady += this.SensorColorFrameReady; // Start the sensor!
try
{
this.sensor.Start();
}
catch (IOException)
{
this.sensor = null;
}
} if (null == this.sensor)
{
this.statusBarText.Text = Properties.Resources.NoKinectReady;
}
}
private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (null != this.sensor)
{
this.sensor.Stop();
}
}
private void SensorColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame != null)
{
// Copy the pixel data from the image to a temporary array
colorFrame.CopyPixelDataTo(this.colorPixels); // 需要临时byte数组 // Write the pixel data into our bitmap
this.colorBitmap.WritePixels(
new Int32Rect(, , this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight),
this.colorPixels,
this.colorBitmap.PixelWidth * sizeof(int),
);
}
}
}
private void ButtonScreenshotClick(object sender, RoutedEventArgs e) // 截屏事件处理
{
if (null == this.sensor)
{
this.statusBarText.Text = Properties.Resources.ConnectDeviceFirst; // 状态栏
return;
} // create a png bitmap encoder which knows how to save a .png file
BitmapEncoder encoder = new PngBitmapEncoder(); // create frame from the writable bitmap and add to encoder
encoder.Frames.Add(BitmapFrame.Create(this.colorBitmap)); string time = System.DateTime.Now.ToString("hh'-'mm'-'ss", CultureInfo.CurrentUICulture.DateTimeFormat); string myPhotos = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); string path = Path.Combine(myPhotos, "KinectSnapshot-" + time + ".png"); // write the new file to disk
try
{
using (FileStream fs = new FileStream(path, FileMode.Create))
{
encoder.Save(fs);
} this.statusBarText.Text = string.Format(CultureInfo.InvariantCulture, "{0} {1}", Properties.Resources.ScreenshotWriteSuccess, path);
}
catch (IOException)
{
this.statusBarText.Text = string.Format(CultureInfo.InvariantCulture, "{0} {1}", Properties.Resources.ScreenshotWriteFailed, path);
}
}
由于第一次编WPF ,倒持半天,总算弄好了~~
Kinect 开发 —— ColorBasic的更多相关文章
- Kinect开发文章目录
整理了一下去年为止到现在写的和翻译的Kinect的相关文章,方便大家查看.另外,最近京东上微软在搞活动, 微软 Kinect for Windows 京东十周年专供礼包 ,如果您想从事Kinect开发 ...
- Kinect开发资源汇总
Kinect开发资源汇总 转自: http://www.sigvc.org/bbs/forum.php?mod=viewthread&tid=254&highlight=kinec ...
- Kinect开发学习笔记之(一)Kinect介绍和应用
Kinect开发学习笔记之(一)Kinect介绍和应用 zouxy09@qq.com http://blog.csdn.net/zouxy09 一.Kinect简单介绍 Kinectfor Xbox ...
- Kinect开发笔记之二Kinect for Windows 2.0新功能
这是本博客翻译文档的第一篇文章.笔者已经苦逼的竭尽全力的在翻译了.但无奈英语水平也是非常有限.不正确或者不妥当不准确的地方必定会有,还恳请大家留言或者邮件我以批评指正.我会虚心接受. 谢谢大家. ...
- Kinect 开发 —— 杂一
Kinect 提供了非托管(C++)和托管(.NET)两种开发方式的SDK,如果您用C++开发的话,需要安装Speech Runtime(V11),Kinect for Windows Runtime ...
- Kinect 开发 —— 控制PPT播放
实现Kinect控制幻灯片播放很简单,主要思路是:使用Kinect捕捉人体动作,然后根据识别出来的动作向系统发出点击向前,向后按键的事件,从而使得幻灯片能够切换. 这里的核心功能在于手势的识别,我们在 ...
- Kinect 开发 —— 全息图
Kinect的另一个有趣的应用是伪全息图(pseudo-hologram).3D图像可以根据人物在Kinect前面的各种位置进行倾斜和移动.如果方法够好,可以营造出3D控件中3D图像的效果,这样可以用 ...
- Kinect 开发 —— 进阶指引(上)
本文将会介绍一些第三方类库如何来帮助处理Kinect传感器提供的数据.使用不同的技术进行Kinect开发,可以发掘出Kinect应用的强大功能.另一方面如果不使用这些为了特定处理目的而开发的一些类库, ...
- Kinect开发 —— 基础知识
转自:http://www.cnblogs.com/yangecnu/archive/2012/04/02/KinectSDK_Application_Fundamentals_Part2.html ...
随机推荐
- linux中的swap
1. 也许你会经常遇到一个经典的swap大小设置问题(比如狗血的面试题). 很多人多会说内存的2倍.. 但是个人认为一般而言 swap 不要设置太大,最好不要超过4G. 2. 进程申请内存不足时,发现 ...
- 运行npm start vue.js项目 出现 npm ERR! missing script: start 错误
npm ERR! missing script: start 错误 有可能缺少依赖包,运行nmp install安装依赖(一般都依赖很多包,过程有点慢),安装完后发现多一个 node_modules文 ...
- error:assign attribute must be unsafeunretained
今天在使用协议的过程中.偶然发现这样使用 ? 1 2 3 4 5 6 7 8 9 10 @interface AppDelegate (){ id<chatdelegate> t ...
- 使用Hadoop ACL 控制訪问权限
使用Hadoop ACL 控制訪问权限 一.HDFS訪问控制 hdfs-site.xml设置启动acl <property> <name>dfs.permissions.en ...
- mediawiki使用笔记
https://www.cnblogs.com/ToDoToTry/p/4475067.html
- POJ 1895 分层图网络流+输出路径
题意: 题目描述:在公元3141年人类的足迹已经遍布银河系.为了穿越那巨大的距离,人类发明了一种名为超时空轨道的技术.超时空轨道是双向的,连接两个星系,穿越轨道需要一天的时间.然而这个轨道只能同时给一 ...
- AndroidTouchEvent总结
默认状态 布局文件 <?xml version="1.0" encoding="utf-8"?> <com.malinkang.touchsa ...
- ToF相机学习笔记之基本知识
ToF相机属于一种非接触式光学传感器,通过计算发射激光的飞行时间获取对应像素的深度信息.就非接触式距离测量方法而言,其分类可用下表表示如下: 1.1 ToF传感器基础 一个逐点式的ToF传感器采用了雷 ...
- 我在看着你呢——shiro学习
说实话开学第一周效率并不高.项目该结的都差不多结了,看来这毛病我是养成了.项目忙的要死的时候,想休息想停一停就不断往下扔包袱.一下没项目了开学了,反倒开始手痒,捉摸着写点什么代码.马上我的小mac就要 ...
- python pdb小结
Debug功能对于developer是非常重要的,python提供了相应的模块pdb让你可以在用文本编辑器写脚本的情况下进行debug. pdb是python debugger的简称.常用的一些命令如 ...