机器视觉Day1 | 卡尔曼滤波、拟合、Apriltag、ARToolkit

拟合:

通过对点的拟合形成线、面。

-->常用方法
最小二乘法、梯度下降法、高斯牛顿(即迭代最小二乘法)、列-马算法。
-->分类
分为线性、非线性。非线性拟合常用多项式拟合

参考:
https://blog.csdn.net/weixin_60737527/article/details/123849242

——————————————————————————————

Apriltag:

AprilTag是一个视觉基准库,在AR,机器人,相机校准领域广泛使用。
通过特定的标志(与二维码相似,但是降低了复杂度以满足实时性要求),可以快速地检测标志,并计算相对位置。

官网:https://april.eecs.umich.edu/software/apriltag.html

——————————————————————————————

ARToolkit
ARToolKit系统核心思路:

参考:https://www.cnblogs.com/polobymulberry/p/5857372.html

——————————————————————————————

卡尔曼滤波:

(通过预测进行目标追踪,增强鲁棒性,避免目标跟踪遗失的情况)
-适用于线性系统 高斯滤波环境(噪声高斯分布)-

-->现象视频:

https://www.bilibili.com/video/BV1Qf4y1J7D4/?spm_id_from=333.999.0.0&vd_source=ca4c6311ee3cdb1d6b0fbe334efa29c4

-->扩展卡尔曼:

非线性to线性(泰勒展开 计算雅可比矩阵)

一、简介

卡尔曼滤波是一种估算系统状态的方法,它结合了系统的动态模型(即我们如何认为系统状态会随时间变化)和传感器的实际测量值。通过不断地预测和更新,卡尔曼滤波能够逐渐减小对系统状态估计的不确定性,从而得到更准确的估计结果。

二、流程

  • 初始化:
    设定一个初始的状态估计值(比如,您认为系统现在处于什么状态)。
    设定一个初始的协方差矩阵(表示您对初始状态估计的不确定性有多大)。
  • 预测:
    使用系统的动态模型(可能是一个或多个数学方程),根据上一时刻的状态估计值,预测当前时刻的状态(尽管这只是一个猜测,但基于我们的模型)。
    同时,更新协方差矩阵,以反映这个预测的不确定性(因为模型本身可能不准确,或者受到外部干扰)。
  • 观测:
    从传感器获取当前时刻的实际测量值。
  • 更新:
    比较预测值和测量值之间的差异(残差)。
    使用这个残差来调整我们的预测值,得到一个更接近真实状态的新估计值(后验估计值)。
    同时,更新协方差矩阵,以反映这个新估计值的不确定性(现在我们已经有了更多的信息,所以不确定性应该减小了)。
  • 重复:
    使用新的状态估计值和协方差矩阵,重复上述的预测和更新步骤,不断地逼近真实的系统状态。

三、核心方程

  • 状态预测方程:告诉我们如何根据上一时刻的状态来预测当前时刻的状态。
  • 协方差预测方程:告诉我们预测的不确定性有多大。
  • 卡尔曼增益方程:是一个“权衡”因子,它决定了在更新过程中我们应该更相信预测值还是测量值。
  • 状态更新方程:使用卡尔曼增益和测量残差来调整预测值,得到新的状态估计值。
  • 协方差更新方程:更新我们对新状态估计值的不确定性。

四、教程:

协方差矩阵: https://www.bilibili.com/video/BV1mD421W7Ko/?spm_id_from=333.337.search-card.all.click&vd_source=ca4c6311ee3cdb1d6b0fbe334efa29c4

五、python实现

NumPy库来实现的一维卡尔曼滤波
点击查看代码
import numpy as np  
  
# 定义卡尔曼滤波的参数  
# 状态转移矩阵  
A = np.array([[1]])  
# 控制矩阵(如果系统没有控制输入,则为0)  
B = np.array([[0]])  
# 观测矩阵  
H = np.array([[1]])  
# 过程噪声协方差  
Q = np.array([[1e-5]])  
# 观测噪声协方差  
R = np.array([[1]])  
# 初始状态估计  
x_est = np.array([[0]])  
# 初始误差协方差估计  
P_est = np.array([[1]])  
  
# 真实状态和观测数据(为了示例而模拟)  
true_state = np.array([0.37])  
measurements = np.array([0.39, 0.50, 0.48, 0.29, 0.25, 0.32, 0.34, 0.48, 0.41, 0.45])  
  
# 卡尔曼滤波更新过程  
estimates = []  
for meas in measurements:  
    # 预测  
    x_pred = A @ x_est  
    P_pred = A @ P_est @ A.T + Q  
      
    # 更新  
    K = P_pred @ H.T @ np.linalg.inv(H @ P_pred @ H.T + R)  
    x_est = x_pred + K @ (meas - H @ x_pred)  
    P_est = (np.eye(len(x_est)) - K @ H) @ P_pred  
      
    estimates.append(x_est[0,0])  
  
# 输出结果  
print(estimates)
二维滤波
点击查看代码
import numpy as np  
  
class KalmanFilter:  
    def __init__(self, dt, process_variance, measurement_variance):  
        # 状态转移矩阵 A  
        self.A = np.array([[1, dt], [0, 1]])  
          
        # 观测矩阵 H  
        self.H = np.array([[1, 0], [0, 1]])  
          
        # 过程噪声协方差矩阵 Q  
        self.Q = np.array([[0.01, 0], [0, 0.01]]) * dt**2  
          
        # 观测噪声协方差矩阵 R  
        self.R = np.array([[measurement_variance, 0], [0, measurement_variance]])  
          
        # 初始状态估计 x  
        self.x = np.array([[0], [0]])  # 初始位置和速度  
          
        # 初始协方差矩阵 P  
        self.P = np.array([[1, 0], [0, 1]])  
  
    def predict(self):  
        # 预测下一个状态  
        self.x = np.dot(self.A, self.x)  
        # 更新协方差矩阵  
        self.P = np.dot(np.dot(self.A, self.P), self.A.T) + self.Q  
  
    def update(self, z):  
        # 计算卡尔曼增益  
        S = np.dot(np.dot(self.H, self.P), self.H.T) + self.R  
        K = np.dot(np.dot(self.P, self.H.T), np.linalg.inv(S))  
          
        # 更新状态估计  
        y = z - np.dot(self.H, self.x)  
        self.x = self.x + np.dot(K, y)  
          
        # 更新协方差矩阵  
        I = np.eye(len(self.x))  
        self.P = np.dot((I - np.dot(K, self.H)), self.P)  
  
# 使用示例  
dt = 0.1  # 时间间隔  
process_variance = 0.1  # 过程噪声方差  
measurement_variance = 1.0  # 观测噪声方差  
  
kf = KalmanFilter(dt, process_variance, measurement_variance)  
  
# 模拟一些观测数据  
true_x = 0  
true_y = 0  
true_vx = 1  
true_vy = 1  
  
measurements = []  
for _ in range(40):  
    true_x += true_vx * dt  
    true_y += true_vy * dt  
    # 添加一些噪声  
    z_x = true_x + np.random.normal(0, measurement_variance)  
    z_y = true_y + np.random.normal(0, measurement_variance)  
    measurements.append([z_x, z_y])  
  
# 运行卡尔曼滤波器  
estimated_positions = []  
for z in measurements:  
    kf.predict()  
    kf.update(np.array(z).reshape(2, 1))  
    estimated_positions.append(kf.x.flatten().tolist())  
  
# 输出结果(可选)  
for pos in estimated_positions:  
    print(pos)
filterpy库实现

- filterpy是一个专门用于实现各种滤波算法的Python库,包括卡尔曼滤波、扩展卡尔曼滤波、无迹卡尔曼滤波等。使用filterpy可以大大简化卡尔曼滤波的实现过程。 -

点击查看代码
from filterpy.kalman import KalmanFilter  
import numpy as np  
  
# 初始化卡尔曼滤波器  
kf = KalmanFilter(dim_x=1, dim_z=1)  
kf.x = np.array([[0.]])  # 初始状态  
kf.F = np.array([[1.]])  # 状态转移矩阵  
kf.H = np.array([[1.]])  # 观测矩阵  
kf.R = np.array([[1.]])  # 观测噪声协方差  
kf.Q = np.array([[1e-5]])  # 过程噪声协方差  
kf.P *= 1000.  # 初始误差协方差矩阵,赋予较大值  
  
# 真实状态和观测数据(为了示例而模拟)  
measurements = np.array([0.39, 0.50, 0.48, 0.29, 0.25, 0.32, 0.34, 0.48, 0.41, 0.45])  
  
estimates = []  
for meas in measurements:  
    kf.predict()  
    kf.update(meas)  
    estimates.append(kf.x[0,0])  
  
print(estimates)
posted @ 2024-07-13 18:24  三小花荷包蛋  阅读(29)  评论(0编辑  收藏  举报