XAML:
<Window x:Class="WpfApplicationKinectTest2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Unloaded="Window_Unloaded" Loaded="Window_Loaded"> <Grid> <Image Name="Image"></Image> </Grid> </Window>
Code:
using Microsoft.Kinect; using System; using System.Linq; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; namespace WpfApplicationKinectTest2 { /// <summary> /// MainWindow.xaml 的互動邏輯 /// </summary> public partial class MainWindow : Window { /// <summary> /// 影像寬度 /// </summary> private const float RenderWidth = 640.0f; /// <summary> /// 影像高度 /// </summary> private const float RenderHeight = 480.0f; /// <summary> /// 關節厚度 /// </summary> private const double JointThickness = 3; /// <summary> /// 身體中間厚度 /// </summary> private const double BodyCenterThickness = 10; /// <summary> /// 整體區塊厚度 /// </summary> private const double ClipBoundsThickness = 10; /// <summary> /// 身體刷子 /// </summary> private readonly Brush centerPointBrush = Brushes.Blue; /// <summary> /// 追蹤關節筆刷 /// </summary> private readonly Brush trackedJointBrush = new SolidColorBrush(Color.FromArgb(255, 68, 192, 68)); /// <summary> /// 位置的筆刷 /// </summary> private readonly Brush inferredJointBrush = Brushes.Yellow; /// <summary> /// 追蹤的筆 /// </summary> private readonly Pen trackedBonePen = new Pen(Brushes.Green, 6); /// <summary> /// 位置的筆 /// </summary> private readonly Pen inferredBonePen = new Pen(Brushes.Gray, 1); /// <summary> /// 繪圖集合 /// </summary> private DrawingGroup drawingGroup; /// <summary> /// 繪圖影像 /// </summary> private DrawingImage imageSource; /// <summary> /// 感應器 /// </summary> private KinectSensor sensor; /// <summary> /// Color data bytes /// </summary> private byte[] dataPixels = null; /// <summary> /// Track ID /// </summary> private int trackID = -1; public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { //Refresh drawingGroup = new DrawingGroup(); imageSource = new DrawingImage(drawingGroup); Image.Source = this.imageSource; sensor = KinectSensor.KinectSensors[0]; if (sensor != null) { this.sensor.SkeletonStream.Enable(); this.sensor.ColorStream.Enable(); this.sensor.DepthStream.Enable(); this.sensor.SkeletonFrameReady += SensorSkeletonFrameReady; this.sensor.ColorFrameReady += SensorColorFrameReady; this.sensor.DepthFrameReady += sensor_DepthFrameReady; this.sensor.Start(); } } private void Window_Unloaded(object sender, RoutedEventArgs e) { sensor.Stop(); } private void SensorColorFrameReady(object sender, ColorImageFrameReadyEventArgs e) { using (ColorImageFrame frame = e.OpenColorImageFrame()) { if (frame != null) { dataPixels = new byte[frame.PixelDataLength]; frame.CopyPixelDataTo(dataPixels); } } } private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) { Skeleton[] skeletons = new Skeleton[0]; using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame()) { if (skeletonFrame == null) return; if (skeletonFrame != null) { skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength]; skeletonFrame.CopySkeletonDataTo(skeletons); } //取得目前背景 using (DrawingContext dc = this.drawingGroup.Open()) { BitmapSource source = BitmapSource.Create((int)RenderWidth, (int)RenderHeight, 96, 96, PixelFormats.Bgr32, null, dataPixels, 640 * 4); dc.DrawImage(source, new Rect(0.0, 0.0, RenderWidth, RenderHeight)); //還有資料傳入 if (skeletons.Length != 0) { foreach (Skeleton skel in skeletons.Where(skl => skl.TrackingState != SkeletonTrackingState.NotTracked)) { if (skel.TrackingState == SkeletonTrackingState.Tracked) { DrawBonesAndJoints(skel, dc); LockUser(skel); } else if (skel.TrackingState == SkeletonTrackingState.PositionOnly) { dc.DrawEllipse( centerPointBrush, null, SkeletonPointToScreen(skel.Position), BodyCenterThickness, BodyCenterThickness); } } } // prevent drawing outside of our render area drawingGroup.ClipGeometry = new RectangleGeometry(new Rect(0.0, 0.0, RenderWidth, RenderHeight)); } } } private void sensor_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e) { using (DepthImageFrame frame = e.OpenDepthImageFrame()) { short[] depthData = new short[frame.PixelDataLength]; frame.CopyPixelDataTo(depthData); if (depthData == null || depthData.Length == 0) return; FindPalyer(ref depthData); } } /// <summary> /// Find Player ID /// </summary> /// <param name="depthData"></param> private void FindPalyer(ref short[] depthData) { foreach (short data in depthData) { //ID int id = (data & DepthImageFrame.PlayerIndexBitmask) - 1; if (id > 0) { Console.WriteLine("遊戲者ID:" + id); } } } private void LockUser(Skeleton skeleton) { if (skeleton.Joints[JointType.Head].Position.Y < skeleton.Joints[JointType.HandRight].Position.Y) { if (trackID == -1) { trackID = skeleton.TrackingId; if (this.sensor.SkeletonStream.AppChoosesSkeletons == false) { this.sensor.SkeletonStream.AppChoosesSkeletons = true; } this.sensor.SkeletonStream.ChooseSkeletons(trackID); Console.WriteLine("鎖定中, ID:" + trackID); } else { trackID = -1; if (this.sensor.SkeletonStream.AppChoosesSkeletons == true) { this.sensor.SkeletonStream.AppChoosesSkeletons = false; } Console.WriteLine("解鎖"); } Thread.Sleep(700); } } private void DrawBonesAndJoints(Skeleton skeleton, DrawingContext drawingContext) { // Render Torso DrawBone(skeleton, drawingContext, JointType.Head, JointType.ShoulderCenter); DrawBone(skeleton, drawingContext, JointType.ShoulderCenter, JointType.ShoulderLeft); DrawBone(skeleton, drawingContext, JointType.ShoulderCenter, JointType.ShoulderRight); DrawBone(skeleton, drawingContext, JointType.ShoulderCenter, JointType.Spine); DrawBone(skeleton, drawingContext, JointType.Spine, JointType.HipCenter); DrawBone(skeleton, drawingContext, JointType.HipCenter, JointType.HipLeft); DrawBone(skeleton, drawingContext, JointType.HipCenter, JointType.HipRight); // Left Arm DrawBone(skeleton, drawingContext, JointType.ShoulderLeft, JointType.ElbowLeft); DrawBone(skeleton, drawingContext, JointType.ElbowLeft, JointType.WristLeft); DrawBone(skeleton, drawingContext, JointType.WristLeft, JointType.HandLeft); // Right Arm DrawBone(skeleton, drawingContext, JointType.ShoulderRight, JointType.ElbowRight); DrawBone(skeleton, drawingContext, JointType.ElbowRight, JointType.WristRight); DrawBone(skeleton, drawingContext, JointType.WristRight, JointType.HandRight); // Left Leg DrawBone(skeleton, drawingContext, JointType.HipLeft, JointType.KneeLeft); DrawBone(skeleton, drawingContext, JointType.KneeLeft, JointType.AnkleLeft); DrawBone(skeleton, drawingContext, JointType.AnkleLeft, JointType.FootLeft); // Right Leg DrawBone(skeleton, drawingContext, JointType.HipRight, JointType.KneeRight); DrawBone(skeleton, drawingContext, JointType.KneeRight, JointType.AnkleRight); DrawBone(skeleton, drawingContext, JointType.AnkleRight, JointType.FootRight); // Render Joints foreach (Joint joint in skeleton.Joints) { Brush drawBrush = null; if (joint.TrackingState == JointTrackingState.Tracked) //追蹤中 { drawBrush = this.trackedJointBrush; } else if (joint.TrackingState == JointTrackingState.Inferred) //大概位置 { drawBrush = this.inferredJointBrush; } //如果畫筆有被設置,畫出關節為橢圓形 if (drawBrush != null) { drawingContext.DrawEllipse(drawBrush, null, SkeletonPointToScreen(joint.Position), JointThickness, JointThickness); } } } private Point SkeletonPointToScreen(SkeletonPoint skelpoint) { DepthImagePoint depthPoint = this.sensor.CoordinateMapper.MapSkeletonPointToDepthPoint(skelpoint, DepthImageFormat.Resolution640x480Fps30); return new Point(depthPoint.X, depthPoint.Y); } private void DrawBone(Skeleton skeleton, DrawingContext drawingContext, JointType jointType0, JointType jointType1) { Joint joint0 = skeleton.Joints[jointType0]; Joint joint1 = skeleton.Joints[jointType1]; //找不到任何追蹤的點就不動作 if (joint0.TrackingState == JointTrackingState.NotTracked || joint1.TrackingState == JointTrackingState.NotTracked) { return; } //找不到任何位置就不動作 if (joint0.TrackingState == JointTrackingState.Inferred && joint1.TrackingState == JointTrackingState.Inferred) { return; } //兩者都有就畫出位置 Pen drawPen = this.inferredBonePen; if (joint0.TrackingState == JointTrackingState.Tracked && joint1.TrackingState == JointTrackingState.Tracked) { drawPen = trackedBonePen; } //畫出關節與關節的線 drawingContext.DrawLine(drawPen, SkeletonPointToScreen(joint0.Position), SkeletonPointToScreen(joint1.Position)); } } }
參考資料:
http://msdn.microsoft.com/en-us/library/jj131025.aspx