需要引入的dll:

需要将下面两个dll复制到当前路径

Kinect for windows提供了脸部识别的功能,可以识出人脸。主要是通过FaceTrackFrame类的GetTriangles()来得到一个三角形数组,这个三角形数组就是给成人面部的基本形状,并且组成的效果是立体的(可以这样理解,可以把3D都拆成三角形来表示,看上去像3D,但其实是2D),这个数组的每个元素都存放着三个整数,分别代码三角形的第一个点,第二个点和第三个点。FaceTrackFrame的GetProjected3DShape方法,可以获取一组坐标信息,这样就可以结合三角形数组元素中的点作为索引,从本方法的坐标集合中取出每个三角形的坐标点来了,就可以绘制这些三角形,就可以组成一个人脸的网络3D效果图了。

本例是从色彩摄像头中获取彩色数据流,并显示到窗体上,再通过FaceTracker得到得到脸部3D信息,并用GDI+的方式把网络图形画到窗体上,这时就可以在真实图像上看到浮着一张网络的面套。同时可以得出脸部交汇最多的坐标,并用GDI+添加上不同有色彩,同时还可以得到人体面部和Kinect 正面的偏差,即人头是否竖直,有没有偏上一边等角度信息。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit;
using Microsoft.Kinect.Toolkit.FaceTracking;
using System.Threading;
using System.IO;
using System.Drawing.Imaging; namespace Face
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} KinectSensor ks = null;
private void Form1_Load(object sender, EventArgs e)
{
//让winform窗体刷新不闪动
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
//找到连接的Kinect设备
foreach (var ks in KinectSensor.KinectSensors)
{
if (ks.Status == KinectStatus.Connected)
{
this.ks = ks;
}
}
//开启色彩流,深度流,骨骼流的跟踪
if (this.ks != null)
{
this.ks.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
this.ks.DepthStream.Enable(DepthImageFormat.Resolution320x240Fps30);
this.ks.DepthStream.Range = DepthRange.Near;
this.ks.SkeletonStream.EnableTrackingInNearRange = true;
this.ks.SkeletonStream.TrackingMode = SkeletonTrackingMode.Seated;
this.ks.SkeletonStream.Enable();
//订阅跟踪数据读取事件
this.ks.AllFramesReady += OnAllFramesReady;
ks.Start();
}
} //这个方法很重要,就是重绘人脸跟踪采集到的数据
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
foreach (SkeletonFaceTracker faceInformation in this.trackedSkeletons.Values)
{
//第一个参数为当前窗体为画布,第二个是添加采集到的信息到listbox中,这个方法画识别到脸部的信息
faceInformation.DrawFaceModel(e.Graphics, Messbox_LB);
}
} //定义脸部识别的集合
private readonly Dictionary<int, SkeletonFaceTracker> trackedSkeletons = new Dictionary<int, SkeletonFaceTracker>();
//色彩流字节数组
private byte[] colorImage;
private ColorImageFormat colorImageFormat = ColorImageFormat.Undefined;
//深度流字节数组
private short[] depthImage;
private DepthImageFormat depthImageFormat = DepthImageFormat.Undefined;
//骨骼信息数组
private Skeleton[] skeletonData; private void OnAllFramesReady(object sender, AllFramesReadyEventArgs allFramesReadyEventArgs)
{
ColorImageFrame colorImageFrame = null;
DepthImageFrame depthImageFrame = null;
SkeletonFrame skeletonFrame = null;
try
{
colorImageFrame = allFramesReadyEventArgs.OpenColorImageFrame(); //接到色彩流对框架
depthImageFrame = allFramesReadyEventArgs.OpenDepthImageFrame(); //接到深度流对框架
skeletonFrame = allFramesReadyEventArgs.OpenSkeletonFrame(); //接到骨骼流对框架 if (colorImageFrame == null || depthImageFrame == null || skeletonFrame == null)
{
return;
} if (this.depthImageFormat != depthImageFrame.Format)
{
this.ResetFaceTracking();
this.depthImage = null;
this.depthImageFormat = depthImageFrame.Format;
} if (this.colorImageFormat != colorImageFrame.Format)
{
this.ResetFaceTracking();
this.colorImage = null;
this.colorImageFormat = colorImageFrame.Format;
}
if (this.depthImage == null)
{
this.depthImage = new short[depthImageFrame.PixelDataLength];
} if (this.colorImage == null)
{
this.colorImage = new byte[colorImageFrame.PixelDataLength];
} if (this.skeletonData == null || this.skeletonData.Length != skeletonFrame.SkeletonArrayLength)
{
this.skeletonData = new Skeleton[skeletonFrame.SkeletonArrayLength];
}
//获取各种数据流信息
colorImageFrame.CopyPixelDataTo(this.colorImage);
depthImageFrame.CopyPixelDataTo(this.depthImage);
skeletonFrame.CopySkeletonDataTo(this.skeletonData);
//清空列表信息
Messbox_LB.Items.Clear();
//编历骨骼流
foreach (Skeleton skeleton in this.skeletonData)
{
//找到有效的骨骼信息
if (skeleton.TrackingState == SkeletonTrackingState.Tracked
|| skeleton.TrackingState == SkeletonTrackingState.PositionOnly)
{
if (!this.trackedSkeletons.ContainsKey(skeleton.TrackingId))
{
//添加骨骼信息到集合中
this.trackedSkeletons.Add(skeleton.TrackingId, new SkeletonFaceTracker());
}
// 得到脸部识别对象
SkeletonFaceTracker skeletonFaceTracker;
if (this.trackedSkeletons.TryGetValue(skeleton.TrackingId, out skeletonFaceTracker))
{
//把获取的数据流的相关信息传给OnFrameReady方法
skeletonFaceTracker.OnFrameReady(Messbox_LB, this.ks, colorImageFormat, colorImage, depthImageFormat, depthImage, skeleton);
skeletonFaceTracker.LastTrackedFrame = skeletonFrame.FrameNumber;
}
}
}
//这个刷新会触发窗体的重画,OnPaint方法会被调用。
this.Refresh();
//把色彩流转转成位图显示成窗体的背景
this.BackgroundImage = ToGrayBitmap(colorImage, , ); }
finally
{
if (colorImageFrame != null)
{
colorImageFrame.Dispose();
}
if (depthImageFrame != null)
{
depthImageFrame.Dispose();
}
if (skeletonFrame != null)
{
skeletonFrame.Dispose();
}
}
}
//把色采流数据转成位图返回
public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height)
{
//定议转换图片的格式,一个像素占32个,前24位为红绿蓝,后8位为空
PixelFormat pf = PixelFormat.Format32bppRgb;
//申请目标位图的变量
Bitmap bmp = new Bitmap(width, height, pf);
//将其内存区域锁定
BitmapData bmpData = bmp.LockBits(new Rectangle(, , width, height), ImageLockMode.WriteOnly, pf);
//获取位图的起始地址
IntPtr iptr = bmpData.Scan0;
//用Marshal的Copy方法,将色彩流字节数组复制到BitmapData中
System.Runtime.InteropServices.Marshal.Copy(rawValues, , iptr, rawValues.Length);
//释放锁
bmp.UnlockBits(bmpData);
return bmp;
}
//重新设置识别对象
private void ResetFaceTracking()
{
foreach (int trackingId in new List<int>(this.trackedSkeletons.Keys))
{
this.RemoveTracker(trackingId);
}
}
//从集合中移动识别信息
private void RemoveTracker(int trackingId)
{
this.trackedSkeletons[trackingId].Dispose();
this.trackedSkeletons.Remove(trackingId);
} private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.ks.Status == KinectStatus.Connected)
{
ks.Stop();
}
}
//定义脸识别类
class SkeletonFaceTracker : IDisposable
{
//定义脸部识别形状三角形数组
private static FaceTriangle[] faceTriangles;
//脸部识别坐标点集合
private EnumIndexableCollection<FeaturePoint, Microsoft.Kinect.Toolkit.FaceTracking.PointF> facePoints;
//脸部跟踪类
private FaceTracker faceTracker;
//定义识别成功标识
private bool lastFaceTrackSucceeded;
//骨骼跟踪状态
private SkeletonTrackingState skeletonTrackingState; public int LastTrackedFrame { get; set; } public void Dispose()
{
if (this.faceTracker != null)
{
this.faceTracker.Dispose();
this.faceTracker = null;
}
}
//用来把识别的信息绘制出来
public void DrawFaceModel(Graphics graphics, ListBox lb)
{
if (!this.lastFaceTrackSucceeded || this.skeletonTrackingState != SkeletonTrackingState.Tracked)
{
return;
} List<System.Drawing.PointF> faceModelPts = new List<System.Drawing.PointF>(); for (int i = ; i < this.facePoints.Count; i++)
{
faceModelPts.Add(new System.Drawing.PointF(this.facePoints[i].X + 0.5f, this.facePoints[i].Y + 0.5f));
}
System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Green); List<System.Drawing.PointF> list = new List<System.Drawing.PointF>();
//遍历所有的三角形,分别画三角形
for (int i = ; i < faceTriangles.Count(); i++)
{
System.Drawing.PointF[] pointFarr = new System.Drawing.PointF[];
pointFarr[] = faceModelPts[faceTriangles[i].First];
pointFarr[] = faceModelPts[faceTriangles[i].Second];
pointFarr[] = faceModelPts[faceTriangles[i].Third];
pointFarr[] = faceModelPts[faceTriangles[i].First];
list.AddRange(pointFarr.Take());
graphics.DrawLines(pen, pointFarr);
} lb.Items.Add(list.GroupBy(f => f).Count() + "点");
int count = list.GroupBy(f => f).Max(s => s.Count());
lb.Items.Add(count);
foreach (var v in list.GroupBy(f => f).Where(s => s.Count() == ))
{
lb.Items.Add(v.Key + " " + );
graphics.FillEllipse(new SolidBrush(System.Drawing.Color.Red), v.Key.X, v.Key.Y, , );
}
foreach (var v in list.GroupBy(f => f).Where(s => s.Count() == ))
{
lb.Items.Add(v.Key + " " + );
graphics.FillEllipse(new SolidBrush(System.Drawing.Color.Blue), v.Key.X, v.Key.Y, , );
}
foreach (var v in list.GroupBy(f => f).Where(s => s.Count() == ))
{
lb.Items.Add(v.Key + " " + );
graphics.FillEllipse(new SolidBrush(System.Drawing.Color.Black), v.Key.X, v.Key.Y, , );
} } /// <summary>
/// 数据更新的方法
/// </summary>
internal void OnFrameReady(ListBox lb, KinectSensor kinectSensor, ColorImageFormat colorImageFormat, byte[] colorImage, DepthImageFormat depthImageFormat, short[] depthImage, Skeleton skeletonOfInterest)
{
this.skeletonTrackingState = skeletonOfInterest.TrackingState;
//判断是否为跟踪状态
if (this.skeletonTrackingState != SkeletonTrackingState.Tracked)
{
return;
}
if (this.faceTracker == null)
{
try
{
//从KinectSensor中实例化出一个脸部识别对象
this.faceTracker = new FaceTracker(kinectSensor);
}
catch (InvalidOperationException)
{
this.faceTracker = null;
}
} if (this.faceTracker != null)
{
//从脸部识别对象中得到脸识别框架
FaceTrackFrame frame = this.faceTracker.Track(
colorImageFormat, colorImage, depthImageFormat, depthImage, skeletonOfInterest);
//标识识别成功
this.lastFaceTrackSucceeded = frame.TrackSuccessful;
if (this.lastFaceTrackSucceeded)
{
if (faceTriangles == null)
{
//得到脸部识别三角形数组
faceTriangles = frame.GetTriangles(); }
//得到脸部识别点的坐标
this.facePoints = frame.GetProjected3DShape(); //加载脸部的空间位置 lb.Items.Add("Rotation 仰低头:" + frame.Rotation.X);
lb.Items.Add("Rotation 左右转头:" + frame.Rotation.Y);
lb.Items.Add("Rotation 左右偏头:" + frame.Rotation.Z);
}
}
} }
}
}
}

