Kinect for windows的脸部识别
需要引入的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的脸部识别的更多相关文章
- Kinect for Windows SDK开发入门(15):进阶指引 下
Kinect for Windows SDK开发入门(十五):进阶指引 下 上一篇文章介绍了Kinect for Windows SDK进阶开发需要了解的一些内容,包括影像处理Coding4Fun K ...
- Kinect for Windows SDK开发入门(十九):Kinect Fusion
Kinect for Windows SDK1.7中引入了Kinect Fusion功能.在1.8的SDK中对该功能进行了改进和强化,Kinect Fusion能够使得我们使用Kinect f ...
- Kinect for Windows SDK开发学习相关资源
Kinect for Windows SDK(K4W)将Kinect的体感操作带到了平常的应用学习中,提供了一种不同于传统的鼠标,键盘及触摸的无接触的交互方式,在某种程度上实现了自然交互界面的理想,即 ...
- [译]Kinect for Windows SDK开发入门(十八):Kinect Interaction交互控件
本文译自 http://dotneteers.net/blogs/vbandi/archive/2013/03/25/kinect-interactions-with-wpf-part-i-getti ...
- Kinect for Windows SDK 1.8的改进及新特性
今年3月, 微软推出了Kinect for Windows SDK 1.7 更新,包括了手势识别 Kinect Interactions 和实时 3D 建模 Kinect Fusion 两项新技术. ...
- Kinect for Windows SDK开发初体验(一)环境配置
1.开发环境需求 (1).硬件需求 a.需要拥有双核,2.66GHz以上的CPU. b.显卡支持Microsoft DirectX 9.0c; c.2GB的内存 d.Kinect for Window ...
- Kinect for Windows SDK开发入门(一):开发环境配置
[译]Kinect for Windows SDK开发入门(一):开发环境配置 前几天无意中看到微软发布了Kinect for windows sensor,进去看了一下Kinect应用的例子,发现K ...
- [Kinect]XBox One Kinect连接Windows
注:本文全原创,作者:Noah Zhang (http://www.cnblogs.com/noahzn/) XBox One带体感套装去年就买了,昨天京东349元入了个适配器,下午就送到了,开箱. ...
- kinect for windows - 手势识别之一,C++实现
用C++来实现手势识别是比较困难的,所以在这个例子,我们只实现了握拳和松手的手势识别,其他没有实现. 先上个效果图: 在这个程序里,我们打开了kinect的RGB流,深度流,骨骼数据流和手势识别流.其 ...
随机推荐
- Flutter路由_fluro引入配置和使用
Flutter本身提供了路由机制,作个人的小型项目,完全足够了.但是如果你要作企业级开发,可能就会把入口文件变得臃肿不堪.而再Flutter问世之初,就已经了企业级路由方案fluro. flutter ...
- 神经网络手写数字识别numpy实现
本文摘自Michael Nielsen的Neural Network and Deep Learning,该书的github网址为:https://github.com/mnielsen/neural ...
- jdbc访问oracle超慢,但是PLSQL访问正常
oracle数据库连接非常慢,sqlplus很快,用客户端就很慢,十几秒才好.然后服务器内存一下就飙升到了90%,最开始以为是表空间占满了,数据库连接数占满了.折腾了半天,重启,还是很慢.应用连接数据 ...
- 【ARM-Linux开发】Linux下查看机器的CPU负载
负载(load)是Linux机器的一个重要指标,直观了反应了机器当前的状态.如果机器负载过高,那么对机器的操作将难以进行. Linux的负载高,主要是由于CPU使用.内存使用.IO消耗三部分构成.任意 ...
- 【DSP开发】德州仪器达芬奇五年之路七宗罪,嵌入式处理器架构之争决战2012
芯片是产业链上游重要的一个环节,一颗小小的芯片具有极高的技术含量和价值,半导体行业每年都会有一个各大厂商营业额的排名,除去2009年,常年盘踞在前三名位置的分别是英特尔,三星半导体和德州仪器,英特尔凭 ...
- JavaScript 短路值
了解表达式中的短路值. 逻辑运算从左到右.逻辑或运算,当左边的条件成立时,后面的条件将不再参与运算.因此在逻辑或运算中,尽量将条件结果为true的放第一位.而在逻辑与运算中,尽量将条件结果为false ...
- HTML 全局属性 = HTML5 中添加的属性。
属性 描述 accesskey 规定激活元素的快捷键. class 规定元素的一个或多个类名(引用样式表中的类). contenteditable 规定元素内容是否可编辑. contextmenu 规 ...
- storm并行度核心概念介绍剖析
一.Storm的并行介绍 并行意味着多个任务在不同的节点上,且每个节点都可独立运行,并且相互之间没有依赖. 而在storm上,storm提交的jobs(任务)通过nimbus分发到多个supervis ...
- 在windows系统下打包linux平台运行的go程序
在windows系统下打包linux平台运行的go程序 1.先在main.go下打包成.exe可执行程序测试代码是否正确 //cd到main.go目录 go build //打包命令 如果打包成功则表 ...
- 下载HTMLTestRunner 地址
通过pip安装 HTMLTestRunne失败 则需要通过手动下载. 下载地址: http://tungwaiyip.info/software/HTMLTestRunner.html 下载后,把H ...