对象跟踪:轻松使用卡尔曼滤波器






4.89/5 (32投票s)
离散卡尔曼滤波器简要教程,附带 C# 示例
![]() |
|
![]() |
![]() |
卡尔曼滤波器轨迹估计: 测量(检测)噪声被设置为一个相对较高的值,但卡尔曼滤波器成功地预测并修正了对象轨迹。 | 卡尔曼 + Camshift 跟踪: Camshift 用于检测对象,卡尔曼滤波器用于校正和估计对象的轨迹。 |
目录
引言
![]() |
|
计算机视觉的首要任务之一是对象跟踪。对象跟踪广泛应用于各种应用程序中,例如:视频监控、汽车跟踪(距离估计)、人体检测和跟踪等。对象跟踪器通常需要一些初始化步骤,例如初始对象位置,这可以通过手动或使用对象检测器(如 Viola 和 Jones 检测器或快速模板匹配)自动提供。跟踪存在几个主要问题:
- 遮挡
- 多目标跟踪
- 尺度、光照和外观变化
- 困难和快速运动
- ...
尽管对象跟踪问题已经存在多年,但尽管有许多对象跟踪器,即使是为特殊目的构建的,以及那些试图普遍解决问题的跟踪器,它仍然没有得到解决。
卡尔曼滤波器,尽管它们可以用于许多其他目的,但经常用于对象跟踪。它们特别适用于已知运动模型的对象,此外,它们还结合了一些额外信息,以便更鲁棒地估计下一个对象位置。它们可以在某些约束条件下用于通用单目标跟踪。本文将解释卡尔曼滤波器背后的主要思想,并将重点介绍其在对象跟踪中的实际应用以及示例。
卡尔曼滤波器 - 主要思想
假设我们有某种检测器,并且我们的检测器不完善:它容易产生误报,并不总是能检测到对象,检测不完善(不提供精确的位置和尺度),而且执行成本高昂。我们还假设我们正在跟踪一名足球运动员。检测到对象后,我们希望利用关于对象的信息,尽可能鲁棒地跟踪它。我们的检测器只会给我们对象的位置,所以我们必须尽可能地利用它。为了预测玩家的下一个位置,我们将需要一个对象运动模型(例如,匀速运动、匀加速运动)。我们的检测器不完善,所以对象位置存在噪声,通常称为测量噪声。此外,选定的运动模型不会完美地描述玩家的运动,所以我们也存在与模型相关的噪声,称为过程噪声。我们希望仅通过以下三个参数来估计玩家的下一个位置:
- 对象运动模型
- 测量噪声
- 过程噪声
因此,我们可以有效地重新检测它,并有望应对对象遮挡。接下来的章节将向您展示如何做到这一点。
![]() |
卡尔曼滤波器的循环。 卡尔曼滤波器的大部分工作可以归结为传播和更新高斯分布,并更新其协方差。首先,滤波器根据提供的状态转换(例如运动模型)预测下一个状态,然后,如果适用,将有噪声的测量信息纳入校正阶段。这个循环会重复进行。 |
初始状态
我们将首先介绍初始状态以及我们试图实现的目标。以下图片展示了初始状态并同时介绍了最相关的术语。
阅读本节时请记住
- x(t) - 状态向量
- z(t) - 测量
- P(t|t-1) - 过程协方差矩阵
预测
预测是第一步,包括下一个状态(位置和速度)预测以及更新我们对对象状态的不确定性(增加不确定性)。
阅读本节时,请记住
- F - 状态转移矩阵
- Q(t) - 过程噪声协方差
正确
获得有噪声的测量后,校正步骤开始。它包含卡尔曼滤波器更新,包括状态更新和不确定性更新(减少不确定性)。
阅读本节时,您应该知道什么是
- R(t) - 测量噪声
现在,当您了解了基础知识后,是时候进行实际示例了,但首先简要介绍一下实现。
实现
所提供的实现是通用的:DiscreteKalmanFilter<TState, TMeasurement>
。通用参数是状态类型(TState
)和测量类型(TMeasurement
)。这种实现方式增加了一个抽象层,从而实现了
- 更容易的代码处理
- 更容易的调试
- 可扩展性
下面的类图显示了实现的概述
![]() |
类图。 卡尔曼滤波器的实现包括两个类——一个抽象类和一个实现离散卡尔曼滤波器的具体类。常见的运动模型也已实现。 |
假设我们要使用恒定速度模型,并且测量模型是对象的位置(正如上图所示)。此示例的用法示例如下所示。
初始化
最复杂的步骤是初始化。我们必须设置:过程噪声和测量噪声(Q 和 R)、过程协方差矩阵(P)、状态转移矩阵(F)和模型选择矩阵(H)。内置模型极大地简化了此任务。由于灵活性,初始化步骤稍长。例如,扩展卡尔曼滤波器需要每个步骤都改变的转移矩阵。此外,过程噪声和测量噪声(Q 和 R)可能不是常数,因此它们也可以在每个步骤中改变。
using ModelState = Accord.Extensions.Statistics.Filters.ConstantVelocity2DModel;
KalmanFilter<ModelState, PointF> kalman = null;
var measurementDimension = 2; //just coordinates
var initialState = new ModelState { Position = new PointF(0,0), Velocity = new PointF(0.5f, -2f)};
var initialStateError = ModelState.GetProcessNoise(accelerationNoise: 10); //process cov. mat. - P(0|0)
//create Kalman filter
kalman = new DiscreteKalmanFilter<ModelState, PointF>(
initialState, initialStateError, //x(0) and P(0|0)
measurementDimension /*(position)*/, 0 /*no control*/,
//state and measurement <=> array conversion
x => ModelState.ToArray(x), x => ModelState.FromArray(x), x => new double[] { x.X, x.Y });
kalman.ProcessNoise = ModelState.GetProcessNoise(accelerationNoise: 10.0); //process noise - Q
kalman.MeasurementNoise = Matrix.Diagonal<double>(kalman.MeasurementVectorDimension, 1.3); //measurement noise - R
kalman.MeasurementMatrix = ModelState.GetPositionMeasurementMatrix(); //measurement selection mat. - H
kalman.TransitionMatrix = ModelState.GetTransitionMatrix(); //state transition matrix - F
预测
预测步骤只包含一个方法,如果没有任何测量,该方法将重复执行,而不进行校正。
kalman.Predict(); //predict next state
正确
校正方法接收有噪声的测量值(例如从检测器获得)。
PointF objectPosition = .... //the position obtained by detector
kalman.Correct(objeectPosition); //correct predicted state by measurement
Console.WriteLine(kalman.State.Position.X + " " + kalman.State.Position.Y);
结论
本文介绍了用于目标跟踪问题的离散卡尔曼滤波器及其在 C# 中的实现。如果运动模型是线性的,并且过程噪声和测量噪声是类高斯分布的,那么卡尔曼滤波器代表了状态更新(在我们的案例中是跟踪问题)的最佳解决方案。这些条件在绝大多数应用中都得到了满足。
源代码和示例代码是 Accord.NET Extensions Framework 的一部分,该框架提供了许多主要用于图像处理、对象检测和跟踪的高级算法,所有这些都打包为流畅的扩展和简单直观的泛型,所以不要忘记看一看 :)
参考文献
[1] | Smith K. "计算机视觉精选主题 - 2D 跟踪 1/2 IJACI" 迄今为止最好的对象跟踪教程 - 本文中使用了一些幻灯片 |
[2] | Kantor G. "卡尔曼的美丽滤波器" |
[3] | Kalman, R. E. (1960). "线性滤波和预测问题的新方法"。Journal of Basic Engineering 82 (1): 35–45 |
历史
- 2015年1月16日 - 发布第一版