在Kinect应用程序中,Skeleton,手势期有什么用?

时间:2016-06-27 08:13:49

标签: c# windows kinect kinect-sdk gesture-recognition

我正在编写一个基于Kinect的应用程序。我需要实现一个波浪右手势。我使用C#从Internet找到了一个代码片段,但我对这段代码有些怀疑。你能救我吗?

代码:

public class KinectClass
{
    public void KinectInitialize ()
    {
        m_myKinect.Start();
        m_myKinect.SkeletonStream.TrackingMode = SkeletonTrackingMode.Seated;
        m_myKinect.SkeletonFrameReady += m_myKinect_SkeletonFrameReady;
    }

    void m_myKinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
    {
        using (SkeletonFrame frame = e.OpenSkeletonFrame())
        {
            if (frame != null)
            {
                if (0 == frame.SkeletonArrayLength) return;
                m_skeletons = new Skeleton[frame.SkeletonArrayLength];
                if (m_skeletons == null) return;
                frame.CopySkeletonDataTo(m_skeletons);
            }
        }

        foreach (Skeleton skeleton in m_skeletons)
        {
            if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
            {
                UpdateSkeletonHistory(skeleton);
                value = gestureobject.Detectgesture();
            }
        }
    }
}

此外,还有一个正在检查波函数的Gesture类:

class Gesture
{
    private List<Skeleton> SkeletonHistory;
    private List<Skeleton> localSkeletonHistory;

    public void UpdateSkeletonHistory(Skeleton SkeletonData)
    {
        SkeletonHistory.Add(SkeletonData);

        if (SkeletonHistory.Count > 90)
        {
            SkeletonHistory.RemoveAt(0);
        }

        return ;
    }

    public short Detectgesture()
    {
        short sReturnvalue = -1;
        int gesturePeriod = 2;
        int indexesPerSecond = 30;
        int indexesToCheck = gesturePeriod * indexesPerSecond;
        localSkeletonHistory = new List<Skeleton>(SkeletonHistory);

        if (m_SkeletonHistory.Count > indexesToCheck)
        {
            localSkeletonHistory = new List<Skeleton>(m_SkeletonHistory);

            if( waveright() )
            {
                Console.Writeline("waveright");
            }
        }
    }

    private bool waveright()
    {
        Console.WriteLine("wave right START");
        bool Movedright = false,
        Movedleft = false;

        float refDistance = 0.2F;

        float startPos = localSkeletonHistory[0].Joints[JointType.HandLeft].Position.X;

        for (int i = 0; i < localSkeletonHistory.Count; i++)
        {
            if (!(localSkeletonHistory[i].Joints[JointType.HandLeft].Position.Y <= localSkeletonHistory[i].Joints[JointType.Head].Position.Y))
            {
                break;
            }
            if (localSkeletonHistory[i].Joints[JointType.HandLeft].Position.X >= (startPos + refDistance))
            {
                Movedright = true;
            }
            if (Movedright && Math.Abs(localSkeletonHistory[i].Joints[JointType.HandLeft].Position.X - startPos) <= 0.1 )
            {
                Movedleft = true;
                m_SkeletonHistory.Clear();
                break;
            }
        }

        return Movedleft;
    }
}

我可以理解Kinect功能,但我对手势功能感到困惑。我的问题如下:

  • 他们为什么要创建一个SkeletonHistory?
  • 对gesturePeriod和indicesPerSecond有什么需要?
  • 他们为什么检查(m_SkeletonHistory.Count&gt; indexesToCheck)?
  • 你能解释一下waveright功能吗?

1 个答案:

答案 0 :(得分:2)

你需要记住的是,仅仅因为手的位置相对于身体是正确的。这并不意味着他们正在挥手。

右波是向右的过渡。所以你无法确定当前的位置。这就是为什么你需要使用SkeletonHistory跟踪以前的位置。

因此,该算法的简要概述是:

For the previous positions since the last triggered gesture:
     If each Skeleton's Y position is greater than the last, then the person is waving right

当然,一只手会向右移动很多次,但这并不意味着它是正确的。所以你需要确定一只手必须向右移动多长时间才能成为一个真正的waveRight手势。

refdistance是一种说法,在将手分类为右波之前,手至少需要移动此距离。

在这里,我相信编码器说这个手势需要持续至少2秒。因此,如果我们每秒获得30个骷髅,那么我们需要检查最后60个骷髅:

int indexesToCheck = gesturePeriod * indexesPerSecond;

msdn文档实际上非常适合这些东西:

https://msdn.microsoft.com/en-us/library/jj131025.aspx

我发现这本书非常适合开始使用这些东西:

Programming with the Kinect for Windows Software Development Kit (Developer Reference)