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[0];

    //初始化照相机
    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(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight),
                        this.colorPixels,
                        this.colorBitmap.PixelWidth * sizeof(int),
                        0);
                }
            }
        }
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

时间: 2024-10-29 19:05:42

Kinect 开发 —— ColorBasic的相关文章

Kinect 开发 &mdash;&mdash; 开发前的准备工作

Kinect SDK v1.5 支持托管语言和非托管语言 Xbox360的游戏是基于Xbox360开发工具包 (XDK)开发的,Xbox 360和Windows是两个完全不同的系统架构.使用Kinect for windows SDK 编译的代码并不能直接部署到Xbox环境中 Kinect 应用程序必须在一个原生操作系统环境下编译,运行 -- 无法在虚拟机上运行 Kinect 开发 —— 开发前的准备工作,布布扣,bubuko.com

Kinect 开发 &mdash;&mdash; 用户交互设计的若干思考

Metro 风格 windows 8 Kinect Hub 手势原型设计 悬停选择     翻页控制 关节点重叠的处理方法 将箭靶设置在画面的边缘,这样玩家持弓的角度与屏幕保持一个大约45度的锐角,这样Kinect可以很精确的检测到拉弓射箭的动作 手势天生具有一定随意性,而且具有一定的文化背景差异性   手与设备的非接触性 虚拟触摸的界面 Kinect 使交互"柔软化"   确认操作保持简单一致 悬停选择 -- 将手停在想要选择的项目方块或按钮上,等待进度圆圈的填充,这个过程会在T时间

【Kinect开发笔记之(一)】初识Kinect

一.Kinect简介 Kinect是微软在2010年6月14日对XBOX360体感周边外设正式发布的名字.它是一种3D体感摄影机(开发代号"Project Natal"),同时它导入了即时动态捕捉.影像辨识.麦克风输入.语音辨识.社群互动等功能. 二.Kinect分类 Kinect for Xbox 360:该版本设计之初就是为了Xbox 360定制的,并未考虑其他的平台.从微软授权角度而言,它无法用于商业开发. Kinect for Windows : 固件上做了升级,支持"

【Kinect开发笔记之(二)】Kinect for windows发展历程

新版本SDK和旧版本的SDK完全兼容,如果您之前安装过旧版本的,可以直接安装新版本的SDK,但是如果您之前的开发版本是Beta版的,则需要卸载之后再安装新版本.在Kinect for Windows SDK 1.0版本中,SDK和示例文件是打包一起安装的.而在之后的版本,为了可以分别升级,微软把这两者分开独立为Kinect for Windows SDK和Kinect for Windows Developer Toolkit这两部分,所以需要分别下载安装, Kinect for Windows

Kinect 开发 &mdash;&mdash; 骨骼数据与彩色影像和深度影像的对齐

在显示彩色影像和深度影像时最好使用WriteableBitmap对象: 要想将骨骼数据影像和深度影像,或者彩色影像叠加到一起,首先要确定深度影像的分辨率和大小,为了方便,这里将深度影像数据和彩色影像数据都采用640x480Fps30的格式,同时将Grid的大小也设置为640*480. 要将骨骼数据和深度影像数据叠加,需要将关节点转换到深度影像所在空间中,可以直接调用MapSkeletonPointToDepthPoint,如果要将骨骼数据叠加到彩色影像上,只需要调用MapSkeletonPoin

Kinect 开发 &mdash;&mdash; 语音识别(下)

使用定向麦克风进行波束追踪 (Beam Tracking for a Directional Microphone) 可以使用这4个麦克风来模拟定向麦克风产生的效果,这个过程称之为波束追踪(beam tracking) 界面上的细长矩形用来指示某一时刻探测到的说话者的语音方向.矩形有一个旋转变换,在垂直轴上左右摆动,以表示声音的不同来源方向. <Rectangle Fill="#1BA78B" HorizontalAlignment="Left" Margin

Kinect 开发 &mdash;&mdash; 姿势识别

姿势和手势通常会混淆,但是他们是两个不同的概念.当一个人摆一个姿势时,他会保持身体的位置和样子一段时间.但是手势包含有动作,例如用户通过手势在触摸屏上,放大图片等操作. 通常,游戏者很容易模仿指定姿势并且比较容易编写算法来识别指定的姿势.例如,如果开发一个用户在天上飞的游戏. 一种控制游戏的方式是,游戏者像鸟一样挥动手臂.挥动的频率越快游戏角色飞的越快,这是一个手势.还有一种方法是,展开双臂,双臂张得越快开,飞的越快.双臂离身体越近,飞的越慢. 身体以及各个关节点的位置定义了一个姿势.更具体的来

Kinect开发资源汇总

Kinect开发资源汇总   转自: http://www.sigvc.org/bbs/forum.php?mod=viewthread&tid=254&highlight=kinect By doctorimage整理 开发Kinect应用本质上和开发其他Windows应用一样,不同的是该SDK支持Kinect感应器的相关功能,比如彩色图像.深度图像.音频.骨骼动画数据等. 本文整理了Kinect应用开发的相关资源,如果你正在进行Kinect开发或打算进行Kinect开发,这将对你有很大

Kinect 开发 &mdash;&mdash; 引言

自然人机交互设计技术 (全息三维投影,手势肢体识别,眼动跟踪 ...) 符合人类心理的交互方式 自然用户界面 -- Natural User Interface 有机用户界面 -- Organic User Interface   第六感设备 -- 手势识别,摄像头,投影,云计算 通过对熟知的技术的组合,产生一种NB 的应用               http://www.pranavmistry.com/ 追影技术 -- 用普通摄像头结合运动跟踪算法,实现体感 微软的 CamBot 技术,G