Kinect for windows的脸部识别

2023-12-08 17:58
文章标签 windows 识别 kinect 脸部

本文主要是介绍Kinect for windows的脸部识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

需要引入的dll:

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

Kinect for windows提供了脸部识别的功能,可以识出人脸。主要是通过FaceTrackFrame类的GetTriangles()来得到一个三角形数组,这个三角形数组就是给成人面部的基本形状,并且组成的效果是立体的(可以这样理解,可以把3D都拆成三角形来表示,看上去像3D,但其实是2D),这个数组的每个元素都存放着三个整数,分别代码三角形的第一个点,第二个点和第三个点。FaceTrackFrameGetProjected3DShape方法,可以获取一组坐标信息,这样就可以结合三角形数组元素中的点作为索引,从本方法的坐标集合中取出每个三角形的坐标点来了,就可以绘制这些三角形,就可以组成一个人脸的网络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, 640, 480);  
}  
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(0, 0, width, height), ImageLockMode.WriteOnly, pf);  
//获取位图的起始地址  
IntPtr iptr = bmpData.Scan0;  
//用Marshal的Copy方法,将色彩流字节数组复制到BitmapData中   
System.Runtime.InteropServices.Marshal.Copy(rawValues, 0, 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 = 0; 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 = 0; i < faceTriangles.Count(); i++)  
{  
System.Drawing.PointF[] pointFarr = new System.Drawing.PointF[4];  
pointFarr[0] = faceModelPts[faceTriangles[i].First];  
pointFarr[1] = faceModelPts[faceTriangles[i].Second];  
pointFarr[2] = faceModelPts[faceTriangles[i].Third];  
pointFarr[3] = faceModelPts[faceTriangles[i].First];  
list.AddRange(pointFarr.Take(3));  
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() == 10))  
{  
lb.Items.Add(v.Key + " " + 10);  
graphics.FillEllipse(new SolidBrush(System.Drawing.Color.Red), v.Key.X, v.Key.Y, 5, 5);  
}  
foreach (var v in list.GroupBy(f => f).Where(s => s.Count() == 9))  
{  
lb.Items.Add(v.Key + " " + 9);  
graphics.FillEllipse(new SolidBrush(System.Drawing.Color.Blue), v.Key.X, v.Key.Y, 5, 5);  
}  
foreach (var v in list.GroupBy(f => f).Where(s => s.Count() == 8))  
{  
lb.Items.Add(v.Key + " " + 8);  
graphics.FillEllipse(new SolidBrush(System.Drawing.Color.Black), v.Key.X, v.Key.Y, 5, 5);  
}  
}  
/// <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的脸部识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/470803

相关文章

问题-windows-VPN不正确关闭导致网页打不开

为什么会发生这类事情呢? 主要原因是关机之前vpn没有关掉导致的。 至于为什么没关掉vpn会导致网页打不开,我猜测是因为vpn建立的链接没被更改。 正确关掉vpn的时候,会把ip链接断掉,如果你不正确关掉,ip链接没有断掉,此时你vpn又是没启动的,没有域名解析,所以就打不开网站。 你可以在打不开网页的时候,把vpn打开,你会发现网络又可以登录了。 方法一 注意:方法一虽然方便,但是可能会有

Windows/macOS/Linux 安装 Redis 和 Redis Desktop Manager 可视化工具

本文所有安装都在macOS High Sierra 10.13.4进行,Windows安装相对容易些,Linux安装与macOS类似,文中会做区分讲解 1. Redis安装 1.下载Redis https://redis.io/download 把下载的源码更名为redis-4.0.9-source,我喜欢跟maven、Tomcat放在一起,就放到/Users/zhan/Documents

Windows中,.net framework 3.5安装

安装.net framework,目前已知2种方法,如下: 一、在MSDN下载对应的安装包,安装,这种可能无法安装成功,概率很大,不成功使用第二种方法,基本上没问题。 二、win8/8.1/10 下安装 .net framework 3.5.1: 1. 打开 win8/8.1/10 安装盘(这里指系统安装镜像文件),提取 sources\sxs 文件夹到 X:\sources\sxs (X代

Windows 可变刷新率是什么?如何开启?

在现代计算设备中,显示屏的刷新率对用户体验起着至关重要的作用。随着显示技术的不断进步,固定刷新率显示器逐渐被支持可变刷新率(Variable Refresh Rate, VRR)技术的显示器所取代。 可变刷新率定义 可变刷新率是什么?可变刷新率(VRR)是一种显示技术,它允许显示器的刷新率动态调整,以匹配显卡输出的帧率。传统的显示器通常具有固定的刷新率(如60Hz、75Hz等),这意味着显示器

基于CTPN(tensorflow)+CRNN(pytorch)+CTC的不定长文本检测和识别

转发来源:https://swift.ctolib.com/ooooverflow-chinese-ocr.html chinese-ocr 基于CTPN(tensorflow)+CRNN(pytorch)+CTC的不定长文本检测和识别 环境部署 sh setup.sh 使用环境: python 3.6 + tensorflow 1.10 +pytorch 0.4.1 注:CPU环境

百度OCR识别结构结构化处理视频

https://edu.csdn.net/course/detail/10506

如何设置windows计划任务

如何设置windows计划任务 前言:在工作过程中写了一个python脚本,用于调用jira接口查询bug单数量,想要在本地定时任务执行,每天发送到钉钉群提醒,写下操作步骤用于记录。 1. 准备 Python 脚本 确保你的 Python 脚本已经保存到一个文件,比如 jira_reminder.py。 2. 创建批处理文件 为了方便任务计划程序运行 Python 脚本,创建一个批处理文

Pycharm配置conda环境(解决新版本无法识别可执行文件问题)

引言: 很多小伙伴在下载最新版本的pycharm或者更新到最新版本后为项目配置conda环境的时候,发现文件夹目录中无法显示可执行文件(一般为python.exe),以下就是本人遇到该问题后试验和解决该问题的一些方法和思路。 一般遇到该问题的人群有两种,一种是刚入门对pycharm进行conda环境配置的小白(例如我),不熟悉相关环境配置的操作和过程,还有一种是入坑pycharm有段时间的老手

神经网络第四篇:推理处理之手写数字识别

到目前为止,我们已经介绍完了神经网络的基本结构,现在用一个图像识别示例对前面的知识作整体的总结。本专题知识点如下: MNIST数据集图像数据转图像神经网络的推理处理批处理  MNIST数据集          mnist数据图像 MNIST数据集由0到9的数字图像构成。像素取值在0到255之间。每个图像数据都相应地标有“7”、“2”、“1”等数字标签。MNIST数据集中,

vscode python pip : 无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

在vscode中控制台运行python文件出现:无法将"pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 使用vscode开发python,需要安装python开发扩展: 本文已经安装,我们需要找的是python安装所在目录,本文实际路径如下: 如果在本文路径中没有此目录,请尝试在C盘中搜索 python,搜索到相关python目录后,点击Python 3.9进入目录,