卡尔曼滤波(kalman filter)
可以基于目标前一时刻的位置,来预测当前时刻的位置,并且可以比传感器(在目标跟踪中即目标检测器,比如yolo等)更准确的估计目标的位置。
卡尔曼滤波被广泛应用于无人机,自动驾驶,卫星导航等领域,简单来说,其作用就是基于传感器的测量值来更新预测值,以达到更精确的估计。
假设我们要跟踪小车的位置变化,如下图所示,蓝色的分布是卡尔曼滤波预测值,棕色的分布是传感器的测量值,灰色的分布就是预测值基于测量值更新后的最优估计。
代码解析:
1.卡尔曼滤波器的启动
目标跟在初始化跟踪器tracker时,就会启动卡尔曼滤波器
main.py
tracker = Tracker(metric)#Tracker是一个类,这里初始化一个跟踪器
tracker.py
class Tracker:
def __init__(self, metric, max_iou_distance=0.7, max_age=30, n_init=3):
...
self.kf = kalman_filter.KalmanFilter()#启动卡尔曼滤波器
...
kalman_filter.py
class KalmanFilter(object):
def __init__(self):
ndim, dt = 4, 1.
# Create Kalman filter model matrices.
self._motion_mat = np.eye(2 * ndim, 2 * ndim)#生成一个8×8的单位矩阵
for i in range(ndim):
self._motion_mat[i, ndim + i] = dt #就是矩阵F,单位矩阵+dt,是为了计算状态的更新,x'=FX=x+dt*vx
self._update_mat = np.eye(ndim, 2 * ndim)#生成一个4×8的单位矩阵
# Motion and observation uncertainty are chosen relative to the current
# state estimate. These weights control the amount of uncertainty in
# the model. This is a bit hacky.
self._std_weight_position = 1. / 20
self._std_weight_velocity = 1. / 160
2. 每个track均值mean与方差covariance的初始化
在目标跟踪中,需要估计track的两个状态均值和方差:
均值(mean),表示目标的位置信息,由bbox的中心坐标(cx,cy),宽高比r,高h,以及各自的速度变化值组成,由8维向量表示为
x=[cx,cy,r,h,vx,vy,vr,vh]
各个速度值初始化为0。卡尔曼滤波器采用匀速模型和线性观测器模型,其观测变量为(cx,cy,r,h)
协方差(covariance):表示目标位置信息的不确定性,由8*8的对角矩阵表示,矩阵中数字越大则表明不确定性越大,可以以任意值初始化。
对于每一个不能匹配成功的新的检测目标detection,都将其初始化为一个新的track,均值mean与方差covariance为每个
track的属性,所以在构建新的track之前,需要通过卡尔曼滤波器计算其初始均值和方差
tracker.py
def update(self, detections):#执行测量更新和跟踪管理,入参detections本质是一个类,类中的各个属性和方法由一对对的box与对应的128特征向量刻画
for detection_idx in unmatched_detections:#对于未匹配成功的detectciton,初始化为新的track,
#对于第一帧图片,暂时只有检测目标,比如有3个检测目标,则全部为unmatched_detections,则将这3个检测目标初始化
self._initiate_track(detections[detection_idx])
def _initiate_track(self, detection):#这里传入来的detection,本质上是一个类class,定义在detection.py,print(detection)是一个地址
mean, covariance = self.kf.initiate(detection.to_xyah())#由检测目标detection的坐标((center x, center y, aspect ratio,
# height)构建均值向量(1×8的向量,初始化为[cenx,ceny,w/h,h,0,0,0,0]与协方差矩阵(8*8矩阵,根据目标的高度构造的一个对角矩阵),
self.tracks.append(