สำหรับการวาดเส้นตรงก็ต้องอาศัยจุดสองจุด คือจุดเริ่มต้นกับจุดสิ้นสุด ซึ่งในที่นี้ เราจะลองลากเส้นเชื่อมระหว่างหัวและสะโพก ซึ่งก็คือแนวกระดูกสันหลังนั่นเอง
ความยากอยู่ตรงที่ ตำแหน่งของข้อต่อต่างๆที่ได้จาก Kinect จะวัดเทียบกับแกนของ Kinect เอง (จุดกำเนิดอยู่ที่ตัว Kinect) และตำแหน่งของข้อต่อก็จะอยู่ในหน่วยของเมตร แต่ การแสดงผลบนหน้าจอจะเป็นพิกัดของหน้าต่าง (จุดกำเนิดอยู่มุมบนซ้าย) และขนาดของหน้าจอก็มักจะเท่ากับขนาดของภาพวีดิโอ เช่น 640x480
ดังนั้น จะต้องมีกระบวนการทำ Coordinate Mapping ซึ่งจริงๆแล้วก็ทำได้ไม่ยาก (อาศัยความรู้เรื่อง Computer Graphics) อย่างไรก็ตาม ตัว Kinect SDK เองก็มีฟังก์ชันสำเร็จรูปเพื่อทำงานนี้มาให้เช่นกัน คือ KinectSensor.CoordinateMapper.MapSkeletonPointToColorPoint() หรือ ถ้าเป็นคำสั่งเก่าจะใช้ KinectSensor.MapSkeletonPointToColor()
ตัวอย่างเช่น ถ้าเราต้องการทำ Mapping จากพิกัดของศีรษะใน Kinect ไปยังหน้าต่างขนาด 640x480 พิกเซล ก็จะใช้คำสั่ง
ColorImagePoint headPoint = myKinect.CoordinateMapper.MapSkeletonPointToColorPoint(headJoint.Position, ColorImageFormat.RgbResolution640x480Fps30);
ลองมาดูตัวอย่างกันครับ
ผลลัพธ์ที่ต้องการ (เส้นแนวกระดูกสันหลังที่เชื่อมต่อระหว่างหัวกับสะโพก)
โค้ด UI
<Window x:Class="SkeletonDrawing.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" SizeToContent="WidthAndHeight" Loaded="Window_Loaded"> <Canvas Name="skeletonCanvas" HorizontalAlignment="Center" Height="480" Width="640"/> </Window>
โค้ด C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Microsoft.Kinect; namespace SkeletonDrawing { public partial class MainWindow : Window { KinectSensor myKinect; public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { // Check to see if a Kinect is available if (KinectSensor.KinectSensors.Count == 0) { MessageBox.Show("No Kinects detected", "Camera Viewer"); Application.Current.Shutdown(); return; } // Get the first Kinect on the computer myKinect = KinectSensor.KinectSensors[0]; // Start the Kinect running and select the depth camera try { myKinect.SkeletonStream.Enable(); myKinect.Start(); } catch { MessageBox.Show("Kinect initialise failed", "Camera Viewer"); Application.Current.Shutdown(); } // connect a handler to the event that fires when new frames are available myKinect.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(myKinect_SkeletonFrameReady); } private void myKinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) { // Remove the old skeleton (if exists) skeletonCanvas.Children.Clear(); Skeleton[] skeletons = null; //copy skeleton data to skeleton array using (SkeletonFrame frame = e.OpenSkeletonFrame()) { if (frame != null) { skeletons = new Skeleton[frame.SkeletonArrayLength]; frame.CopySkeletonDataTo(skeletons); } } //if no skeleton data if (skeletons == null) return; //for each skeleton foreach (Skeleton skeleton in skeletons) { //if skeleton is tracked if (skeleton.TrackingState == SkeletonTrackingState.Tracked) { //Head joint Joint headJoint = skeleton.Joints[JointType.Head]; //Hip joint Joint hipJoint = skeleton.Joints[JointType.HipCenter]; //Map head position to canvas //ColorImagePoint headPoint = myKinect.MapSkeletonPointToColor(headJoint.Position, ColorImageFormat.RgbResolution640x480Fps30); ColorImagePoint headPoint = myKinect.CoordinateMapper.MapSkeletonPointToColorPoint(headJoint.Position, ColorImageFormat.RgbResolution640x480Fps30); //Map hip position to canvas //ColorImagePoint hipPoint = myKinect.MapSkeletonPointToColor(hipCenter.Position, ColorImageFormat.RgbResolution640x480Fps30); ColorImagePoint hipPoint = myKinect.CoordinateMapper.MapSkeletonPointToColorPoint(hipJoint.Position, ColorImageFormat.RgbResolution640x480Fps30); //Prepare a line Line backBone = new Line(); backBone.Stroke = new SolidColorBrush(Colors.Red); backBone.StrokeThickness = 5; //Draw a line from head to hip backBone.X1 = headPoint.X; backBone.Y1 = headPoint.Y; backBone.X2 = hipPoint.X; backBone.Y2 = hipPoint.Y; //Add this line to canvas skeletonCanvas.Children.Add(backBone); } }//end for }//end method }//end class }
No comments:
Post a Comment