Kinect – 计算器 – 调整骨骼运动至鼠标





5.00/5 (4投票s)
Kinect – 计算器 – 调整骨骼运动至鼠标
在我的上一篇博文中,Kinect – 创建按钮,我展示了一种为 Windows 创建 Kinect 按钮的方法。在接下来的博文中,我将展示更多通过移动 Windows 鼠标光标基于 Kinect 骨骼右手的姿势来实现的方法。
为什么要创建 Kinect 按钮?
为什么不使用 Windows 鼠标光标,并创建出色的手势或头部运动()来模拟点击,这样我们就无需创建专门的 Kinect 按钮了呢?
答案
- 你至少需要站在离电脑屏幕 1 米的距离之外,即使这样,我年纪大了,也无法从那么远的距离清晰地看到…
- Kinect 的精确度仍然不够完美,并且从那么远的距离点击一个 48x48 的按钮是很困难的。
- 即使你增加了桌面分辨率,用双手同时操作点击仍然不简单也不实用。
- 但是,我仍然要这样做!放大镜、酷炫的头部或手势运动等等。
在这篇博文中,我将把那些 Kinect 按钮(基于计时器工作)实现到一个我构建的简单的计算器
上,并将 Windows 鼠标钩接到骨骼运动上。
其中唯一的主要问题是将骨骼位置调整到你的屏幕分辨率,正如你所知,骨骼坐标以米为单位表示,并且来自 640x480 的屏幕,所以我创建了一个名为 Positions
的新类来帮助我完成这项工作。
AdjustToScreen
方法获取关节(并基于当前的屏幕分辨率),另一个方法获取关节和特定的屏幕宽度和高度。
public static class Positions
{
//For - Resolution640x480
private const float SkeletonMaxX = 0.6f;
private const float SkeletonMaxY = 0.4f;
private static float Adjust(int primaryScreenResolution,
float maxJointPosition, float jointPosition)
{
var value = (((((float)primaryScreenResolution) / maxJointPosition) / 2f) *
jointPosition)
+ (primaryScreenResolution / 2);
if (value > primaryScreenResolution || value < 0f) return 0f;
return value;
}
/// <summary>
/// Get the current Joint position and Adjust the Skeleton
/// joint position to the current Screen resolution.
/// </summary>
/// <param name="joint">Joint to Adjust</param>
/// <returns></returns>
public static Vector AdjustToScreen(Joint joint)
{
var newVector = new Vector
{
X = Adjust((int)SystemParameters.PrimaryScreenWidth,
SkeletonMaxX, joint.Position.X),
Y = Adjust((int)SystemParameters.PrimaryScreenHeight,
SkeletonMaxY, -joint.Position.Y),
Z = joint.Position.Z,
W = joint.Position.W
};
return newVector;
}
/// <summary>
/// Get the current Joint position and Adjust the Skeleton joint
/// position to a specific Screen Size.
/// </summary>
/// <param name="joint">Joint to Adjust</param>
/// <param name="screenWidth">Screen Width</param>
/// <param name="screenHeight">Screen Height</param>
/// <returns></returns>
public static Vector AdjustToScreen(Joint joint, int screenWidth, int screenHeight)
{
var newVector = new Vector
{
X = Adjust(screenWidth, SkeletonMaxX, joint.Position.X),
Y = Adjust(screenHeight, SkeletonMaxY, -joint.Position.Y),
Z = joint.Position.Z,
W = joint.Position.W
};
return newVector;
}
}
现在我创建了另一个辅助类,名为 – NativeMethods
,用于根据骨骼关节位置移动和设置鼠标光标位置。
public static class NativeMethods
{
public partial class MouseOperations
{
[DllImport("user32.dll")]
public static extern bool SetCursorPos(int x, int y);
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out Point pt);
}
}
在 SkeletonFrameReady
中,我添加了另一个质量检查,还检查了关节的 TrakingState
,而不仅仅是数据的 TrakingState
,并且确保关节位置质量(W
)足够高,然后再移动鼠标。
质量检查将防止鼠标跳动。
void SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
foreach (SkeletonData data in e.SkeletonFrame.Skeletons)
{
//Tracked that defines whether a skeleton is 'tracked' or not.
//The untracked skeletons only give their position.
if (data.TrackingState != SkeletonTrackingState.Tracked) continue;
//Each joint has a Position property that is defined by a Vector4: (x, y, z, w).
//The first three attributes define the position in camera space.
//The last attribute (w)
//gives the quality level (between 0 and 1) of the
foreach (Joint joint in data.Joints)
{
switch (joint.ID)
{
case JointID.HandRight:
if (joint.Position.W < 0.6f || joint.TrackingState !=
JointTrackingState.Tracked) return;// Quality check
//Based on Skeleton Right Hand Position adjust the location
//to the screen
var newPos = Positions.AdjustToScreen(joint);
if (newPos.X == 0f || newPos.Y == 0f) return;
NativeMethods.MouseOperations.SetCursorPos(
Convert.ToInt32(newPos.X), Convert.ToInt32(newPos.Y));
break;
}
}
}
}
确保你启用了 TransformSmooth
,你不想让鼠标跳动。(Kinect–如何使用 TransformSmoothParameters 应用平滑帧显示)。
_kinectNui.SkeletonEngine.TransformSmooth = true;
var parameters = new TransformSmoothParameters
{
Smoothing = 1.0f,
Correction = 0.1f,
Prediction = 0.1f,
JitterRadius = 0.05f,
MaxDeviationRadius = 0.05f
};
_kinectNui.SkeletonEngine.SmoothParameters = parameters;
演示项目
这个项目包含一个 Common 类,其中包含本博文的主要方法,例如移动鼠标和将 Kinect 骨骼调整到桌面分辨率。
尽情享用!