渐变光标移动算法 - Kinect SDK

时间:2011-09-07 23:04:53

标签: c# wpf algorithm kinect

我正在构建Kinect SDK WPF应用程序并使用Kinect移动“光标”/手形对象。

我遇到的问题是,由于Kinect的精确度,每秒30帧,光标实际上会有点跳跃(即握住手时,物体在5px空间内移动)。

我打算编写一种算法,它不会简单地将我的“光标”冲刺的X / Y移动到屏幕上的正确位置,但表现得更像是“将手移向这个X / Y坐标“这是一个更平稳的运动。

有人能指出一个别人写的好的,所以我可以避免重新发明轮子。

我知道这可能很常见,但由于我更像是一个业务开发人员,我不确定这个功能的名称如果是一个n00b问题,请提前道歉。

3 个答案:

答案 0 :(得分:4)

将您的输入值(跳跃位置)视为具有低频和高频部分的信号。低频表示粗略位置/运动,而高频部分表示较小距离内的快速跳跃。

所以你需要或寻找的是低通滤波器。如果您设法使用正确的参数设置它,那么过滤掉高频部分并留下粗糙(但与Kinect可以获得的准确度)位置。此参数是滤波器的交叉频率。你必须玩一下,你会看到。

时间离散值的实现示例来自here(最初来自wikipedia):

static final float ALPHA = 0.15f;

protected float[] lowPass( float[] input, float[] output ) {
    if ( output == null ) return input;

    for ( int i=0; i<input.length; i++ ) {
        output[i] = output[i] + ALPHA * (input[i] - output[i]);
    }
    return output;
}

您可以将位置向量的X和Y分量的最后一个值放入此函数中以使其平滑(X为input[0],Y为input[1]output[0] output[1]是上一个函数调用的结果。)

就像我已经说过的那样,你必须找到平滑因子ALPHA (0≤ALPHA≤1)的良好平衡

  • 太大,信号不会得到足够的平滑,效果不够
  • 太小,信号会“过多”平滑,光标会落后于用户移动,惯性太大

(如果查看公式newout = out + alpha * (in - out),您会看到alpha值为0,您只需再次使用旧的out值,因此值永远不会改变;而值为值1你有newout = out + in - out这意味着你不要平滑任何东西,但总是采取最新的值)

答案 1 :(得分:4)

当我使用Kinect时,我只是使用了一些简单的数学运算(我认为称为线性回归)来移动到光标当前位置与其目标位置之间某个距离的点。获取光标的位置,获取用户手所在的位置(转换为屏幕坐标),然后将光标移动到这些位置之间的某个点。

float currentX = ..., currentY = ..., targetX = ..., targetY = ...; 
float diffX = targetX - currentX;
float diffY = targetY - currentY;
float delta = 0.5f; // 0 = no movement, 1 = move directly to target point. 

currentX = currentX + delta * diffX;
currentY = currentY + delta * diffY;

根据三角洲的不同,你仍会受到抖动的影响,但它会更加平滑,通常在一个较小的区域内。

在相关的说明中,您是否看过Kinect的骨架平滑参数?实际上,您可以让SDK处理一些过滤。

答案 2 :(得分:0)

解决这个问题的一个非常简单的想法是将光标显示在某个位置上,该位置是过去一些位置的平均值。例如,假设您跟踪手的最后五个位置,然后将光标显示在该位置。然后,如果用户的手相对静止,则帧与帧之间的急动应该相当低,因为最后五帧将使手处于大致相同的位置并且噪声应该抵消。如果用户然后在屏幕上移动光标,光标将从其旧位置移动到新位置时生成动画,因为当您考虑手的最后五个位置时,平均位置将在其新旧之间缓慢插值位置。

这种方法非常容易调整。您可以转换数据点,以便旧点的权重大于或小于新点,并可以调整您保留的历史记录的长度。

希望这有帮助!