需要引入的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. Unity3d 烘培lightingmap 注意的2点.

    1.在Qulity里面设置合适的灯光数量.否则,你会发现烘培出来的场景,有些灯光没有起作用. 2.在导入模型时候,注意勾选:Generate Lightingmap .  否则,模型没办法烘培. 3. ...

  2. linux中环境变量设置

    Linux下环境变量设置的三种方法: 如想将一个路径加入到$PATH中,可以像下面这样做: 只对当前的shell 起作用的环境变量 1.控制台中设置,不赞成这种方式,因为他只对当前的shell 起作用 ...

  3. 【AMAD]django-filter -- 一个通用的,基于用户选择的Django Queryset 过滤系统

    简介 用法 和DRF集成 个人评分 简介 django-filter1可以通过URL的query string参数,动态对Queryset进行过滤. 用法 import django_filters ...

  4. logstash1 - kafka - logstash2 - elasticsearch - kibana

    0.拓扑图 参考:https://www.cnblogs.com/JetpropelledSnake/p/10057545.html 1.logstash的配置 [root@VM_0_4_centos ...

  5. 《C++ Primer》读书笔记之第15章:面向对象编程

    一.面向对象概述 1. 面向对象的三个基本特性 封装.继承和多态. 2. 封装 指把隐藏对象的实现细节,仅对外提供接口,从而达到接口与实现分离的效果.封装的好处:一是提高数据的安全性,用户只能使用对象 ...

  6. [转帖]中国新超算彻底告别进口CPU 国产芯片已可与国外抗衡

    中国新超算彻底告别进口CPU 国产芯片已可与国外抗衡 蓝天·2017-10-17·本土IC 来源: 观察者网 https://www.laoyaoba.com/html/news/newsdetail ...

  7. (十八)JDBC获取存储过程和主键

    目录 获取数据库自动生成的主键: JDBC调用存储过程 获取数据库自动生成的主键: update 更新操作以后,如果需要用到结果集,可以通过 PreparedStatement.getResultSe ...

  8. if (strAreaCode.Find("体检")>=0)

    string类提供了6种查找函数,每种函数以不同形式的find命名. 这些操作全部返回string::size_type类型的值,以下形式标记查找匹配所发生的位置: 或者返回一个名为string::n ...

  9. Spring实战(二)Spring容器和bean的生命周期

    引入问题: 在XML配置文件中配置bean后,这些文件又是如何被加载的?它们被加载到哪里去了? Spring容器——框架核心 1.什么是Spring容器?它的功能是什么? 在基于Spring的应用中, ...

  10. linux下mysql数据导入到redis

    自Redis 2.6以上版本起,Redis支持快速大批量导入数据,即Pipe传输.通过将要导入的命令转换为Resp格式,然后通过MySQL的concat()来整理出最终导入的命令集合,以达到快速导入的 ...