Kinect for windows的脸部识别的更多相关文章

  1. Kinect for Windows SDK开发入门(15):进阶指引 下

    Kinect for Windows SDK开发入门(十五):进阶指引 下 上一篇文章介绍了Kinect for Windows SDK进阶开发需要了解的一些内容,包括影像处理Coding4Fun K ...

  2. Kinect for Windows SDK开发入门(十九):Kinect Fusion

        Kinect for Windows SDK1.7中引入了Kinect Fusion功能.在1.8的SDK中对该功能进行了改进和强化,Kinect Fusion能够使得我们使用Kinect f ...

  3. Kinect for Windows SDK开发学习相关资源

    Kinect for Windows SDK(K4W)将Kinect的体感操作带到了平常的应用学习中,提供了一种不同于传统的鼠标,键盘及触摸的无接触的交互方式,在某种程度上实现了自然交互界面的理想,即 ...

  4. [译]Kinect for Windows SDK开发入门(十八):Kinect Interaction交互控件

    本文译自 http://dotneteers.net/blogs/vbandi/archive/2013/03/25/kinect-interactions-with-wpf-part-i-getti ...

  5. Kinect for Windows SDK 1.8的改进及新特性

    今年3月, 微软推出了Kinect for Windows SDK 1.7 更新,包括了手势识别 Kinect Interactions 和实时 3D 建模 Kinect Fusion 两项新技术. ...

  6. Kinect for Windows SDK开发初体验(一)环境配置

    1.开发环境需求 (1).硬件需求 a.需要拥有双核,2.66GHz以上的CPU. b.显卡支持Microsoft DirectX 9.0c; c.2GB的内存 d.Kinect for Window ...

  7. Kinect for Windows SDK开发入门(一):开发环境配置

    [译]Kinect for Windows SDK开发入门(一):开发环境配置 前几天无意中看到微软发布了Kinect for windows sensor,进去看了一下Kinect应用的例子,发现K ...

  8. [Kinect]XBox One Kinect连接Windows

    注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) XBox One带体感套装去年就买了,昨天京东349元入了个适配器,下午就送到了,开箱. ...

  9. kinect for windows - 手势识别之一,C++实现

    用C++来实现手势识别是比较困难的,所以在这个例子,我们只实现了握拳和松手的手势识别,其他没有实现. 先上个效果图: 在这个程序里,我们打开了kinect的RGB流,深度流,骨骼数据流和手势识别流.其 ...

