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();//请求绘制或重绘位图 } } } }