一、kinect开发的一个流程图

1、我们可以知道一个简单的框架就是几部分

(1)选择使用的kinect传感器

KinectSensor.KinectSensors[]

(2)打开需要的数据流

_kinect.DepthStream.Enable();
_kinect.ColorStream.Enable();
_kinect.SkeletonStream.Enable();

(3)注册事件

其实就是主要的算法在这里体现。

有个小窍门:VS的CodeSnippet快速生成事件代码,如在代码“_kinect.DepthFrameReady+=”后面连续按两次“Tab”键,就会生成相应的时间并处理相应的代码。

二、初始化、启用kinect设备

代码如下,记得要声明一个私有成员变量_kinect,并在MainWindow()里面调用。

KinectSensor _kinect;

        private void startKinect()
{
if(KinectSensor.KinectSensors.Count>)
{
//选择第一个kinect设备
_kinect = KinectSensor.KinectSensors[];
MessageBox.Show("Kinect目前状态为:" + _kinect.Status); //初始化设定,启用彩色图像,深度图像和骨骼追踪
_kinect.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
_kinect.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
_kinect.SkeletonStream.Enable(); //注册时间,该方法将保证彩色图像,深度图像和骨骼图像的同步
_kinect.AllFramesReady += _kinect_AllFramesReady; //启动kinect
_kinect.Start();
}
else
{
MessageBox.Show("没有发现任何kinect设备");
}
}

void _kinect_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{

}

三、彩色图像流数据处理

1、在MainWindows窗体上新增一个Image控件,命名为imageCamera

2、在_kinect_AllFramesReady事件处理中增加如下代码、

//显示彩色摄像头
using(ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if(colorFrame == null)
{
return;
} byte[] pixels = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(pixels); //BGR32格式图片一个像素为4个字节
int stride = colorFrame.Width * ;
ImageCamera.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, , , PixelFormats.Bgr32, null, pixels, stride); }

BGR32图像的1像素对应4字节(32位),分别是B,G,R,阿尔法通道(透明度)。

BitmapSource.Create是一个从数组到二维矩阵的过程。

Stride为图片步长,代表图片一行像素所占的字节数,为摄像头传输图片的宽度乘以4,

DPI,越高越清晰,普通的显示器就是96差不多。

3、效果图

四、深度数据捕获

1、定义深度图像的有效视角范围。

const float MaxDepthDistance = ;
const float MinDepthDistance = ;
const float MaxDepthDistanceOffest = MaxDepthDistance - MinDepthDistance; private const int RedIndex = ;
private const int GreenIndex = ;
private const int BlueIndex = ;

2、代码

private byte[]convertDepthFrameToColorFrame(DepthImageFrame depthFrame)
{
short[] rawDepthData = new short[depthFrame.PixelDataLength];
depthFrame.CopyPixelDataTo(rawDepthData); Byte[] piexls = new byte[depthFrame.Height * depthFrame.Width * ]; for(int depthIndex = ,colorIndex=;depthIndex<rawDepthData.Length&&colorIndex<piexls.Length;depthIndex++,colorIndex+=)
{
int player = rawDepthData[depthIndex] & DepthImageFrame.PlayerIndexBitmask; int depth = rawDepthData[depthIndex];
if(depth<=)
{
piexls[colorIndex + BlueIndex] = ;
piexls[colorIndex + GreenIndex] = ;
piexls[colorIndex + RedIndex] = ;
}
else if(depth>&&depth<)
{
piexls[colorIndex + BlueIndex] = ;
piexls[colorIndex + GreenIndex] = ;
piexls[colorIndex + RedIndex] = ;
}
else if(depth>)
{
piexls[colorIndex + BlueIndex] = ;
piexls[colorIndex + GreenIndex] = ;
piexls[colorIndex + RedIndex] = ;
} byte intensity = CalculateIntensityFromDepth(depth);
piexls[colorIndex + BlueIndex] = intensity;
piexls[colorIndex + GreenIndex] = intensity;
piexls[colorIndex + RedIndex] = intensity; if(player>)
{
piexls[colorIndex + BlueIndex] = Colors.LightGreen.B;
piexls[colorIndex + GreenIndex] = Colors.LightGreen.G;
piexls[colorIndex + RedIndex] = Colors.LightGreen.R;
}
}
return piexls;
} void _kinect_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
//显示彩色摄像头
using(ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if(colorFrame == null)
{
return;
} byte[] pixels = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(pixels); //BGR32格式图片一个像素为4个字节
int stride = colorFrame.Width * ;
ImageCamera.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, , , PixelFormats.Bgr32, null, pixels, stride); } using(DepthImageFrame depthFrame = e.OpenDepthImageFrame())
{
if(depthFrame==null)
{
return;
} byte[] piexls = convertDepthFrameToColorFrame(depthFrame); int stride = depthFrame.Width * ;
imageDepth.Source = BitmapSource.Create(depthFrame.Width, depthFrame.Height, , , PixelFormats.Bgr32, null, piexls, stride); }

