SDK1.5中新增了人脸识别类库:Microsoft.Kinect.Toolkit.FaceTracking使得在Kinect中进行人脸识别变得简单,该类库的源代码也在Developer Toolkit中。在Developer Toolkit中也自带人脸识别的例子,您也可以打开运行或者查看源代码。


开发前准备

要使用面部追踪功能,Kinect SDK版本应该至少是1.5,最新版本为1.6,您可以参考之前的那篇文章下载安装,Kinect SDK 和 Kinect Developer Toolkit要一起安装,我的机器上装的是最新的SDK1.6版本。

安装Kinect Developer Toolkit会安装Kinect Studio、一些C#/VB.Net/C++的应用程序示例、源码以及两个用于面部追踪的类库FaceTrackData.dll ,FaceTrackLib.dll包括32位和64位版本,安装好了之后,这些dll应该都在该目录下面 :

如果用C++开发的话,可以直接在项目中使用着两个dll,否则,如果使用.NET开发的话,还需要将这些dll包装成托管代码。

幸运的是, Developer Toolkit中提供了两个使用.NET来实现面部追踪的代码,我们可以直接使用其替我们包装好了dll,该类库的源码也可以看到。 打开Developer Toolkit Browser 找到Component示例,然后安装,之后浏览所在目录,应该能够找到下面两个dll,不安装也可以,您也可以直接到SDK目录中查找这两个dll,在我的及其上目录为C:\Program Files\Microsoft SDKs\Kinect\Developer Toolkit v1.6.0\Samples\bin:

  • Microsoft.Kinect.Toolkit
  • Microsoft.Kinect.Toolkit.FaceTracking

这两个dll的源码可以在示例中找到,引用了这两个dll之后,还需要将FaceTrackData.dll和FaceTrackLib.dll拷贝到项目中,并保证他和exe在同一个目录下面。


创建WPF项目

新建一个名为KinectFaceTracking的WPF项目,然后引用Microsoft.Kinect ,Microsoft.Kinect.Toolkit.FaceTracking 和Microsoft.Kinect.Toolkit这三个dll

要使用面部追踪,在开启KinectSensor之后需要启用ColorImageStream,  DepthImageStream 和SkeletonStream这三个Stream,部分代码如下:

//启用必要的三个Stream
kinectSensor.ColorStream.Enable();
kinectSensor.DepthStream.Enable(DepthImageFormat.Resolution80x60Fps30); kinectSensor.SkeletonStream.TrackingMode = SkeletonTrackingMode.Seated;
kinectSensor.SkeletonStream.Enable(new TransformSmoothParameters() { Correction = 0.5f, JitterRadius = 0.05f, MaxDeviationRadius = 0.05f, Prediction = 0.5f, Smoothing = 0.5f }); // 监听流事件.
kinectSensor.AllFramesReady +=kinectSensor_AllFramesReady; // 初始化数据
colorPixelData = new byte[kinectSensor.ColorStream.FramePixelDataLength];
depthPixelData = new short[kinectSensor.DepthStream.FramePixelDataLength];
skeletonData = new Skeleton[]; //打开Kinect
kinectSensor.Start(); //初始化人脸识别
faceTracker = new FaceTracker(kinectSensor);

前面的代码应该都好懂,值得一提的是最后一句,初始化FaceTracker 对象。在初始化景深数据流时,我们使用最低分辨率的景深影像数据流,这样fps会更高,使得结果更加流畅. 最后,我们注册了AllFramesReady事件。


获取面部数据

在Developer Toolkit中,脸部数据帧使用FaceTrackFrame表示。 为了获取数据,我们需要调用FaceTracker对象的Track方法并传入我们从Kinect中获取的数据,然后FaceTracker对象会对这些数据进行处理来进行面部追踪,部分代码如下:

