手势识别算法: 数据滤波算法、数据分算法——KNN

目录

    • 数据滤波算法设计介绍
    • 数据分类算法介绍
        • 卡尔曼滤波算法的原理 和简单实现

数据滤波算法设计介绍

数据滤波算法是去除噪音干扰的有效方法,此次采用使用广泛的滤波算法——卡尔曼滤波算法。 这样计算量小,利于计算机实现等特点。将极板上采集的数据进行实时的处理,将数据中的噪音清除,把误差降到最小。

数据分类算法介绍

KNN是以一种数据分类算法,在学习模式下,将多次手势进行采样滤波,之后进入判定模式,系统会实时采样,当数据稳定后,得到其特征向量,计算其特征向量与样本数据之间的欧式距离,找到相距最短的k个样本,判断其类型,即可手势识别。
手势识别算法: 数据滤波算法、数据分算法——KNN_第1张图片

卡尔曼滤波算法的原理 和简单实现

简介:

卡尔曼滤波(Kalman filtering)一种利用线性系统状态方程,通过系统输入输出观测数据,对系统状态进行最优估计的算法。由于观测数据中包括系统中的噪声和干扰的影响,所以最优估计也可看作是滤波过程。

- 被观测的系统

首先我们需要用方程来描述被观测的系统,因为后面滤波器的方程要用到这里的一些参数。卡尔曼滤波器适用于线性系统,设该系统的状态方程和观测方程为:

x(k) = A · x(k-1) + B · u(k) + w(k)
z(k) = H · x(k) + y(k)

x(k) —— k时刻系统的状态
u(k) —— 控制量
w(k) —— 符合高斯分布的过程噪声,其协方差在下文中为Q(我理解的噪声 就是误差的意思)
z(k) —— k时刻系统的观测值
y(k) —— 符合高斯分布的测量噪声,其协方差在下文中为R
A、B、H —— 系统参数,多输入多输出时为矩阵,单输入单输出时就是几个常数

注意在后面滤波器的方程中我们将不会再直接面对两个噪声w(k)和y(k),而是用到他们的协方差Q和R。至此,A、B、H、Q、R这几个参数都由被观测的系统本身和测量过程中的噪声确定了。

  • 滤波器

工程中用到的卡尔曼滤波是一个迭代的过程,每得到一个新的观测值迭代一次,来回来去地更新两个东西:“系统状态”(x)和“误差协方差”§。由于每次迭代只用到上一次迭代的结果和新的测量值,这样滤波对计算资源的占用是很小的。

每一次迭代,两个步骤:预测和修正。预测是根据前一时刻迭代的结果,即x(k-1|k-1)和P(k-1|k-1),来预测这一时刻的系统状态和误差协方差,得到x(k|k-1)和P(k|k-1):

x(k|k-1) = A · x(k-1|k-1) + B · u(k)
P(k|k-1) = A · P(k-1|k-1) · AT + Q

(这里用到的A、B、H、Q、R就是从前面的状态/观测方程中拿来的)
然后计算卡尔曼增益K(k)(不知道咋来的),和这一次的实际测量结果z(k)一起,用于修正系统状态x(k|k-1)及误差协方差P(k|k-1),得到最新的x(k|k)和P(k|k):

K(k) = P(k|k-1) · HT · (H · P(k|k-1) · HT + R)-1
x(k|k) = x(k|k-1) + K(k) · (z(k) - H · x(k|k-1))
P(k|k) = (I - K(k) · H) · P(k|k-1)

x(k|k)就是我们要的滤波后的值,它和P(k|k)将会作为x(k-1|k-1)和P(k-1|k-1)用在下一时刻的迭代里

- 定义一个简单场景

先看状态方程和观测方程。假设我们是在测温度、加速度,此时控制量是没有的,即:

B · u(k) ≡ 0

另外,参数A和H也简单地取1。现在滤波器的预测方程简化为:

① x(k|k-1) = x(k-1|k-1)
② P(k|k-1) = P(k-1|k-1) + Q

同时修正方程变成:

③ K(k) = P(k|k-1) / (P(k|k-1) + R)
④ x(k|k) = x(k|k-1) + K(k) · (z(k) - x(k|k-1))
⑤ P(k|k) = (1 - K(k)) · P(k|k-1)

①对②、③无影响,于是④可以写成:

x(k|k) = x(k-1|k-1) + K(k) · (z(k) - x(k-1|k-1))

在程序中,该式写起来更简单:

x = x + K * (新观测值 - x);
观察②,对这一时刻的预测值不就是上一时刻的修正值+Q嘛,不妨把它合并到上一次迭代中,即⑤改写成:

P(k+1|k) = (1 - K(k)) · P(k|k-1) + Q

这一时刻的P(k+1|k),会作为下一时刻的P(k|k-1),刚好是③需要的。于是整个滤波过程只用这三个式子来迭代即可:

K(k) = P(k|k-1) / (P(k|k-1) + R)
x(k|k) = x(k-1|k-1) + K(k) · (z(k) - x(k-1|k-1))
P(k+1|k) = (1 - K(k)) · P(k|k-1) + Q

经过前面的推导,我们发现在程序中只需要不断重复这一小段即可实现卡尔曼滤波:

while(新观测值)
{
    K = P / (P + R);
    x = x + K * (新观测值 - x);
    P = (1 - K) · P + Q;
}

我们发现这一堆字母中,x和P只需要赋初值,每次迭代会产生新值;K用不着赋初值;Q和R赋值以后在之后的迭代中也可以改
x和P的初值是可以随便设的,强大的卡尔曼滤波器马上就能抹除不合理之处。但需注意,P的初值不能为0,否则滤波器会认为已经没有误差了

剩下的也就是Q和R了。他俩的物理意义是噪声的协方差,他们的值是需要我们试出来的
因此应该根据具体的使用场景收集到的数据来决定Q和R的取值
全程最难的地方莫过于确定协方差R和Q的值。R的值我们或许能较好的确定,因为一般情况下我们能较清楚的知道仪器的测量误差,所以这是需要自己去猜测计算的,而Q超出了我的能力范围,此处也就不去讲怎么调了

你可能感兴趣的:(手势识别,算法,机器学习,c语言)