教程:利用Kinect.Toolbox和Coding4Fun进行Kinect编程






4.87/5 (21投票s)
Kinect.Toolbox和Coding4Fun API的使用可以为Kinect编程节省时间,本文将对此进行阐述,并介绍如何修改和使用这些API。
引言
自2011年7月Kinect SDK发布Beta版本以来,对这项新技术感兴趣的程序员、学生和爱好者数量不断增加,能够让Kinect编程变得非常简单的工具和API的开发也随之增加,Kinect编程中最常用的API是Kinect.Toolbox和Coding4Fun。本文将介绍和研究这两个API的使用。

背景
C#、Visual Studio 2010、Kinect设备、下载并安装Kinect SDK:下载Kinect SDK Beta。
第0步:下载并安装API
首先,我们应该下载API及其代码(Kinect.Toolbox和Coding4Fun)。为此,我们访问以下网站下载API:Coding4Fun API和Kinect.Toolbox
附注:请确保您已下载Winform的代码和API。
第1步:开始使用Microsoft Kinect SDK
下载并安装API后,将需要作为引用的DLL文件将包含在下载的zip文件中。
注意:Kinect SDK的DLL位于:C:\Program Files (x86)\Microsoft Research KinectSDK
- 现在,打开Visual Studio并创建一个新的WinForms项目。
- 为我们将在项目中使用到的API添加引用。
- 在Visual Studio中打开Form1.cs并添加这些引用。

为此,在Visual Studio中转到“解决方案资源管理器”,右键单击“引用”,然后单击“添加新引用”。对于每个DLL,浏览到其位置并选择它。
using Microsoft.Research.Kinect.Nui;
using Kinect.Toolbox;
using Coding4Fun.Kinect.WinForm;
第2步:检测手部移动事件
手部是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;
   }
    #region add events
    
    nui.SkeletonFrameReady += 
      new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
    SwG.OnGestureDetected += On_GestureDetected;
    #endregion
}
第3步:初始化Kinect并链接事件与方法
现在,我们转到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;
    }
    #region add events
    nui.SkeletonFrameReady += 
      new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
    SwG.OnGestureDetected += On_GestureDetected;
    #endregion
在此代码的try-catch块中,我们运行Kinect设备。如果设备不正常:断电或USB线未连接到计算机,则会抛出异常。
在第二个块中,我们检测身体。如果Kinect检测到身体,则nui_SkeletonFrameReady方法将响应此事件。此事件有一个参数,即检测到的身体,在Kinect SDK中称为SkeletonFrame。
最后,我们将移动事件链接到将响应该移动的方法。
第4步:响应事件
为了响应我们在上一步中看到的两个事件,我们应该使用链接到这些事件的方法。为此,请将这两个方法添加到Form1类中。
方法1:检测身体的右手(检测第一个骨架的一个关节)。void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
    SkeletonFrame allSkeletons = e.SkeletonFrame;
    //get the first tracked skeleton
    SkeletonData skeleton = (from s in allSkeletons.Skeletons
                             where s.TrackingState == SkeletonTrackingState.Tracked
                             select s).FirstOrDefault();
    //Test if skelton exist and tracked
    if (skeleton != null && skeleton.TrackingState == SkeletonTrackingState.Tracked)
    {
        SwG.Add(skeleton.Joints[JointID.HandRight].Position, nui.SkeletonEngine);
        // scale those Joints to the primary screen width and height
        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 is swip to right go to the next picture
    if (gest == "SwipeToRight")
        suivant();
    //if gest is swip to left go to the previouse picture
    if (gest == "SwipeToLeft")
        precedente(); // e.g :is a method that 
    
}
当Kinect设备检测到跟踪的关节(右手)向左或向右滑动时,将在此方法中触发此Gesture事件,以响应此事件。“SwipeToRight”和“SwipeToLeft”是Kinect.Toolbox API中声明的两个字符串。因此,在我们的方法中,我们测试右手是从左到右还是从右到左移动,并执行一些响应手部移动的操作。
技巧
技巧1
如果我们测试此代码,我们会发现对手部移动的响应太快了,并且应用程序与手部移动之间没有良好的交互性。因此,为了解决此问题,我们像这样修改SkeltonEngine的抖动(jitter)设置。
#region TransformSmooth
//Must set to true and set after call to Initialize
nui.SkeletonEngine.TransformSmooth = true;
//Use to transform and reduce jitter
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中,我们看到只有两种姿势SwipeToRight3和SwipeToLeft。可以通过修改源代码在API中实现其他类型的姿势。在本节中,我们将看到如何添加BackToFront姿势并将其用于我们的代码,例如在屏幕上选择某项内容。
首先,我们转到Kinect.Toolbox源代码,在SwipeGestureDetector.cs类中,我们通过添加以下代码行来修改LookForGesture()方法。
void LookForGesture()
{
    / / From left to right
    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;
    }
    / / from right to left
    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;
    }
    / / From back to front
    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;
    }
    / / from front to back
    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可以替代原始DLL,现在我们可以在应用程序中检测前后手势。
因此,新的On_GestureDetected()方法将如下所示。
public void On_GestureDetected(string gest)
{
          //if gest is swip to right go to the next picture
    if (gest == "SwipeToRight")
        suivant(); // e.g : Go to the next item
         //if gest is swip to left go to the previouse picture
    if (gest == "SwipeToLeft")
        precedente(); // e.g : Go to the previous item
         //if gest is swip to front 
    if (gest == "BackToFront")
        ClickItem(); //e.g : Click to the displayed item
}
我希望现在你们大多数人已经对如何使用这两个强大的API开发Kinect应用程序有了初步想法,并且可以编写交互式应用程序,从而帮助和改善残疾人、文盲等人的生活。我期待您的反馈和评论。

