Kalman滤波器真的太复杂了,因此整理了这篇文章,来记录一下对自己有用的一些参考链接。
如果用我自己的话来总结kalman滤波器(可能不准确):

  1. 要观测的目标自身存在一个运动状态(状态方程);
  2. 在这个目标身上我安装了一些传感器(观测方程);
  3. 我可以通过它上一个的运动状态,来预测此时刻的位置;
  4. 我也可以通过传感器来直接检测出它此时刻的位置;
  5. 但是这个世界存在着误差,我无论预测还是检测都可能不准;
  6. 因此我打算将预测值和检测值数据融合一下;
  7. 在数据融合过程中,我更相信预测值还是检测值,那就用到卡尔曼增益(Kk);
  8. Kalman帮我决定更相信预测值还是检测值进行了量化,Kalman根据协方差矩阵、状态观测矩阵等写出了一个方程,让估计误差最小。

在这里插入图片描述

Kalman跟踪直观感受

链接说明
用卡尔曼滤波器打造一个简易单目标跟踪器

Kalman原理

链接说明
授之以渔: 卡尔曼滤波器 …大泻蜜 …一个段子,啥都没记住就记住了这个哈哈
【卡尔曼滤波器】1_递归算法_Recursive Processing对卡尔曼原理解说的视频,方便入门,也适合二刷三刷
目标跟踪之卡尔曼滤波—理解Kalman滤波的使用预测对状态方程和观测方程进行了比较详细的解说。
图像处理之目标跟踪(一)之卡尔曼kalman滤波跟踪(主要为知识梳理)(转载)对预测和更新方程进行了比较详细的说明,但是写得比较凌乱
如何快速理解卡尔曼滤波跟踪 python 目标跟踪算法对预测和更新方程进行了比较详细的说明,但是写得比较凌乱

Kalman应用

链接说明
卡尔曼滤波在目标跟踪中的运用python中卡尔曼滤波的案例以及调用opencv自带库的写法
学习OpenCV2——卡尔曼滤波(KalmanFilter)详解待读
使用Kalman滤波器做目标跟踪待读

opencv官方kalman函数说明
cv::KalmanFilter Class Reference

自己写了个类
输入值为目标的中心坐标和长宽,输入预测的坐标位置和速度,可能存在部分错误,需后期修正。

import cv2
import numpy as np
# from myUtils.utils import xyxy_to_xywh


class KalmanTrack:
    def __init__(self):
        # 状态数和观测数需要修改
        self.kalman = cv2.KalmanFilter(6, 4)  # 6:状态数,包括(xmin,ymin,xmax,ymax, dx,dy)坐标及速度(每次移动的距离);
                                              # 4:观测量,能看到的是坐标值

        # 状态转移矩阵
        A = np.array([[1, 0, 0, 0, 1, 0],
                      [0, 1, 0, 0, 0, 1],
                      [0, 0, 1, 0, 0, 0],
                      [0, 0, 0, 1, 0, 0],
                      [0, 0, 0, 0, 1, 0],
                      [0, 0, 0, 0, 0, 1]], np.float32)
        self.kalman.transitionMatrix = A  # 状态转移矩阵

        # 控制矩阵
        B = None
        self.kalman.controlMatrix = B

        # 状态观测矩阵
        H = np.array([[1, 0, 0, 0, 0, 0],
                      [0, 1, 0, 0, 0, 0],
                      [0, 0, 1, 0, 0, 0],
                      [0, 0, 0, 1, 0, 0]], np.float32)
        self.kalman.measurementMatrix = H  # 系统测量矩阵

        # 观测噪声协方差矩阵R,p(v)~N(0,R)
        # 观测噪声来自于检测框丢失、重叠等
        R = np.array([[1, 0, 0, 0],
                      [0, 1, 0, 0],
                      [0, 0, 1, 0],
                      [0, 0, 0, 1]], np.float32)
        self.kalman.measurementNoiseCov = R

        # 过程噪声协方差矩阵Q,p(w)~N(0,Q),噪声来自真实世界中的不确定性,
        # 在跟踪任务当中,过程噪声来自于目标移动的不确定性(突然加速、减速、转弯等)
        Q = np.eye(6, dtype=np.float32) * 0.1
        self.kalman.processNoiseCov = Q

        # 状态估计协方差矩阵P初始化
        P = np.eye(6, dtype=np.float32)
        self.kalman.errorCovPre = P

        self.cur_measurement = np.nan
        self.cur_prediction = np.nan

        self.pre_measurement = np.nan
        self.pre_prediction = np.nan

    def get_cur_state(self, target_box):
        """获取初始值状态测量值"""
        # target_box = [729, 238, 764, 339]
        self.cur_measurement = target_box  # 目标初始bouding box

        # self.cur_measurement = xyxy_to_xywh(self.cur_measurement)

        #  [中心x,中心y,宽w,高h]
        self.cur_measurement = np.array(
            [[np.float32(self.cur_measurement[0]), np.float32(self.cur_measurement[1]),
              np.float32(self.cur_measurement[2]), np.float32(self.cur_measurement[3])]]).T

        return self.cur_measurement

    def get_initial_state(self, target_box):
        self.cur_measurement = self.get_cur_state(target_box)

        self.pre_measurement = self.cur_measurement
        self.cur_prediction = self.cur_measurement
        self.pre_prediction = self.cur_measurement

    def correct_and_predict(self, target_box):
        # 将前线状态进行存储
        self.pre_measurement = self.cur_measurement
        self.pre_prediction = self.cur_prediction

        # 用当前测量来校正卡尔曼滤波器
        self.cur_measurement = self.get_cur_state(target_box)

        self.kalman.correct(self.cur_measurement)  # 用当前测量来校正卡尔曼滤波器
        self.cur_prediction = self.kalman.predict()  # 计算卡尔曼预测值,作为当前预测
        return self.cur_prediction


if __name__ == '__main__':
    kalman_tracker = KalmanTrack()
    kalman_tracker.get_initial_state([729, 288, 35, 101])  # xywh

    while True:
        # 将先前的预测值作为当前的测量值
        data = list([kalman_tracker.pre_prediction[0][0], kalman_tracker.pre_prediction[1][0],
                    kalman_tracker.pre_prediction[2][0], kalman_tracker.pre_prediction[3][0]])
        print(kalman_tracker.correct_and_predict(data))

更多推荐