python中的kalman 2d过滤器

时间:2012-12-16 13:58:37

标签: python 2d kalman-filter

我的输入是在跟踪器软件的屏幕上移动的点的2d(x,y)时间序列。我想用卡尔曼滤波器消除一些噪音。有人能指出我为卡尔曼2d滤镜的python代码吗? 在scipy cookbook中,我发现只有一个例子: http://www.scipy.org/Cookbook/KalmanFiltering 我看到OpenCV中有卡尔曼滤波器的实现,但找不到代码示例。 谢谢!

2 个答案:

答案 0 :(得分:55)

以下是基于equations given on wikipedia的卡尔曼滤波器的实现。请注意,我对卡尔曼滤波器的理解非常简陋,因此最有可能改进此代码。 (例如,它遇到了here所讨论的数值不稳定性问题。据我所知,这只影响Q时的运动噪声非常小的数值稳定性。在现实生活中,噪声通常不小,所以幸运(至少对于我的实施)在实践中数值不稳定性不会出现。)

在下面的示例中,kalman_xy假设状态向量是4元组:位置为2个数字,速度为2个数字。 已为此状态向量专门定义了FH矩阵:如果x是4元组状态,则

new_x = F * x
position = H * x

然后调用kalman,这是广义卡尔曼滤波器。如果你想定义一个不同的状态向量 - 也许是一个代表位置,速度和加速度的6元组,它仍然是有用的。您只需通过提供适当的FH来确定运动方程。

import numpy as np
import matplotlib.pyplot as plt

def kalman_xy(x, P, measurement, R,
              motion = np.matrix('0. 0. 0. 0.').T,
              Q = np.matrix(np.eye(4))):
    """
    Parameters:    
    x: initial state 4-tuple of location and velocity: (x0, x1, x0_dot, x1_dot)
    P: initial uncertainty convariance matrix
    measurement: observed position
    R: measurement noise 
    motion: external motion added to state vector x
    Q: motion noise (same shape as P)
    """
    return kalman(x, P, measurement, R, motion, Q,
                  F = np.matrix('''
                      1. 0. 1. 0.;
                      0. 1. 0. 1.;
                      0. 0. 1. 0.;
                      0. 0. 0. 1.
                      '''),
                  H = np.matrix('''
                      1. 0. 0. 0.;
                      0. 1. 0. 0.'''))

def kalman(x, P, measurement, R, motion, Q, F, H):
    '''
    Parameters:
    x: initial state
    P: initial uncertainty convariance matrix
    measurement: observed position (same shape as H*x)
    R: measurement noise (same shape as H)
    motion: external motion added to state vector x
    Q: motion noise (same shape as P)
    F: next state function: x_prime = F*x
    H: measurement function: position = H*x

    Return: the updated and predicted new values for (x, P)

    See also http://en.wikipedia.org/wiki/Kalman_filter

    This version of kalman can be applied to many different situations by
    appropriately defining F and H 
    '''
    # UPDATE x, P based on measurement m    
    # distance between measured and current position-belief
    y = np.matrix(measurement).T - H * x
    S = H * P * H.T + R  # residual convariance
    K = P * H.T * S.I    # Kalman gain
    x = x + K*y
    I = np.matrix(np.eye(F.shape[0])) # identity matrix
    P = (I - K*H)*P

    # PREDICT x, P based on motion
    x = F*x + motion
    P = F*P*F.T + Q

    return x, P

def demo_kalman_xy():
    x = np.matrix('0. 0. 0. 0.').T 
    P = np.matrix(np.eye(4))*1000 # initial uncertainty

    N = 20
    true_x = np.linspace(0.0, 10.0, N)
    true_y = true_x**2
    observed_x = true_x + 0.05*np.random.random(N)*true_x
    observed_y = true_y + 0.05*np.random.random(N)*true_y
    plt.plot(observed_x, observed_y, 'ro')
    result = []
    R = 0.01**2
    for meas in zip(observed_x, observed_y):
        x, P = kalman_xy(x, P, meas, R)
        result.append((x[:2]).tolist())
    kalman_x, kalman_y = zip(*result)
    plt.plot(kalman_x, kalman_y, 'g-')
    plt.show()

demo_kalman_xy()

enter image description here

红点表示噪声位置测量值,绿线表示卡尔曼预测位置。

答案 1 :(得分:0)

对于我的一个项目,我需要为时间序列建模创建间隔,并且为了使过程更高效,我创建了tsmoothie:用于时间序列平滑的python库和异常值向量化检测。

它提供了不同的平滑算法以及计算间隔的可能性。

对于KalmanSmoother,您可以对曲线进行平滑处理,以将不同的成分组合在一起:水平,趋势,季节性,长期季节性

import numpy as np
import matplotlib.pyplot as plt
from tsmoothie.smoother import *
from tsmoothie.utils_func import sim_randomwalk

# generate 3 randomwalks timeseries of lenght 100
np.random.seed(123)
data = sim_randomwalk(n_series=3, timesteps=100, 
                      process_noise=10, measure_noise=30)

# operate smoothing
smoother = KalmanSmoother(component='level_trend', 
                          component_noise={'level':0.1, 'trend':0.1})
smoother.smooth(data)

# generate intervals
low, up = smoother.get_intervals('kalman_interval', confidence=0.05)

# plot the first smoothed timeseries with intervals
plt.figure(figsize=(11,6))
plt.plot(smoother.smooth_data[0], linewidth=3, color='blue')
plt.plot(smoother.data[0], '.k')
plt.fill_between(range(len(smoother.data[0])), low[0], up[0], alpha=0.3)

enter image description here

我还指出tsmoothie可以向量化方式对多个时间序列进行平滑处理