随着对这项新技术感兴趣的程序员、学生和粉丝数量的增加,Kinect编程工具和API的开发也日益增多。本文将探讨Kinect.Toolbox和coding4Fun这两个最常用的API的使用。
在开始之前,需要准备以下工具和环境:
请确保已经下载并安装了Kinect SDK Beta版本。
首先,需要下载Kinect.Toolbox和Coding4Fun这两个API及其代码。请访问它们的官方网站进行下载。
注意:请确保下载的是适用于WinForm的API和代码。
下载并安装API后,将在Visual Studio中创建一个新的WinForms项目,并添加这些API的DLL文件作为项目引用。
Kinect SDK的DLL文件通常位于以下路径:
C:\Program Files (x86)\Microsoft Research KinectSDK
接下来,在Visual Studio中打开一个新的WinForms项目,并添加以下API的引用:
using Microsoft.Research.Kinect.Nui;
using Kinect.Toolbox;
using Coding4Fun.Kinect.Winform;
在Kinect编程中,手部是最常用的身体部位,因为它是身体最互动的部分。在本节中,将检测右手的移动,并使用API来确定移动的方向,例如从右到左、从下到上等。
首先,在Form1类中初始化一些字段,这些字段将在后续步骤中使用:
private void Form1_Load(object sender, EventArgs e)
{
try
{
nui.Initialize(RuntimeOptions.UseSkeletalTracking);
}
catch (InvalidOperationException)
{
MessageBox.Show("Runtime initialization failed. Please make sure Kinect device is plugged in.");
return;
}
// 添加事件
nui.SkeletonFrameReady += new EventHandler(nui_SkeletonFrameReady);
SwG.OnGestureDetected += On_GestureDetected;
}
现在,将在Form1的加载事件中初始化Kinect,并将其事件链接到相应的方法(C#中的委托机制)。
将以下代码添加到Form1的加载事件中:
private void Form1_Load(object sender, EventArgs e)
{
try
{
nui.Initialize(RuntimeOptions.UseSkeletalTracking);
}
catch (InvalidOperationException)
{
MessageBox.Show("Runtime initialization failed. Please make sure Kinect device is plugged in.");
return;
}
// 添加事件
nui.SkeletonFrameReady += new EventHandler(nui_SkeletonFrameReady);
SwG.OnGestureDetected += On_GestureDetected;
}
在这段代码的try-catch块中,启动Kinect设备。如果设备出现问题(例如电源关闭或USB线未连接到计算机),将抛出异常。
在第二个代码块中,检测身体。如果Kinect检测到身体,nui_SkeletonFrameReady方法将响应此事件,此事件有一个参数,即检测到的身体,在Kinect SDK中称为SkeletonFrame。
最后,将移动事件链接到将响应此移动的方法。
为了响应上一步中看到的两个事件,需要使用与这些事件链接的方法。为此,请将这两个方法添加到Form1类中:
方法1:检测身体的右手(检测第一个骨架的一个关节)。
void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
SkeletonFrame allSkeletons = e.SkeletonFrame;
// 获取第一个跟踪的骨架
SkeletonData skeleton = (from s in allSkeletons.Skeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).FirstOrDefault();
// 测试骨架是否存在并被跟踪
if (skeleton != null && skeleton.TrackingState == SkeletonTrackingState.Tracked)
{
SwG.Add(skeleton.Joints[JointID.HandRight].Position, nui.SkeletonEngine);
// 将这些关节缩放到主屏幕的宽度和高度
Joint scaledRight = skeleton.Joints[JointID.HandRight].ScaleTo((int)SystemInformation.PrimaryMonitorSize.Width, (int)SystemInformation.PrimaryMonitorSize.Height, SkeletonMaxX, SkeletonMaxY);
}
}
在这段代码中,获取Kinect设备检测到的第一个身体(它可以检测到两个身体),然后将右手与移动事件链接,以检测右手的移动:SwG.Add()...等等。
方法2:检测右手的手势。
为此,请将此方法添加到Form1类中,以响应OnGestureDetected事件:
public void On_GestureDetected(string gest)
{
// 如果手势是向右滑动,则转到下一张图片
if (gest == "SwipeToRight")
suivant();
// 如果手势是向左滑动,则转到上一张图片
if (gest == "SwipeToLeft")
precedente();
// 例如:是一个方法
}
当Kinect设备检测到跟踪的关节(右手)向左或向右滑动时,将在此方法中触发手势事件,"SwipeToRight"和"SwipeToLeft"是Kinect.Toolbox API中声明的两个字符串,因此在方法是测试右手是从左到右还是从右到左移动,根据这个手部移动做出相应的操作。
技巧1:如果测试这段代码,会发现对手势的响应太快,没有在应用程序和手势之间获得良好的交互性,因此为了解决这个问题,可以像这样修改SkeletonEngine的抖动:
#region TransformSmooth
// 必须设置为true,并在调用Initialize之后设置
nui.SkeletonEngine.TransformSmooth = true;
// 用于转换和减少抖动
var parameters = new TransformSmoothParameters
{
Smoothing = 0.75f,
Correction = 0.07f,
Prediction = 0.08f,
JitterRadius = 0.08f,
MaxDeviationRadius = 0.07f
};
nui.SkeletonEngine.SmoothParameters = parameters;
#endregion
技巧2:在Kinect.toolbox中看到只有两种类型的手势SwipeToRight和SwipeToLeft,其他类型的手势可以通过修改源代码在API中实现,在这个技巧中将看到如何添加BackToFront并在代码中使用它,例如在屏幕上选择某个项目。
首先去Kinect.Toolbox的源代码,在SwipeGestureDetector.cs类中修改LookForGesture()方法,通过添加以下代码:
void LookForGesture()
{
// 从左到右
if (ScanPositions ((P1, P2) => Math.Abs(P2.Y - P1.Y) < 0.20f, (P1, P2) => P2.X - P1.X > -0.01f, (P1, P2) => Math.Abs(P2.X - P1.X) > 0.2f, 250, 2500))
{
RaiseGestureDetected("LeftToRight");
return;
}
// 从右到左
if (ScanPositions ((P1, P2) => Math.Abs(P2.Y - P1.Y) < 0.20f, (P1, P2) => P2.X - P1.X < 0.01f, (P1, P2) => Math.Abs(P2.X - P1.X) > 0.2f, 250, 2500))
{
RaiseGestureDetected("RightToLeft");
return;
}
// 从后到前
if (ScanPositions ((P1, P2) => Math.Abs(P2.Y - P1.Y) < 0.15f, (P1, P2) => P2.Z - P1.Z < 0.01f, (P1, P2) => Math.Abs(P2.Z - P1.Z) > 0.2f, 250, 2500))
{
RaiseGestureDetected("BackToFront");
return;
}
// 从前到后
if (ScanPositions ((P1, P2) => Math.Abs(P2.Y - P1.Y) < 0.15f, (P1, P2) => P2.Z - P1.Z > -0.04f, (P1, P2) => Math.Abs(P2.Z - P1.Z) > 0.4f, 250, 2500))
{
RaiseGestureDetected("FrontToBack");
return;
}
}
修改这个方法后,编译解决方案以获得新的修改过的DLL,这个修改过的DLL可以替换第一个,现在可以在应用程序中检测到从后到前的手势。
public void On_GestureDetected(string gest)
{
// 如果手势是向右滑动,则转到下一张图片
if (gest == "SwipeToRight")
suivant();
// 如果手势是向左滑动,则转到上一张图片
if (gest == "SwipeToLeft")
precedente();
// 如果手势是向前滑动
if (gest == "BackToFront")
ClickItem();
// 例如:点击显示的项目
}