C#动手实践:Kinect V2 开发(2):数据源工作原理及红外源Demo

Kinect体系架构

Kinect 数据模式

1.Sensor

KinectSensor类

private KinectSensor kinectSensor = null;

this.kinectSensor = KinectSensor.GetDefault();

this.kinectSensor.Open();

this.kinectSensor.Close();

2.Source

源,Kinect上的各个传感器

它公开了每一个传感器源的元数据然后给你一个入口

体感器每一数据类型展示一个源

属性(字段):

AudioSource  获取音频的源

BodyFrameSource   获取身体框架的源

BodyIndexFrameSource   获取身体索引帧的源

ColorFrameSource   获取颜色帧的源

DepthFrameSource   获取景深帧的源

InfraredFrameSource   获取红外帧的源

LongExposureInfraredFrameSource   获取长曝光红外帧的源

3.Reader

一旦有了Reader,你就可以使用事件来访问各帧

在一个源上,可以使用多个Reader

Reader可以暂停

 

//为红外帧源创建一个读出器,赋值给InfraredFrameReader类的实例:reader

InfraredFrameReader reader = sensor.InfraredFrameSource.OpenReader();

//为FrameArrived事件注册方法,事件的触发条件是一旦捕获到帧(就绪)就触发

reader.FrameArrived += InfraredReaderFrameArrived;

打开读出器,订阅已经就绪的帧事件,当有帧进来时就回调

 

4.Frame References

帧引用

帧引用,在帧事件的数据变量中,事实发送的就是帧引用

这样你才能访问帧本身

方法:

AcquireFrame 获取此引用所持有的帧

如果在事件触发之前,或者在你对其进行处理之前帧就已经过期,你就只能从已获得的帧方法中得到一个空帧。这就是为什么需要查看一下的原因

属性:

RelativeTime (相对时间)可以使你对不同的帧建立暂时的相关

不是绝对时间,是让你能比较各个源之间的时间

 

使用方法:1.注册帧事件,获得帧引用

2.使用using数据块即可,这个using数据块将自动处理帧,完成后腰准备好处理下一帧

某一时刻只有一种类型的一个帧可用,如果不关闭、不处理帧,你就不能得到新的帧

void irReader_FrameArrived(InfraredFrameReader sender,              

                           InfraredFrameArrivedEventArgs args)

{

    using (InfraredFrame frame = args.FrameReference.AcquireFrame())

    {

       if (frame != null)

       {

           // Get what you need from the frame

       }

    }

}

 

5.Frame

帧本身

 有了帧,就可以访问实际数据并加以利用了

建议拷贝一个本地副本或直接访问基础缓冲区,这样你就可以迅速做出反应而无需长时间地使帧保持在当前可用状态

每个帧都有宽度和高度数值等格式

 

6.FrameDescription类

  继承于接口IFrameDescription

帧描述,获得帧的相关数据(宽、高等)

帧描述的长度以像素为单位

使用红外源在Windows应用商店应用内输出图像

  

public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.Loaded += MainPage_Loaded;
        }
        KinectSensor sensor;
        InfraredFrameReader irReader;
        ushort[] irData;//储存读出器读出的数据,IR数据的格式是Ushort
        byte[] irDataConverted;//将红外数据转换为图像,创建缓冲区
        WriteableBitmap irBitmap;//提供可写入并可更新的位图流,将我们转换好的图像送入XAML中的image

        //其实和在构造函数里写是一样的,MainPage构建时触发事件执行下面的方法
        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            //初始化
            #region
            sensor = KinectSensor.GetDefault();//获取默认Kinect
            irReader = sensor.InfraredFrameSource.OpenReader();//打开红外读出器
            FrameDescription fd = sensor.InfraredFrameSource.FrameDescription;//创建红外帧描述
            irData = new ushort[fd.LengthInPixels];//帧描述的长度以像素为单位,16位整数数组  65535
            irDataConverted = new byte[fd.LengthInPixels * 4];//IR需要转换为RGBA图像需要进行四次 #FF FF FF FF
            irBitmap = new WriteableBitmap(fd.Width, fd.Height);//创建位图
            image.Source = irBitmap;
            #endregion

            sensor.Open();//1.打开传感器
            irReader.FrameArrived += IrReader_FrameArrived;//2.为读出器订阅事件
        }

        private void IrReader_FrameArrived(InfraredFrameReader sender, InfraredFrameArrivedEventArgs args)
        {
            //能否能从事件数组变量中的帧引用获取帧
            using(InfraredFrame irFrame = args.FrameReference.AcquireFrame())
            {
                if (irFrame!=null)
                {
                    irFrame.CopyFrameDataToArray(irData);//将帧数据复制到数组中
                    for (int i = 0; i < irData.Length; i++)//循环得到RGBA
                    {
                        byte intensity = (byte)(irData[i] >> 8);
                        irDataConverted[i * 4] = intensity;
                        irDataConverted[i * 4+1] = intensity;
                        irDataConverted[i * 4+2] = intensity;
                        irDataConverted[i * 4+3] = 255;//A为透明度,指定为255为不透明
                    }
                    irDataConverted.CopyTo(irBitmap.PixelBuffer);//将RGBA复制到位图的缓冲区中
                    irBitmap.Invalidate();//请求绘制或重绘位图
                }
            }
        }
    }
原文地址:https://www.cnblogs.com/ansijiu/p/5706232.html