随机推荐

  1. PHPNamespace命名空间

    命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误.这种情况下只要避免命名重复就可以解决,最常见的一种做法是约定一个前缀. 例:项目中有两个 ...

  2. Zookeeper 记录

    本文主要是学习记录: 部分内容为 <从Paxos到Zookeeper> 部分内容为   zookpper 原理分析  https://www.cnblogs.com/leesf456/p/ ...

  3. HIVE配置mysql metastore

    HIVE配置mysql metastore    hive中除了保存真正的数据以外还要额外保存用来描述库.表.数据的数据,称为hive的元数据.这些元数据又存放在何处呢?    如果不修改配置hive ...

  4. python 1秒启动一个下载服务器

    在Linux系统中,进入要下载文件的目录,用python执行以下命令.启动一个简单的文件下载服务器. python2: [root@saltstack-1 apps]# python -m Simpl ...

  5. hadoop 》》 django 简单操作hdfs 语句

    >> from django.shortcuts import render # Create your views here. from hdfs.client import Clien ...

  6. 利用神器BTrace 追踪线上 Spring Boot应用运行时信息

    概述 生产环境中的服务可能会出现各种问题,但总不能让服务下线来专门排查错误,这时候最好有一些手段来获取程序运行时信息,比如 接口方法参数/返回值.外部调用情况 以及 函数执行时间等信息以便定位问题.传 ...

  7. go环境变量配置 (GOROOT和GOPATH)的区别和含义

    GOROOT就是go的安装路径 在~/.bash_profile中添加下面语句: GOROOT=/usr/local/go export GOROOT 当然, 要执行go命令和go工具, 就要配置go ...

  8. List和Dictionary互转

    // 声明Dictionary并初始化 Dictionary<string, string> dic = new Dictionary<string, string>() { ...

  9. luogu P5023 填数游戏

    luogu loj 被这道题送退役了 题是挺有趣的,然而可能讨论比较麻烦,肝了2h 又自闭了,鉴于CSP在即,就只能先写个打表题解了 下面令\(n<m\),首先\(n=1\)时答案为\(2^m\ ...

  10. js之数据类型(对象类型——单体内置对象——Math)

    Math是一个内置对象,它具有数学常数和函数的属性和方法.Math对象用于执行数学任务,和其它对象不同,Math只是一个静态对象并没有Math()构造函数,实际上,Math()只是一个由js设置的对象 ...