卡尔曼滤波介绍

卡尔曼滤波介绍

    • 📖 **卡尔曼滤波原理简介**
      • 🔑 **核心思想**
      • 📦 **卡尔曼滤波的组成**
    • 🔍 **代码分析(`kalman_filter.py`)**
      • 🏗️ 1. 状态空间定义
      • 🔄 2. 初始化模型矩阵
      • 🚀 3. 核心方法分析
        • 🧩 **预测**
        • 🧩 **更新**
        • 📏 **门控距离(gating distance)**
    • 🧑‍💻 **示例代码:模拟目标运动**
    • ✅ **小结**

📖 卡尔曼滤波原理简介

卡尔曼滤波(Kalman Filter, KF)是一种线性最优估计算法,用于通过一系列带噪声的观测值估计动态系统的状态。它假设系统模型和观测模型都是线性高斯的。

🔑 核心思想

  1. 预测 (Prediction)
    根据系统的动态模型预测下一个时刻的状态和协方差。

    x^k∣k−1=Fx^k−1∣k−1+Buk\hat{x}_{k|k-1} = F \hat{x}_{k-1|k-1} + Bu_k x^kk1=Fx^k1∣k1+Buk

    Pk∣k−1=FPk−1∣k−1FT+QP_{k|k-1} = F P_{k-1|k-1} F^T + Q Pkk1=FPk1∣k1FT+Q

    • FFF:状态转移矩阵
    • BBB:控制输入矩阵
    • QQQ:过程噪声协方差矩阵
    • PPP:状态协方差矩阵
  2. 更新 (Update)
    利用当前观测值修正预测结果。

    卡尔曼增益

    Kk=Pk∣k−1HT(HPk∣k−1HT+R)−1K_k = P_{k|k-1} H^T (H P_{k|k-1} H^T + R)^{-1} Kk=Pkk1HT(HPkk1HT+R)1

    更新状态

    x^k∣k=x^k∣k−1+Kk(zk−Hx^k∣k−1)\hat{x}_{k|k} = \hat{x}_{k|k-1} + K_k(z_k - H \hat{x}_{k|k-1}) x^kk=x^kk1+Kk(zkHx^kk1)

    更新协方差

    Pk∣k=(I−KkH)Pk∣k−1P_{k|k} = (I - K_k H) P_{k|k-1} Pkk=(IKkH)Pkk1

    • HHH:观测矩阵
    • RRR:观测噪声协方差矩阵
    • zkz_kzk:观测向量

📦 卡尔曼滤波的组成

模块功能描述
状态预测根据动态模型预测当前状态
观测预测将状态预测结果投影到观测空间
计算卡尔曼增益结合预测和观测权重,平衡两者的置信度
状态更新利用观测值修正预测
协方差更新更新估计的不确定性

🔍 代码分析(kalman_filter.py

这个代码是一个简化版的卡尔曼滤波实现,用于目标跟踪(tracking bounding boxes in image space)。
代码参考实现:Yolov5-deepsort-inference/deep_sort/deep_sort/sort/kalman_filter.py

🏗️ 1. 状态空间定义

# 状态空间 (x, y, a, h, vx, vy, va, vh)
# x, y : 边框中心
# a    : 宽高比
# h    : 高度
# vx, vy, va, vh : 对应的速度
# 8维状态向量
x = [x, y, a, h, vx, vy, va, vh] 

8维状态向量,前4维是位置+形状,后4维是速度。


🔄 2. 初始化模型矩阵

def __init__(self):# 运动矩阵Fndim, dt = 4, 1.self._motion_mat = np.eye(8)for i in range(4):self._motion_mat[i, 4 + i] = dt# 观测矩阵Hself._update_mat = np.eye(ndim, 2 * ndim)self._std_weight_position = 1. / 20self._std_weight_velocity = 1. / 160# 恒定速度模型(dt=1)# _motion_mat = [#     [1,0,0,0,1,0,0,0],  # x = x + vx#     [0,1,0,0,0,1,0,0],  # y = y + vy#     [0,0,1,0,0,0,1,0],  # a = a + va#     [0,0,0,1,0,0,0,1],  # h = h + vh#     [0,0,0,0,1,0,0,0],  # vx不变#     ...                  # 其余速度项同理# ]# _update_mat = [#     [1,0,0,0,0,0,0,0], #     [0,1,0,0,0,0,0,0],  #     [0,0,1,0,0,0,0,0], #     [0,0,0,1,0,0,0,0],  # ]def initiate(self, measurement):mean_pos = measurement  # [x, y, a, h]mean_vel = np.zeros_like(mean_pos)  # 速度初始化为0mean = np.r_[mean_pos, mean_vel]  # 8维状态向量# 协方差初始化(与目标高度h相关)std = [2 * self._std_weight_position * h,2 * self._std_weight_position * h,1e-2,  # 宽高比噪声较小2 * self._std_weight_position * h,10 * self._std_weight_velocity * h,10 * self._std_weight_velocity * h,1e-5,  # 宽高比速度噪声极小10 * self._std_weight_velocity * h]covariance = np.diag(np.square(std))  # 对角协方差矩阵 Preturn mean, covariance
  • 运动矩阵 FFF:假设目标匀速移动。
  • 观测矩阵 HHH:只观测位置和形状 (x, y, a, h),它固定不变是因为观测模型假设始终相同。如果观测维度、传感器模型或观测函数发生改变,就需要让HHH随时间更新。
  • 位置噪声权重(1/20) > 速度噪声权重(1/160)。
  • 高度h作为尺度因子:大目标位置更确定,小目标位置更不确定。
  • 宽高比a及其速度的噪声极小(1e-2, 1e-5),因目标比例通常稳定。

🚀 3. 核心方法分析

🧩 预测
# def predict(self, mean, covariance):
#     mean = F * mean
#     covariance = F * covariance * F^T + Qdef predict(self, mean, covariance):# 过程噪声(依赖目标高度)std_pos = [self._std_weight_position * h, ...]std_vel = [self._std_weight_velocity * h, ...]motion_cov = np.diag(np.square(np.r_[std_pos, std_vel]))# 状态预测  x_k = F * x_{k-1}mean = np.dot(self._motion_mat, mean) # 协方差预测   P_k = F * P_{k-1} * F^T + Qcovariance = np.linalg.multi_dot((self._motion_mat, covariance, self._motion_mat.T)) + motion_covreturn mean, covariance
  • 预测当前状态
  • 加入过程噪声 motion_cov

🧩 更新
# 投影(观测空间预测), 计算观测预测及其不确定性
# def project(self, mean, covariance):
#     mean = H * mean
#     covariance = H * covariance * H^T + R# def update(self, mean, covariance, measurement):
#     projected_mean, projected_cov = self.project(mean, covariance)
#     kalman_gain = covariance * H^T * (projected_cov)^-1
#     innovation = measurement - projected_mean
#     new_mean = mean + kalman_gain * innovation
#     new_covariance = covariance - kalman_gain * projected_cov * kalman_gain^Tdef project(self, mean, covariance):# 观测噪声(仅位置相关)std = [self._std_weight_position * mean[3],self._std_weight_position * mean[3],1e-1,self._std_weight_position * mean[3]]innovation_cov = np.diag(np.square(std))  # 观测噪声R# 投影到观测空间:z = H * xmean = np.dot(self._update_mat, mean)  # 观测协方差:H * P * H^T + Rcovariance = np.linalg.multi_dot((self._update_mat, covariance, self._update_mat.T)) + innovation_covreturn mean, covariance + innovation_covdef update(self, mean, covariance, measurement):# 1. 预测观测空间分布projected_mean, projected_cov = self.project(mean, covariance)# 2. 计算卡尔曼增益(Cholesky分解加速)chol_factor = scipy.linalg.cho_factor(projected_cov, lower=True, check_finite=False)kalman_gain = scipy.linalg.cho_solve(chol_factor, np.dot(covariance, self._update_mat.T).T).T# 3. 融合观测innovation = measurement - projected_mean  # 新息new_mean = mean + np.dot(innovation, kalman_gain.T)# 4. 更新协方差new_covariance = covariance - np.linalg.multi_dot((kalman_gain, projected_cov, kalman_gain.T))
  • 根据观测修正预测。
  • scipy.linalg.cho_factor 是 SciPy 中用于计算矩阵的 Cholesky 分解的函数,专门针对对称(或 Hermitian)正定矩阵。它的核心作用是将矩阵分解为下三角矩阵 L 和其共轭转置 LTL^TLT (或 LHL^HLH )的乘积形式 A=LLTA = LL^TA=LLT,从而为后续的线性方程组求解提供高效支持。
  • scipy.linalg.cho_solve 是 SciPy 中用于高效求解基于 Cholesky 分解的线性方程组的函数。它专门用于处理对称正定(或 Hermitian 正定)矩阵的线性方程组 Ax=bAx = bAx=b ,通过结合 cho_factor 的分解结果,显著提升计算效率。

📏 门控距离(gating distance)
  • 马氏距离 (Mahalanobis distance) 测量预测和观测的差异,用于在跟踪多目标时判断某观测是否匹配预测。
"""
Table for the 0.95 quantile of the chi-square distribution with N degrees of
freedom (contains values for N=1, ..., 9). Taken from MATLAB/Octave's chi2inv
function and used as Mahalanobis gating threshold.
"""
chi2inv95 = {1: 3.8415,2: 5.9915,3: 7.8147,4: 9.4877,5: 11.070,6: 12.592,7: 14.067,8: 15.507,9: 16.919}def gating_distance(self, mean, covariance, measurements, only_position=False):# 投影到观测空间mean, cov = self.project(mean, covariance)if only_position:  # 仅使用(x,y)mean, cov = mean[:2], cov[:2, :2]measurements = measurements[:, :2]# 计算马氏距离(高效三角分解)cholesky_factor = np.linalg.cholesky(cov)d = measurements - meanz = scipy.linalg.solve_triangular(cholesky_factor, d.T, lower=True)return np.sum(z * z, axis=0)  # 马氏距离平方
  • 计算状态预测与观测的马氏距离d2=(z−Hx^)TS−1(z−Hx^)d^2 = (z - H\hat{x})^T S^{-1} (z - H\hat{x})d2=(zHx^)TS1(zHx^)

  • 通过chi2inv95表(卡方分布95%置信区间)设定阈值,用于数据关联

  • np.linalg.choleskyscipy.linalg.solve_triangular 在求解线性方程组时,需显式调用两次 solve_triangular
    补充代码对比:

    # =======================cholesky + solve_triangular=======================
    import numpy as np
    from scipy.linalg import solve_triangularA = np.array([[4, 12, -16], [12, 37, -43], [-16, -43, 98]])  # 对称正定矩阵
    b = np.array([10, 8, 3])# 分解阶段
    L = np.linalg.cholesky(A)  # 返回下三角矩阵 L# 求解阶段
    y = solve_triangular(L, b, lower=True)   # 解 Ly = b(前向替换)
    x = solve_triangular(L.T, y, lower=False)  # 解 L^T x = y(后向替换)# =======================cho_factor + cho_solve=======================
    from scipy.linalg import cho_factor, cho_solvec, low = cho_factor(A)  # 分解并返回压缩格式的因子矩阵
    x = cho_solve((c, low), b)  # 直接求解 Ax = b
    

🧑‍💻 示例代码:模拟目标运动

下面的代码用你的 KalmanFilter 进行一个简单演示:

import numpy as np
import matplotlib.pyplot as plt
from kalman_filter import KalmanFilterkf = KalmanFilter()
true_positions = []
estimated_positions = []# 模拟真实轨迹 (匀速直线)
true_state = np.array([0, 0, 1, 100, 1, 1, 0, 0])
measurements = []
for i in range(50):true_state[:4] += true_state[4:]  # 更新真实位置true_positions.append(true_state[:2].copy())# 添加观测噪声measurement = true_state[:4] + np.random.randn(4) * 5measurements.append(measurement)# 初始化
mean, covariance = kf.initiate(measurements[0])# 滤波
for z in measurements:mean, covariance = kf.predict(mean, covariance)mean, covariance = kf.update(mean, covariance, z)estimated_positions.append(mean[:2].copy())# 绘图
true_positions = np.array(true_positions)
estimated_positions = np.array(estimated_positions)
measurements = np.array(measurements)plt.plot(true_positions[:, 0], true_positions[:, 1], 'g-', label="True Path")
plt.plot(measurements[:, 0], measurements[:, 1], 'rx', label="Measurements")
plt.plot(estimated_positions[:, 0], estimated_positions[:, 1], 'b-', label="Kalman Filter")
plt.legend()
plt.title("Kalman Filter Tracking Example")
plt.show()

小结

这份代码实现了标准卡尔曼滤波,适配于目标跟踪任务:

  • 预测:估计下一个位置
  • 更新:用新观测修正预测
  • 门控距离:多目标关联时使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/87775.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/87775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

递归与循环

文章目录递归TestRecursiveListRemoveNodeTestRecursiveListRemoveNode2循环TestWhileLoopListRemoveNodeTestWhileLoopListRemoveNode2递归 关键理解这几点: 1、求解基本问题 2、将原问题拆分为小问题,直至基本问题(难点) 3、借…

3D魔方游戏

# 3D魔方游戏 这是一个基于Three.js的3D魔方游戏,支持2到6阶魔方的模拟操作。 ## 功能特点 - 支持2到6阶魔方 - 真实的3D渲染效果 - 鼠标操作控制 - 随机打乱功能 - 提示功能 - 重置功能 ### 安装依赖 bash npm install ### 启动游戏 bash npm start 然…

下载安装 com0com

下载 在 sourceforge 网站下载安装器:下载链接 安装完成后可以在设备管理器中看到默认创建的一对虚拟串口 使用串口调试助手收发 使用串口调试助手分别打开。如下图所示,在端口选择的下拉列表中可以看到刚才在设备管理器中看到的 COM3 和 COM5 分…

C++ 应用软件开发从入门到实战详解

目录 1、引言 2、IDE 开发环境介绍 2.1、Visual Studio 2.2、Qt Creator 3、 C语言特性 3.1、熟悉泛型编程 3.2、了解C/C异常处理 3.3、熟练使用STL容器 3.4、熟悉C11新特性 4、Windows 平台的编程技术与调试技能 4.1、需要掌握的若干编程技术和基础知识 4.2、需…

Python爬虫实战:研究slug相关技术

1. 引言 1.1 研究背景与意义 随着互联网技术的快速发展,网络上的信息量呈爆炸式增长。如何从海量的非结构化数据中提取有价值的信息,成为当前数据科学领域的重要研究方向。网络爬虫作为一种自动化数据采集工具,可以高效地获取网页内容,为数据分析提供丰富的数据来源。 Sl…

人工智能-基础篇-18-什么是RAG(检索增强生成:知识库+向量化技术+大语言模型LLM整合的技术框架)

RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合外部知识检索与大语言模型(LLM)生成能力的技术框架,旨在提升生成式AI在问答、内容创作等任务中的准确性、实时性和领域适应性。 1、核心概念 …

CppCon 2018 学习:What do you mean “thread-safe“

什么是“线程安全”? “线程安全”指的是一个函数、方法或代码块能够在多个线程同时执行时,不会出现意外的交互或破坏共享数据,能够安全地运行。 POSIX 对线程安全的定义很清楚: “一个线程安全的函数可以在多个线程中被安全地并…

热方程初边值问题解法

已知公式: u ( x , t ) ∫ − ∞ ∞ G ( x , y , t ) g ( y ) d y . u(x,t)\int_{-\infty}^{\infty}G(x,y,t)g(y)dy. u(x,t)∫−∞∞​G(x,y,t)g(y)dy. (1) 其中 G ( x , y , t ) 1 2 k π t e − ( x − y ) 2 4 k t G(x,y,t)\frac{1}{2…

怎样理解:source ~/.bash_profile

场景复现 $ source ~/.bash_profileAnalysis 分析 一句话概括 source ~/.bash_profile “在 当前 终端会话里,立刻执行并加载 ~/.bash_profile 中的所有命令,让其中定义的环境变量、函数、alias 等即时生效,而无需重新登录或开新 Shell。…

搜索问答技术概述:基于知识图谱与MRC的创新应用

目录 一、问答系统应用分析 二、搜索问答技术与系统 (一)需求和信息分析 问答需求类型 多样的数据源 文本组织形态 (二)主要问答技术介绍 发展和成熟度分析 重点问答技术基础:KBQA和DeepQA KBQA(…

TCP数据的发送和接收

本篇文章结合实验对 TCP 数据传输中的重传机制、滑动窗口以及拥塞控制做简要的分析学习。 重传 实验环境 这里使用两台腾讯云服务器:vm-1(172.19.0.3)和vm-2(172.19.0.6)。 超时重传 首先 vm-1 作为服务端启动 nc…

python 保存二维数组到本地

Python中保存二维数组有多种方法,以下是常用的几种方式:1. 使用NumPy(推荐)import numpy as np# 创建二维数组 arr np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])# 保存为.npy文件(NumPy专用格式) np.save…

LIN总线通讯中从节点波特率同步原理

波特率同步原理:从节点如何通过0x55校准时钟? 一、同步场的核心作用:统一“时间标尺” 在LIN总线中,主节点与从节点各自拥有独立的时钟源(如MCU内部RC振荡器),但由于制造工艺差异,…

【Unity笔记02】订阅事件-自动开门

流程 当玩家移动到触发区域的时候,门自动打开 事件系统 using System; using System.Collections; using System.Collections.Generic; using UnityEngine;public class EventSystem : MonoBehaviour {public static EventSystem Instance { get; private set; }…

控制台字符动画

旋转的立方体 #include <cstdint> #include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <cstdlib> #include <ctime> #include <thread> using namespace std;float angleX .0f; float a…

基于 PyTorch 的猫狗图像分类实战

基于 PyTorch 的猫狗图像分类实战 项目背景简介 深度学习框架 PyTorch 因其动态计算图和灵活易用性&#xff0c;被广泛应用于图像分类等计算机视觉任务。在入门计算机视觉领域时&#xff0c;常常以手写数字识别&#xff08;MNIST&#xff09;作为 “Hello World”&#xff0c…

SwiftUI 7(iOS 26 / iPadOS 26)中玻璃化标签页的全新玩法

&#x1f378; Liquid Glass 登场&#xff1a;界面设计焕然一新 WWDC25 可谓惊喜连连&#xff0c;其中最引人瞩目的变革之一&#xff0c;莫过于苹果推出的全新跨平台设计语言 —— Liquid Glass&#xff08;液态玻璃&#xff09;。这一设计风格涵盖了从按钮到导航栏&#xff0…

PDF处理控件Spire.PDF教程:在Java中读取PDF,提取文本、图片和表格

在数据驱动的现代开发中&#xff0c;高效处理 PDF 文档已成为 Java 开发者不可或缺的核心能力。无论是处理各类发票扫描件、业务分析报告&#xff0c;还是包含丰富图表的技术文档&#xff0c;掌握 Java 版的 PDF 解析技术都将大幅提升数据处理效率&#xff0c;充分释放文档中的…

跨平台游戏引擎 Axmol-2.7.0 发布

Axmol 2.7.0 版本是一个以错误修复和功能改进为主的次要LTS长期支持版本 &#x1f64f;感谢所有贡献者及财务赞助者&#xff1a;scorewarrior、peterkharitonov、duong、thienphuoc、bingsoo、asnagni、paulocoutinhox 重大变更 Android Studio 最低版本要求升级至 2025.1.1…

XML 笔记

<image src"hue.gif" width"100" height"auto" align"left"/> <br/> 换行 在 XML 中&#xff0c;<![CDATA[ 和 ]]> 用于定义一个 CDATA 节&#xff08;Character Data Section&#xff09;。CDATA 节是用于将一段…