如何使用 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();
}
}
}
範例程式碼下載:
更多相關資料參考:

