如何使用 Kinect 來控制滑鼠鼠標移動 (For Windows SDK V1)
現在看體感控制,其實真的越來越來進步,
所以這些不再是遙不可及或只會在電影出現的畫面。
今天KT要來說明一下 :「如何使用 Kinect 來控制滑鼠鼠標移動」,
原作者Brian Peek,採用KinectWpfViewers控制項來完成,
最近KT收到的來信,都是希望可以改寫KinectWpfViewers的控制項,
或如何不去使用這控制項來完成,這件事確實有點困擾我。
KinectWpfViewers 真的滿好用的,不知道為什麼大家這麼排斥它,
裡面的source code,KT改天再來剖析給大家玩玩看。
所以今天來示範一下,不用KinectWpfViewers控制項,來控制滑鼠鼠標移動。
在講這之前,你需要有"骨架追蹤"的概念,因為這是屬於"骨架追蹤"的延伸應用。
有了骨架追蹤的概念,要來控制滑鼠鼠標移動,就變得是件很簡單的事,
因為只要追蹤出,如:右手關節點,然後將關節點的螢幕X、Y值,
餵給鼠標位置函數,這件事就等於大功告成。
// 取得左手和右手關節點 Joint jointRight = currentSkeleton.Joints[JointType.HandRight]; Joint jointLeft = currentSkeleton.Joints[JointType.HandLeft]; //將3D座標轉換成螢幕2D座標(採用Coding4Fun的ScaleTo方法) Joint scaledRight = jointRight.ScaleTo((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, SkeletonMaxX, SkeletonMaxY); Joint scaledLeft = jointLeft.ScaleTo((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, SkeletonMaxX, SkeletonMaxY); //採用右手關節點的 X和Y座標值,來控制滑鼠標 int cursorX, cursorY; cursorX = (int)scaledRight.Position.X; cursorY = (int)scaledRight.Position.Y; //將右手座標,餵給 SendMouseInput這個方法,來改變滑鼠鼠標位置。 NativeMethods.SendMouseInput(cursorX, cursorY, (int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, leftClick);
另外可在加一些手勢判斷來控制滑鼠,如左手舉高,代表滑鼠左鍵按下:
private const float ClickThreshold = 0.33f;//大於此值,代表手舉高 bool leftClick; //當左手大於舉起高度的臨界值,則代表左鍵按下。 if (jointLeft.Position.Y > ClickThreshold) { leftClick = true; } else { leftClick = false; }
附帶一提,當然如果你是要用左手來控制鼠標,
則餵左手的關節點XY位置給鼠標位置函數:
//採用左手關節點X和Y座標值,來控制滑鼠標 cursorX = (int)scaledLeft.Position.X; cursorY = (int)scaledLeft.Position.Y;
執行畫面:
完整XAML 程式碼如下:
使用說明: 右手:移動,改變滑鼠位置 左手:舉高,左鍵按下
完整C# 程式碼如下:
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using Microsoft.Kinect; using System.Linq; using Coding4Fun.Kinect.Wpf; using Microsoft.Kinect.Samples.CursorControl; namespace KinectMouseControl_Demo { public partial class MainWindow : Window { //大於此值,代表手舉高 private const float ClickThreshold = 0.33f; //骨架 X 和 Y最高值設定 private const float SkeletonMaxX = 0.60f; private const float SkeletonMaxY = 0.40f; //宣告 KinectSensor 裝置ID KinectSensor sensor = KinectSensor.KinectSensors[0]; Skeleton[] skeletons; public MainWindow() { InitializeComponent(); //宣告視窗"載入"和"卸載"處理函數 this.Loaded += new RoutedEventHandler(MainWindow_Loaded); this.Unloaded += new RoutedEventHandler(MainWindow_Unloaded); //平滑處理,防止高頻率微小抖動和突發大跳動造成的關節雜訊 TransformSmoothParameters parameters = new TransformSmoothParameters(); parameters.Smoothing = 0.7f; parameters.Correction = 0.3f; parameters.Prediction = 0.4f; parameters.JitterRadius = 1.0f; parameters.MaxDeviationRadius = 0.5f; sensor.SkeletonStream.Enable(parameters); //開啟骨架追蹤功能 sensor.SkeletonStream.Enable(); } //骨架追蹤處理函數 void runtime_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) { bool receivedData = false; using (SkeletonFrame SFrame = e.OpenSkeletonFrame()) { if (SFrame == null) { // The image processing took too long. More than 2 frames behind. } else { skeletons = new Skeleton[SFrame.SkeletonArrayLength]; SFrame.CopySkeletonDataTo(skeletons); receivedData = true; } } if (receivedData) { Skeleton currentSkeleton = (from s in skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).FirstOrDefault(); if (currentSkeleton != null) { // 取得左手和右手關節點 Joint jointRight = currentSkeleton.Joints[JointType.HandRight]; Joint jointLeft = currentSkeleton.Joints[JointType.HandLeft]; //將3D座標轉換成螢幕2D座標(採用Coding4Fun的ScaleTo方法) Joint scaledRight = jointRight.ScaleTo((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, SkeletonMaxX, SkeletonMaxY); Joint scaledLeft = jointLeft.ScaleTo((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, SkeletonMaxX, SkeletonMaxY); //採用右手關節點的 X和Y座標值,來控制滑鼠標 int cursorX, cursorY; cursorX = (int)scaledRight.Position.X; cursorY = (int)scaledRight.Position.Y; bool leftClick; //當左手大於舉起高度的臨界值,則代表左鍵按下。 if (jointLeft.Position.Y > ClickThreshold) { leftClick = true; } else { leftClick = false; } //將右手座標,餵給 SendMouseInput這個方法,來改變滑鼠鼠標位置。 NativeMethods.SendMouseInput(cursorX, cursorY, (int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, leftClick); } } } //視窗關閉,卸載處裡函數 void MainWindow_Unloaded(object sender, RoutedEventArgs e) { //關閉 Kinect裝置 sensor.Stop(); } //視窗開啟,載入處裡函數 void MainWindow_Loaded(object sender, RoutedEventArgs e) { //宣告骨架追蹤處理函數 sensor.SkeletonFrameReady += runtime_SkeletonFrameReady; //開啟 Kinect裝置 sensor.Start(); } } }
範例程式碼下載:
更多相關資料參考: