IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 《卡尔曼滤波理解及python实现》 -> 正文阅读

[Python知识库]《卡尔曼滤波理解及python实现》


卡尔曼滤波的简单理解及应用


Kalman滤波

  • 状态估计器

  • 模型精确和随机干扰信号统计特性已知的线性系统

  • 本质:贝叶斯模型 + 最小均方误差估计

  • 步骤

    • 根据上一次的最优状态估计和最优估计误差去计算这次的先验状态估计和先验误差估计
    • 根据本次先验误差估计和测量噪声,得到卡尔曼增益
    • 根据当前测量值和先验状态估计值,通过卡尔曼增益加权,得到本次的最优估计

推导

五个公式

  • 预测

x ^ k ? = F k x ^ k ? 1 + B k u ? k \hat{x}_k^- = F_k \hat{x}_{k-1} + B_k\vec{u}_k x^k??=Fk?x^k?1?+Bk?u k?

P k ? = F k P k ? 1 F k T + Q k P_k^- = F_k P_{k-1}F_k^T + Q_k Pk??=Fk?Pk?1?FkT?+Qk?

  • 更新

K k = P k ? H k T ( H k P k ? H k T + R k ) ? 1 K_k = P_k^- H_k^T(H_kP_k^-H_k^T + R_k)^{-1} Kk?=Pk??HkT?(Hk?Pk??HkT?+Rk?)?1

x ^ k = x ^ k ? + K k ( z ? k ? H k x ^ k ? ) \hat{x}_k = \hat{x}_k^- + K_k (\vec{z}_k - H_k \hat{x}_k^-) x^k?=x^k??+Kk?(z k??Hk?x^k??)

P k = P k ? ? K k H k P k ? P_k = P_k^- - K_kH_kP_k^- Pk?=Pk???Kk?Hk?Pk??

参数含义
x ^ k ? \hat{x}_k^- x^k??k时刻的先验状态估计值 ,根据k-1时刻的最优估计预测的k时刻的结果
P k ? P_k^- Pk??k时刻的先验估计协方差,预测状态不确定性度量
x ^ k \hat{x}_k x^k?k时刻的后验状态估计值,最优估计
P k P_k Pk?k时刻的后验估计协方差
R k R_k Rk?观测噪声协方差矩阵
H k H_k Hk?观测矩阵
K k K_k Kk?卡尔曼增益
B k B_k Bk?控制矩阵,控制向量如何作用当前矩阵
u ? k \vec{u}_k u k?控制向量
F k F_k Fk?状态转移矩阵,如何从上一状态推测当前状态
z ? k \vec{z}_k z k?k时刻观测值
Q k Q_k Qk?过程噪声协方差矩阵

推导过程

  • 先列出状态预测方程

x k = F k x k ? 1 + B k u k + w k ? 1 x_k = F_kx_{k-1}+B_ku_k + w_{k-1} xk?=Fk?xk?1?+Bk?uk?+wk?1?

  • 利用预测状态的协方差矩阵描述不确定度

P k = c o v ( x k , x k ) = c o v ( F k x k ? 1 ) + c o v ( B k u k ) + c o v ( w k ) = F k P k ? 1 F k T + Q k P_k = cov(x_k, x_k)=cov(F_kx_{k-1}) + cov(B_ku_k) + cov(w_k) \\ =F_kP_{k-1}F_k^T +Q_k Pk?=cov(xk?,xk?)=cov(Fk?xk?1?)+cov(Bk?uk?)+cov(wk?)=Fk?Pk?1?FkT?+Qk?

  • 实际过程中,状态元素有时候无法直接测量,需要观测方程实现状态转移

z k = H ? x k + v k z_k = H *x_k+v_k zk?=H?xk?+vk?

  • 真实值与预测值误差

e k ? = x k ? x k ? e_k^- = x_k - x_k^-\\ ek??=xk??xk??

  • 真实值与预测值误差协方差为

P k ? = E ( e k ? ? e k ? T ) P_k^- = E(e_k^- * e_k^{-T}) Pk??=E(ek???ek?T?)

  • 真实值与估计值误差

e k = x k ? x ^ k = x k ? ( x ^ k ? + K k ( z ? k ? H k x ^ k ? ) ) = ( I ? K k H k ) ( x k ? x k ? ) ? K k v k e_k = x_k - \hat{x}_k = x_k - (\hat{x}_k^- + K_k (\vec{z}_k - H_k \hat{x}_k^-)) \\ =(I-K_kH_k)(x_k-x_k^-) - K_kv_k ek?=xk??x^k?=xk??(x^k??+Kk?(z k??Hk?x^k??))=(I?Kk?Hk?)(xk??xk??)?Kk?vk?

  • 真实值与估计值误差的协方差为

P k = E ( e k ? e k T ) = E ( [ ( I ? K k H k ) ( x k ? x k ? ) ? K k v k ] [ ( I ? K k H k T ) ( x k ? x k ? ) ? K k v k ] T ) = ( I ? K k H k ) P k ? ( I ? K k H k ) T + K k R K T = P k ? ? K k H k P k ? ? P k ? H k T + K k ( H k P k ? H T + R ) K k T P_k = E(e_k*e_k^T) \\ = E([(I-K_kH_k)(x_k-x_k^-) - K_kv_k][(I-K_kH_k^T)(x_k-x_k^-) - K_kv_k]^T) \\ = (I-K_kH_k)P_k^-(I-K_kH_k)^T + K_kRK^T \\ = P_k^- - K_kH_kP_k^- - P_k^-H_k^T + K_k(H_kP_k^-H^T + R)K_k^T Pk?=E(ek??ekT?)=E([(I?Kk?Hk?)(xk??xk??)?Kk?vk?][(I?Kk?HkT?)(xk??xk??)?Kk?vk?]T)=(I?Kk?Hk?)Pk??(I?Kk?Hk?)T+Kk?RKT=Pk???Kk?Hk?Pk???Pk??HkT?+Kk?(Hk?Pk??HT+R)KkT?

  • 卡尔曼滤波的估计原则就是使最优状态估计的协方差 P k P_k Pk?最小
    在这里插入图片描述

  • P k P_k Pk?对卡尔曼增益矩阵 K K K求偏导

? P k ? K k = ? 2 ( P k ? H T ) + 2 K k ( H k P k ? H T + R ) = 0 \frac{?P_k}{?K_k} = -2(P_k^-H^T) + 2K_k(H_kP_k^-H^T + R) = 0 ?Kk??Pk??=?2(Pk??HT)+2Kk?(Hk?Pk??HT+R)=0

  • 求得卡尔曼增益 K k K_k Kk?

K k = P k ? H k T ( H k P k ? H T + R ) ? 1 K_k = P_k^-H_k^T(H_kP_k^-H^T + R)^{-1} Kk?=Pk??HkT?(Hk?Pk??HT+R)?1

  • K k K_k Kk?代入 P k P_k Pk? ,得到

P k = P k ? ? K k H k P k ? P_k = P_k^- - K_kH_kP_k^- Pk?=Pk???Kk?Hk?Pk??

实现

  • 卡尔曼滤波的预测、更新车辆轨迹

  • 根据已知轨迹,预测后面多步的轨迹

  • 分别使用cv2.KalmanFilter和按照上述公式推导实现

  • 数据使用视频帧号和目标对应中心点的x和y坐标

cv2.KalmanFilter

  • cv2.KalmanFilter函数介绍如下
cv2.KalmanFilter(dynam_params, measure_param, control_params) # 创建kalman滤波器 
    dynam_params:状态空间的维数; 4
    measure_param:测量值的维数;  2
    control_params:控制向量的维数,默认为0。由于这里该模型中并没有控制变量,因此也为0。
