KINECT的骨架偵測點主要是以SPINE這個點為主,偵測到這個點才會開始判斷其他點的位置
距離太近就有可能會出現判斷方向相反,在測試時就有可能發生左腳被偵測到右腳去了,右腳跑來左腳的位置…
載入程式就觸發事件,將畫布重置,嘗試去取得KINECT的感應器的骨架資料
取得到骨架資料就由SensorSkeletonFrameReady開始來取資料,使用RenderClippedEdges去得知有沒有超過邊界,有就將紅色畫在邊框;再來使用DrawBone將A關節點到B關節點畫成直線,並將關節畫成橢圓形
using System.Windows; using System.Windows.Media; using Microsoft.Kinect; namespace WpfApplication3 { /// <summary> /// MainWindow.xaml 的互動邏輯 /// </summary> public partial class MainWindow : Window { //影像寬度 private const float RenderWidth = 640.0f; //影像高度 private const float RenderHeight = 480.0f; //關節厚度 private const double JointThickness = 3; //身體中間厚度 private const double BodyCenterThickness = 10; //整體區塊厚度 private const double ClipBoundsThickness = 10; //身體刷子 private readonly Brush centerPointBrush = Brushes.Blue; //追蹤關節筆刷 private readonly Brush trackedJointBrush = new SolidColorBrush(Color.FromArgb(255, 68, 192, 68)); //位置的筆刷 private readonly Brush inferredJointBrush = Brushes.Yellow; //追蹤的筆 private readonly Pen trackedBonePen = new Pen(Brushes.Green, 6); //位置的筆 private readonly Pen inferredBonePen = new Pen(Brushes.Gray, 1); //繪圖集合 private DrawingGroup drawingGroup; //繪圖影像 private DrawingImage imageSource; //感應器 private KinectSensor sensor; public MainWindow() { InitializeComponent(); } #region 表單載入 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) { sensor.SkeletonStream.Enable(); sensor.SkeletonFrameReady += SensorSkeletonFrameReady; sensor.Start(); } } #endregion 表單載入 #region 結束程式 private void Window_Unloaded(object sender, RoutedEventArgs e) { sensor.Stop(); } #endregion 結束程式 #region 處理超過邊界的事件 private void RenderClippedEdges(Skeleton skeleton, DrawingContext drawingContext) { //超過最底,則會紅線 if (skeleton.ClippedEdges.HasFlag(FrameEdges.Bottom)) { drawingContext.DrawRectangle( Brushes.Red, null, new Rect(0, RenderHeight - ClipBoundsThickness, RenderWidth, ClipBoundsThickness)); } //超過最頂端,則顯示紅線 if (skeleton.ClippedEdges.HasFlag(FrameEdges.Top)) { drawingContext.DrawRectangle( Brushes.Red, null, new Rect(0, 0, RenderWidth, ClipBoundsThickness)); } //超過最左邊,則顯示紅線 if (skeleton.ClippedEdges.HasFlag(FrameEdges.Left)) { drawingContext.DrawRectangle( Brushes.Red, null, new Rect(0, 0, ClipBoundsThickness, RenderHeight)); } //超過最右邊,則顯示紅線 if (skeleton.ClippedEdges.HasFlag(FrameEdges.Right)) { drawingContext.DrawRectangle( Brushes.Red, null, new Rect(RenderWidth - ClipBoundsThickness, 0, ClipBoundsThickness, RenderHeight)); } } #endregion 處理超過邊界的事件 #region 感應器接收資料 private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) { Skeleton[] skeletons = new Skeleton[0]; using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame()) { if (skeletonFrame != null) { skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength]; skeletonFrame.CopySkeletonDataTo(skeletons); } } //取得目前背景 using (DrawingContext dc = this.drawingGroup.Open()) { //將背景重畫 dc.DrawRectangle(Brushes.Black, null, new Rect(0.0, 0.0, RenderWidth, RenderHeight)); //還有資料傳入 if (skeletons.Length != 0) { foreach (Skeleton skel in skeletons) { RenderClippedEdges(skel, dc); if (skel.TrackingState == SkeletonTrackingState.Tracked) { DrawBonesAndJoints(skel, dc); } else if (skel.TrackingState == SkeletonTrackingState.PositionOnly) { dc.DrawEllipse( centerPointBrush, null, this.SkeletonPointToScreen(skel.Position), BodyCenterThickness, BodyCenterThickness); } } } // prevent drawing outside of our render area drawingGroup.ClipGeometry = new RectangleGeometry(new Rect(0.0, 0.0, RenderWidth, RenderHeight)); } } #endregion 感應器接收資料 #region 畫出骨頭與關節 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); } } } #endregion 畫出骨頭與關節 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/hh438998.aspx
http://msdn.microsoft.com/en-us/library/hh973074.aspx
http://msdn.microsoft.com/en-us/library/jj131025.aspx
http://msdn.microsoft.com/en-us/library/hh973077.aspx
http://msdn.microsoft.com/en-us/library/hh855353.aspx
http://msdn.microsoft.com/en-us/library/hh973073.aspx
http://msdn.microsoft.com/en-us/library/jj131024.aspx
http://msdn.microsoft.com/en-us/library/jj131429.aspx
http://msdn.microsoft.com/en-us/library/dn188677.aspx
http://stackoverflow.com/questions/2060478/c-sharp-redaction-drawing-on-image
參考圖片:
http://i.msdn.microsoft.com/dynimg/IC534688.png
http://i.msdn.microsoft.com/dynimg/IC584841.png