// 获取每一帧数据,然后存储到变量中来
using (ColorImageFrame colorImageFrame = e.OpenColorImageFrame())
{
if (colorImageFrame == null)
return;
colorImageFrame.CopyPixelDataTo(colorPixelData);
} using (DepthImageFrame depthImageFrame = e.OpenDepthImageFrame())
{
if (depthImageFrame == null)
return;
depthImageFrame.CopyPixelDataTo(depthPixelData);
} using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if (skeletonFrame == null)
return;
skeletonFrame.CopySkeletonDataTo(skeletonData);
} //获取处于跟踪状态的骨骼数据对象,如果没有,则返回.
var skeleton = skeletonData.FirstOrDefault(s => s.TrackingState == SkeletonTrackingState.Tracked);
if (skeleton == null)
return;

前面的都是数据准备阶段,一旦数据都获取了之后,我们使用FaceTracker对象来对这些数据进行识别,提取面部信息。

// 面部追踪
FaceTrackFrame faceFrame = faceTracker.Track(kinectSensor.ColorStream.Format,
colorPixelData,
kinectSensor.DepthStream.Format,
depthPixelData,
skeleton);

faceFrame是一个FaceTrackFrame类型的变量,代表面部追踪的处理结果,该对象的更详细信息,您可以查看 MSDN,下面是该对象的OMD图

首先,TrackSuccessful 属性只是是否识别出了面部,FaceRect是面部所在的矩形区域,最重要的是下面的几个方法:这些方法可以提供最多87个点来表示面部信息,这些点可以以二维或者三维的形式提供。我们可以提取一些用户的面部表情信息:

  • Get3DShape() 方法返回三维表示的121个点集合.
  • GetProjected3DShape() 方法返回同样数目的以二维形式展现的点的集合,这些点映射到640×480像素的图像上.
  • GetAnimationUnitCoefficients()  返回面部表情的描述值,在下面我们会用到这个值来绘制人物图像.更多的信息,您可以查看 Animation Units on MSDN.
  • GetTriangles() 该方法可以 和Get3DShape 方法一起使用. 他返回一个三角形集合,集合中的每个三角形的顶点都是由Get3DShape 中的点组成。这些三角形可以用来进行3D建模,就像Developer Toolkit自带例子中的那样,我们可以用它来对整个面部进行动态建模。

绘制面部

有了数据之后,我们可以在WPF中用XAML来绘制一个简单的人脸了。在绘制过程中,我们会使用一些变换Transformations (Translations, Rotations, Scales, …) 来表示人的表情的变化,比如说RenderTransform对象可以用来改变对象的渲染方式,我们使用一个Ellipse 对象来代表嘴巴 (Ellipse with x:Name=”Mouth”) :他有一个 ScaleTransform属性,我们可以使用它来改变X轴和Y轴上的缩放,来模拟口型的变化,眉头的模拟也是如此。

<Window x:Class="KinectFaceTracking.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="" Width="">
<Grid>
<Grid>
<Canvas x:Name="MainCanvas" Width="" Height="">
<Canvas.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="CanvasRotate" CenterX="" CenterY="" /> <!--<TranslateTransform x:Name="CanvasTranslate" />-->
</TransformGroup>
</Canvas.RenderTransform> <Ellipse Width="" Height="" x:Name="Face" StrokeThickness="" Stroke="Black" Canvas.Left="" Canvas.Top="" />
<Ellipse Width="" Height="" x:Name="LeftEye" Stroke="Black" StrokeThickness="" Canvas.Left="" Canvas.Top="" />
<Ellipse Canvas.Left="" Canvas.Top="" x:Name="RightEye" Height="" Stroke="Black" StrokeThickness="" Width="" />
<Ellipse Canvas.Left="" Canvas.Top="" Height="" x:Name="Mouth" Stroke="Black" StrokeThickness="" Width="" >
<Ellipse.RenderTransform>
<ScaleTransform x:Name="MouthScaleTransform" CenterX="" CenterY="" ScaleX="" ScaleY=""/>
</Ellipse.RenderTransform>
</Ellipse> <!--<Ellipse Canvas.Left="" Canvas.Top="" Height="" x:Name="Nose" Stroke="Black" StrokeThickness="" Width="" />-->
<Rectangle Width="" Stroke="Black" Fill="Black" StrokeThickness="" Height="" Canvas.Left="" Canvas.Top="">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="RightBrow" />
<RotateTransform x:Name="RightBrowRotate" CenterX="" Angle="" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle> <Rectangle Width="" Stroke="Black" Fill="Black" StrokeThickness="" Height="" Canvas.Left="" Canvas.Top="" >
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="LeftBrow" />
<RotateTransform x:Name="LeftBrowRotate" CenterX="" Angle="" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Canvas.Left="" Canvas.Top="" Fill="Black" Height="" Stroke="Black" StrokeThickness="" Width="">
<Rectangle.RenderTransform>
<TransformGroup>
<RotateTransform Angle="-70" CenterX="" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Canvas.Left="" Canvas.Top="" Fill="Black" Height="" Stroke="Black" StrokeThickness="" Width="">
<Rectangle.RenderTransform>
<TransformGroup>
<RotateTransform Angle="" CenterX="" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
</Grid>
</Grid>
</Window>