3、效果图

五、骨骼追踪

1、首先注释掉我们之前注册的时间,重新注册一个彩色数据流时间和一个骨骼事件,然后添加如下代码

private Skeleton[] skeletons;
void _kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
bool isSkeletonDataEeady = false;
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if(skeletonFrame!=null)
{
skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
skeletonFrame.CopySkeletonDataTo(skeletons);
isSkeletonDataEeady = true;
} } if(isSkeletonDataEeady==true)
{
Skeleton currentSkeleton = (from s in skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).FirstOrDefault();
if(currentSkeleton !=null)
{
lockHeadWithSpot(currentSkeleton);
} }
} void lockHeadWithSpot(Skeleton s)
{
Joint head = s.Joints[JointType.Head];
ColorImagePoint colorPoint = _kinect.MapSkeletonPointToColor(head.Position, _kinect.ColorStream.Format); Point p = new Point((int)(ImageCamera.Width * colorPoint.X / _kinect.ColorStream.FrameWidth),
(int)(ImageCamera.Height * colorPoint.Y / _kinect.ColorStream.FrameHeight)); Canvas.SetLeft(ellipseHead, p.X);
Canvas.SetRight(ellipseHead, p.Y);
} void _kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame == null)
{
return;
} byte[] pixels = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(pixels); //BGR32格式图片一个像素为4个字节
int stride = colorFrame.Width * ;
ImageCamera.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, , , PixelFormats.Bgr32, null, pixels, stride); } }

2、效果图

六关闭kinect设备

private void stopKinect()
{
if(_kinect != null)
{
if(_kinect.Status== KinectStatus.Connected)
{
_kinect.Stop();
}
}
}

kinect学习笔记(四)——各种数据流的更多相关文章

  1. Learning ROS for Robotics Programming Second Edition学习笔记(四) indigo devices

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  2. 零拷贝详解 Java NIO学习笔记四(零拷贝详解)

    转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...

  3. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  4. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  5. java之jvm学习笔记四(安全管理器)

    java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...

  6. Typescript 学习笔记四:回忆ES5 中的类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  7. ES6学习笔记<四> default、rest、Multi-line Strings

    default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...

  8. muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制

    目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ...

  9. python3.4学习笔记(四) 3.x和2.x的区别,持续更新

    python3.4学习笔记(四) 3.x和2.x的区别 在2.x中:print html,3.x中必须改成:print(html) import urllib2ImportError: No modu ...

  10. Go语言学习笔记四: 运算符

    Go语言学习笔记四: 运算符 这章知识好无聊呀,本来想跨过去,但没准有初学者要学,还是写写吧. 运算符种类 与你预期的一样,Go的特点就是啥都有,爱用哪个用哪个,所以市面上的运算符基本都有. 算术运算 ...

随机推荐

  1. controller传值view

    400错误是请求错误 Model是map格式 @Controller public class HelloController { //view的值传给controller @RequestMappi ...

  2. JS 键值对

    function Map() { this.keys = new Array(); this.data = new Array(); //添加键值对 this.set = function (key, ...

  3. linux 下安装开发组件包

    最初安装redhat 时, 系统自己装的,只安装了base 包,在开发过程中,需要不停的安装某个需求包,   图省事,安装光盘下的开发组件包: 在安装光盘下,,,用命令: yum grouplist ...

  4. 百度编辑器Ueditor 初始化加载内容失败解决办法

    项目上有用到百度文本编辑器ueditor,在页面加载的时候初始化编辑器内容时候,使用 $.document.ready(function() { UE.getEditor('editor').setC ...

  5. POJ 2418 Hardwood Species

                                                     Hardwood Species Time Limit: 10000MS   Memory Limit ...

  6. 如何用火车头采集当前页面url网址

    首先创建一个标签为本文网址,勾选后面的“从网址中采集”. 选择下面的“正则提取”,点击通配符“(?<content>?)”,这样在窗口中就显示为(?<content>[\s\S ...

  7. 减小Delphi2010程序的尺寸(关闭RTTI反射机制)

    自从Delphi2010增强了RTTI反射机制后,编译出来的程序变得更大了,这是因为默认情况下 Delphi2010 给所有类都加上了RTTI信息(呵呵,不管你用不用它,好像实用价值确实不高,至少目前 ...

  8. 写时复制技术(Copy-on-write)

    COW技术初窥:        在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了"写时复制" ...

  9. (0,eval)('this')与eval的区别

    看doT源码的时候,看到了这么一句代码: global = (function(){ return this || (0,eval)('this'); }()); global.doT = doT; ...

  10. EtherCAT数据帧结构

    EtherCAT数据直接使用以太网数据帧(以太网帧解释http://blog.chinaunix.net/uid-23080322-id-118440.html)传输,使用的帧类型为0x88A4.Et ...