也就是將骨架結合影像,順便來衝篇數XDDD
結合後可以幹嗎?就可以用一把光劍啊,或者讓使用者測試衣服是否符合自己的需求等等的功能
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
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;
private byte[] dataPixels = null;
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.ColorStream.Enable();
sensor.SkeletonFrameReady += SensorSkeletonFrameReady;
sensor.ColorFrameReady += SensorColorFrameReady;
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 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)
{
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.DrawRectangle(Brushes.Black, null, new Rect(0.0, 0.0, RenderWidth, RenderHeight));
dc.DrawImage(source, 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,
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://writecodepeople.blogspot.tw/2013/05/cnet-kinect.html
http://writecodepeople.blogspot.tw/2013/05/cnet-wpfkinect.html