完成之后,一个简单的人脸就绘制完成了,如下:


将数据和表情绑定

现在表情绘制完成,我们只需要使用面部追踪的数据来改变各部分的动画参数就可以模拟脸部表情了。

获取数据之前,我们需要检查是否识别出来了脸部。如果识别出来人脸,我们就接着获取动画单位系数(Animation Units coefficients). 这个参数可以告诉哦我们被追踪对象嘴巴是张开还是合拢,还是在笑,眉头紧锁还是笑颜逐开等等…

//如果识别出来,进行进一步处理
if (faceFrame.TrackSuccessful)
{
// 获取动画单位系数 Animation Units coeffs.
var AUCoeff = faceFrame.GetAnimationUnitCoefficients(); var jawLowerer = AUCoeff[AnimationUnit.JawLower];
jawLowerer = jawLowerer < ? : jawLowerer;
MouthScaleTransform.ScaleY = jawLowerer * + 0.1;
MouthScaleTransform.ScaleX = (AUCoeff[AnimationUnit.LipStretcher] + ); LeftBrow.Y = RightBrow.Y = (AUCoeff[AnimationUnit.BrowLower]) * ; RightBrowRotate.Angle = (AUCoeff[AnimationUnit.BrowRaiser] * );
LeftBrowRotate.Angle = -RightBrowRotate.Angle; CanvasRotate.Angle = faceFrame.Rotation.Z;
}

上面的动画参数的取值范围都是在-1和1之间。到这里一个简单的面部追踪小程序就完成了,您可以对着Kinect做一些表情试一试变化。下面是我做的一些截图:

