layout: post title: Kinect开发实践 subtitle: 如果不是毕设,我啥时候会挖这个坑呢 date: 2020-1-1 author: Elias header-img: img/post-bg-bluewhale.jpg catalog: true tags:
- Blog
Kinect应用开发实践
写在前面
本次实践要完成的目标
- 熟悉Kinect带有的人体骨骼识别功能,并能够实时获取骨骼数据流,建立人体骨骼图像。
- 实现对骨骼数据的处理,完成静态姿势识别。
- 实现对骨骼数据的处理,完成动态动作识别。
- 定义出危险动作,并在做出相应危险动作后,能够识别并标注。
- …
搭建Kinect开发环境
主机性能
处理器:Intel(R) Core(TM) i5-6300HQ CPU @ 2.30GHz 2.30 GHz
机待RAM:8.00 GB
系统:Win10
VS2017
…
KinectForWindows SDK
…
开始实践!
从第一个程序开始
-
获取Kinect设备传来的彩色帧,并关闭某个色彩通道
新建一个WPF工程

添加引用”Microsoft.Kinect”

在”MainWindow.xaml.cs”中引用命名空间

为了能够在窗体中将后续接收的图像显示出来,我们需要在设计器中加入一个Image,用于显示我们接收的图像。
<Window x:Class="CloseColor.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:CloseColor" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <Image x:Name="image"/> </Grid> </Window>
接着在”MainWindow.xaml.cs”中完成我们对MainWindow.xaml的交互逻辑,代码如下。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Microsoft.Kinect; namespace CloseColor { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { private KinectSensor kinect = null; //创建一个新的kinect private ColorFrameReader colorFrame = null; //创建色彩读取器 private WriteableBitmap colorBitmap = null; //创建色彩位图 private FrameDescription colorFrameDescription = null; //创建色彩框架描述 private Int32Rect colorBitmapRect; //创建32位色彩位图矩阵 private int colorBitmapStride; //定义色彩位图的Stride byte[] pixelData = null; //像素数据数组 public MainWindow() { InitializeComponent(); //初始化组件 this.kinect = KinectSensor.GetDefault(); //获得kinect初始化数据 this.colorFrame = kinect.ColorFrameSource.OpenReader(); //通过读取器获得Kinect获取的色彩框架 this.colorFrame.FrameArrived += ColorFrame_FrameArrived; //绑定事件 this.colorFrameDescription = this.kinect.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra); //获取kinect收集的色彩框架描述 pixelData = new byte[colorFrameDescription.LengthInPixels * 4]; //创建实例 //按照Bgra格式设定数据帧的描述信息(B:Blue,G:Green,R:Red,A:Alpha) // 1920*1080 彩色图像 this.colorBitmap = new WriteableBitmap(colorFrameDescription.Width, colorFrameDescription.Height, 96.0, 96.0, PixelFormats.Bgr32, null); // //根据数据帧的宽高创建colorBitmap的实例 this.colorBitmapRect = new Int32Rect(0, 0, this.colorBitmap.PixelWidth, colorBitmap.PixelHeight); this.colorBitmapStride = this.colorFrameDescription.Width * 4; //32位图像中,Stride = Width * 4 image.Source = this.colorBitmap; //将色彩位图赋值给image this.kinect.Open(); //打开kinect } //定义事件处理函数 void ColorFrame_FrameArrived(object sender, ColorFrameArrivedEventArgs e) { using(ColorFrame frame = e.FrameReference.AcquireFrame()) { if(frame != null) //若获取的框架不为空 { frame.CopyConvertedFrameDataToArray(this.pixelData, ColorImageFormat.Bgra); //将转换后的帧数据复制到数组this.pixelData for(int i = 0; i < pixelData.Length; i += 4) { //pixelData[i] = 0x00;//关闭蓝色通道 B //pixelData[i] = 0x00;//关闭绿色通道 G pixelData[i + 2] = 0x00;//关闭红色通道 R } this.colorBitmap.WritePixels(this.colorBitmapRect, this.pixelData, this.colorBitmapStride, 0); } } } } }
-知识补充
-
Stride
stride是图像处理中常用的概念。
假设一行有11个像素(Width = 11),对于一个32位(每个像素4字节)的图像来说,Stride=11 * 4 = 44.
其中还会有字节对齐的问题,譬如:假设一行有11个像素(Width = 11),对于一个24位(每个像素3字节)的图像,Stride = 11 * 3 + 3 = 36,注意到这里并不是Stride = 11 * 3 = 33,因为这里是按照4字节对齐的,因此33中,前32占满了,第33位占据一个4字节空间,因此是36.
根据上述内容,我们能够手动计算Stride的值:
(1)Stride = 像素位数/8 * Width;
(2)若Stride不是4的倍数,那么Stride = Stride + (4 - Stride mod 4);
-
C#中@的用法
(1)加在字符串前面,字符串中的”\“失去转义符的作用,可直接写字符串而不需要考虑转义字符。
private readonly string gestureDatabase = @"Database\uphand.gbd"; // 若不加 @,需写成如下格式: private readonly string gestureDatabase = "Database\\uphand.gbd";(2)加在字符串前面,字符串中的 “ 要用 ““ 表示。
(3)加在字符串前面,字符串中的空格、换行都会保存,方便阅读代码。