Kinect for windows的脸部识别
需要引入的dll:
需要將下面兩個(gè)dll復(fù)制到當(dāng)前路徑
Kinect for windows提供了臉部識別的功能,可以識出人臉。主要是通過FaceTrackFrame類的GetTriangles()來得到一個(gè)三角形數(shù)組,這個(gè)三角形數(shù)組就是給成人面部的基本形狀,并且組成的效果是立體的(可以這樣理解,可以把3D都拆成三角形來表示,看上去像3D,但其實(shí)是2D),這個(gè)數(shù)組的每個(gè)元素都存放著三個(gè)整數(shù),分別代碼三角形的第一個(gè)點(diǎn),第二個(gè)點(diǎn)和第三個(gè)點(diǎn)。FaceTrackFrame的GetProjected3DShape方法,可以獲取一組坐標(biāo)信息,這樣就可以結(jié)合三角形數(shù)組元素中的點(diǎn)作為索引,從本方法的坐標(biāo)集合中取出每個(gè)三角形的坐標(biāo)點(diǎn)來了,就可以繪制這些三角形,就可以組成一個(gè)人臉的網(wǎng)絡(luò)3D效果圖了。
本例是從色彩攝像頭中獲取彩色數(shù)據(jù)流,并顯示到窗體上,再通過FaceTracker得到得到臉部3D信息,并用GDI+的方式把網(wǎng)絡(luò)圖形畫到窗體上,這時(shí)就可以在真實(shí)圖像上看到浮著一張網(wǎng)絡(luò)的面套。同時(shí)可以得出臉部交匯最多的坐標(biāo),并用GDI+添加上不同有色彩,同時(shí)還可以得到人體面部和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窗體刷新不閃動(dòng) this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.DoubleBuffer, true); //找到連接的Kinect設(shè)備 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(); //訂閱跟蹤數(shù)據(jù)讀取事件 this.ks.AllFramesReady += OnAllFramesReady; ks.Start(); } } //這個(gè)方法很重要,就是重繪人臉跟蹤采集到的數(shù)據(jù) protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); foreach (SkeletonFaceTracker faceInformation in this.trackedSkeletons.Values) { //第一個(gè)參數(shù)為當(dāng)前窗體為畫布,第二個(gè)是添加采集到的信息到listbox中,這個(gè)方法畫識別到臉部的信息 faceInformation.DrawFaceModel(e.Graphics, Messbox_LB); } } //定義臉部識別的集合 private readonly Dictionary<int, SkeletonFaceTracker> trackedSkeletons = new Dictionary<int, SkeletonFaceTracker>(); //色彩流字節(jié)數(shù)組 private byte[] colorImage; private ColorImageFormat colorImageFormat = ColorImageFormat.Undefined; //深度流字節(jié)數(shù)組 private short[] depthImage; private DepthImageFormat depthImageFormat = DepthImageFormat.Undefined; //骨骼信息數(shù)組 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]; } //獲取各種數(shù)據(jù)流信息 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)) { //把獲取的數(shù)據(jù)流的相關(guān)信息傳給OnFrameReady方法 skeletonFaceTracker.OnFrameReady(Messbox_LB, this.ks, colorImageFormat, colorImage, depthImageFormat, depthImage, skeleton); skeletonFaceTracker.LastTrackedFrame = skeletonFrame.FrameNumber; } } } //這個(gè)刷新會觸發(fā)窗體的重畫,OnPaint方法會被調(diào)用。 this.Refresh(); //把色彩流轉(zhuǎn)轉(zhuǎn)成位圖顯示成窗體的背景 this.BackgroundImage = ToGrayBitmap(colorImage, 640, 480); } finally { if (colorImageFrame != null) { colorImageFrame.Dispose(); } if (depthImageFrame != null) { depthImageFrame.Dispose(); } if (skeletonFrame != null) { skeletonFrame.Dispose(); } } } //把色采流數(shù)據(jù)轉(zhuǎn)成位圖返回 public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height) { //定議轉(zhuǎn)換圖片的格式,一個(gè)像素占32個(gè),前24位為紅綠藍(lán),后8位為空 PixelFormat pf = PixelFormat.Format32bppRgb; //申請目標(biāo)位圖的變量 Bitmap bmp = new Bitmap(width, height, pf); //將其內(nèi)存區(qū)域鎖定 BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, pf); //獲取位圖的起始地址 IntPtr iptr = bmpData.Scan0; //用Marshal的Copy方法,將色彩流字節(jié)數(shù)組復(fù)制到BitmapData中 System.Runtime.InteropServices.Marshal.Copy(rawValues, 0, iptr, rawValues.Length); //釋放鎖 bmp.UnlockBits(bmpData); return bmp; } //重新設(shè)置識別對象 private void ResetFaceTracking() { foreach (int trackingId in new List<int>(this.trackedSkeletons.Keys)) { this.RemoveTracker(trackingId); } } //從集合中移動(dòng)識別信息 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 { //定義臉部識別形狀三角形數(shù)組 private static FaceTriangle[] faceTriangles; //臉部識別坐標(biāo)點(diǎn)集合 private EnumIndexableCollection<FeaturePoint, Microsoft.Kinect.Toolkit.FaceTracking.PointF> facePoints; //臉部跟蹤類 private FaceTracker faceTracker; //定義識別成功標(biāo)識 private bool lastFaceTrackSucceeded; //骨骼跟蹤狀態(tài) 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() + "點(diǎn)"); 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> /// 數(shù)據(jù)更新的方法 /// </summary> internal void OnFrameReady(ListBox lb, KinectSensor kinectSensor, ColorImageFormat colorImageFormat, byte[] colorImage, DepthImageFormat depthImageFormat, short[] depthImage, Skeleton skeletonOfInterest) { this.skeletonTrackingState = skeletonOfInterest.TrackingState; //判斷是否為跟蹤狀態(tài) if (this.skeletonTrackingState != SkeletonTrackingState.Tracked) { return; } if (this.faceTracker == null) { try { //從KinectSensor中實(shí)例化出一個(gè)臉部識別對象 this.faceTracker = new FaceTracker(kinectSensor); } catch (InvalidOperationException) { this.faceTracker = null; } } if (this.faceTracker != null) { //從臉部識別對象中得到臉識別框架 FaceTrackFrame frame = this.faceTracker.Track( colorImageFormat, colorImage, depthImageFormat, depthImage, skeletonOfInterest); //標(biāo)識識別成功 this.lastFaceTrackSucceeded = frame.TrackSuccessful; if (this.lastFaceTrackSucceeded) { if (faceTriangles == null) { //得到臉部識別三角形數(shù)組 faceTriangles = frame.GetTriangles(); } //得到臉部識別點(diǎn)的坐標(biāo) this.facePoints = frame.GetProjected3DShape(); //加載臉部的空間位置 lb.Items.Add("Rotation 仰低頭:" + frame.Rotation.X); lb.Items.Add("Rotation 左右轉(zhuǎn)頭:" + frame.Rotation.Y); lb.Items.Add("Rotation 左右偏頭:" + frame.Rotation.Z); } } } } } } }?
轉(zhuǎn)載于:https://www.cnblogs.com/shouhouxiaomuwu/p/3389541.html
總結(jié)
以上是生活随笔為你收集整理的Kinect for windows的脸部识别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SqlServer 自动化分区方案
- 下一篇: SQL Server存储过程(转载)