Kinect 开发 —— 面部追踪的更多相关文章

  1. Kinect 开发 —— 骨骼追踪进阶(上)

    Kinect传感器核心只是发射红外线,并探测红外光反射,从而可以计算出视场范围内每一个像素的深度值.从深度数据中最先提取出来的是物体主体和形状,以及每一个像素点的游戏者索引信息.然后用这些形状信息来匹 ...

  2. Kinect 开发 —— 骨骼追踪(下)

    Kinect 连线游戏 在纸上将一些列数字(用一个圆点表示)从小到大用线连起来.游戏逻辑很简单,只不过我们在这里要实现的是动动手将这些点连起来,而不是用笔或者鼠标. 在开始写代码之前,需要明确定义我们 ...

  3. Kinect 开发 —— 骨骼追踪

    骨骼追踪技术通过处理景深数据来建立人体各个关节的坐标,骨骼追踪能够确定人体的各个部分,如那部分是手,头部,以及身体.骨骼追踪产生X,Y,Z数据来确定这些骨骼点.骨骼追踪系统采用的景深图像处理技术使用更 ...

  4. Kinect 开发 —— 骨骼追踪 (下)

    基于景深数据的用户交互 骨骼数据中关节点不仅有X,Y值,还有一个深度值 除了使用WPF的3D特性外,在布局系统中可以根据深度值来设定可视化元素的尺寸大小来达到某种程序的立体效果. 下面的例子使用Can ...

  5. Kinect开发文章目录

    整理了一下去年为止到现在写的和翻译的Kinect的相关文章,方便大家查看.另外,最近京东上微软在搞活动, 微软 Kinect for Windows 京东十周年专供礼包 ,如果您想从事Kinect开发 ...

  6. Kinect开发笔记之二Kinect for Windows 2.0新功能

    这是本博客翻译文档的第一篇文章.笔者已经苦逼的竭尽全力的在翻译了.但无奈英语水平也是非常有限.不正确或者不妥当不准确的地方必定会有,还恳请大家留言或者邮件我以批评指正.我会虚心接受. 谢谢大家.   ...

  7. Kinect 开发 —— 杂一

    Kinect 提供了非托管(C++)和托管(.NET)两种开发方式的SDK,如果您用C++开发的话,需要安装Speech Runtime(V11),Kinect for Windows Runtime ...

  8. Kinect 开发 —— 全息图

    Kinect的另一个有趣的应用是伪全息图(pseudo-hologram).3D图像可以根据人物在Kinect前面的各种位置进行倾斜和移动.如果方法够好,可以营造出3D控件中3D图像的效果,这样可以用 ...

  9. Kinect 开发 —— ColorBasic

    创建一个Kincet项目通常需要: 1. 创建一个VS项目,一般为了展示通常创建一个wpf项目. 2. 添加Microsoft.Kinect.dll引用,如果是早期版本的SDK,这个名称可能不同. 3 ...

随机推荐

  1. <Sicily>Tiling a Grid With Dominoes

    一.题目描述 We wish to tile a grid 4 units high and N units long with rectangles (dominoes) 2 units by on ...

  2. HDU 1789 Doing Homework again【贪心】

    题意:给出n个作业的截止时间,和该作业没有完成会被扣掉的分数.问最少会被扣掉多少分. 第一次做这一题是好久之前,当时不会(不会处理两个关键字关系@_@)---现在还是不会---看了题解---原来是这样 ...

  3. 十一 模板匹配match template

    一.介绍 1.模板匹配 通俗讲就是以图找图,通过图中的一部分来找它在图中的位置(模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域). 模板匹配是一种最原始.最基本的模式识别方法,研究某一特定对 ...

  4. keytool常用操作

    keytool 秘钥需要存储在秘钥库中,秘钥库可以理解为一个存储了一个或多个秘钥的文件.一个秘钥库可以存储多个密钥对,每个秘钥对你都需要给他们取一个名字. D:\software\Java\jdk1. ...

  5. Intel NUC迷你机2019年底迎来i9 8核心16线程

    Intel处理器这两年全年提速,虽然10nm新工艺受阻,但核心数在全面增加,从发烧到桌面到低功耗莫不如此,如今连NUC迷你机也要全新进化了,一年多之后就会迎来8核心16线程,而且也划入i9序列. 根据 ...

  6. who---显示目前登录系统的用户信息

    who命令是显示目前登录系统的用户信息.执行who命令可得知目前有那些用户登入系统,单独执行who命令会列出登入帐号,使用的终端机,登入时间以及从何处登入或正在使用哪个X显示器. 语法 who(选项) ...

  7. 【深度学习大讲堂】首期第一讲:人工智能的ABCDE 第二部分:简谈当前AI技术与发展趋势

    (完)

  8. win下通过pip安装TensorFlow

    官方介绍(超详细):https://www.tensorflow.org/install/pip 按照官方介绍,不同的TensorFlow版本只支持特定的python版本所以你要是下载.whl包安装的 ...

  9. web——前后端通信原理

    前端向后台传输数据: 传输方法:post  get 区别: (1)get:用于从服务器获取数据,将参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看 ...

  10. CRC校验原理及步骤

    什么是CRC校验? CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并 ...