kalman.measurementMatrix 观测矩阵 H
kalman.transitionMatrix  状态转移矩阵 F
kalman.processNoiseCov 处理噪声协方差矩阵  Q
kalman.measurementNoiseCov 观测噪声协方差矩阵 R
kalman.controlMatrix 控制矩阵 B
kalman.statePost   校正状态 
kalman.statePre   预测状态
kalman.errorCovPost 后验方差协方差阵 P = (I-KH)P'(k)
kalman.errorCovPre 先验方差
kalman.gain 卡尔曼增益矩阵
  • 实现如下
# 状态量  x, y, Vx, Vy
kalman = cv2.KalmanFilter(4, 2)
kalman.measurementMatrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0]], np.float32) # 设置测量矩阵 H
kalman.processNoiseCov = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]], np.float32) # 设置过程噪声协方差矩阵 Q
kalman.measurementNoiseCov = np.matrix([[1, 0], [0, 1]])    # 观测噪声方差

num = len(info['frame'])
for k in range(1, num):
    delt = (info['frame'][k] - info['frame'][k-1])
    kalman.transitionMatrix = np.array([[1, 0, delt, 0], [0, 1, 0, delt], [0, 0, 1, 0], [0, 0, 0, 1]], np.float32) # 设置转移矩阵 F

    x, y = info['x'][k], info['y'][k]
    current_measurement = np.array([[np.float32(x)], [np.float32(y)]])
    kalman.correct(current_measurement)  # 用当前测量来校正卡尔曼滤波器
    current_prediction = kalman.predict()
    plt.scatter(info['frame'][k], current_prediction[0][0], color='g')
    plt.scatter(info['frame'][k], current_prediction[1][0], color='y')
plt.show()

自己实现

    x_hat = np.matrix([[info['x'][0]], [info['y'][0]], [0], [0]])
    P = np.matrix(np.diag([1, 1, 1, 1]))
    Q = np.matrix(np.diag([1, 1, 1, 1]))
    # Q = np.matrix([[1/3, 0, 1/2, 0], [0, 1/3, 0, 1/2], [1/2, 0, 1, 0], [0, 1/2, 0, 1]], np.float32)
    H = np.matrix([[1, 0, 0, 0], [0, 1, 0, 0]])
    R = np.matrix([[1, 0], [0, 1]])
    figure = plt.figure()
    plt.scatter(info['frame'], info['x'], color='r', label='x-观测值')
    plt.scatter(info['frame'], info['y'], color='g', label='y-观测值')

    for k in range(1, num):
        delt_t = (info['frame'][k] - info['frame'][k - 1])
        F = np.matrix([[1, 0, delt_t, 0], [0, 1, 0, delt_t], [0, 0, 1, 0], [0, 0, 0, 1]])
        # 预测
        x_hat_minus = F * x_hat
        P_minus = F * P * F.T + Q

        # 更新
        K = P_minus * H.T * np.linalg.inv(H * P_minus * H.T + R)
        x_hat = x_hat_minus + K * (np.matrix([[info['x'][k]], [info['y'][k]]]) - H * x_hat_minus)
        P = P_minus - K * H * P_minus

        plt.scatter(info['frame'][k], x_hat_minus.A[0][0], color='olive', label='x-预测值', marker='s')
        plt.scatter(info['frame'][k], x_hat_minus.A[1][0], color='pink', label='y-预测值', marker='*')
    plt.show()

轨迹预测

  • 通过修改delt_t,实现之后轨迹的预测
  • 因为没有观测值的加权,导致预测值会有部分误差
# 往后预测10步
for i in range(1, 11):
# 多步预测
delt_t = i
F = np.matrix([[1, 0, delt_t, 0], [0, 1, 0, delt_t], [0, 0, 1, 0], [0, 0, 0, 1]])
x_hat_minus = F * x_hat
  • 预测效果如下

参考链接

1 cv::KalmanFilter Class Reference

2 卡尔曼滤波五个公式推导过程

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-30 12:01:04  更:2021-08-30 12:01:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 12:28:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码