简介:STRCF算法是目前视觉跟踪中颇具代表性的相关滤波改进方法,资源面向学习视觉目标跟踪的研究者与工程师,尤其适合希望深入理解相关滤波原理并动手复现论文成果的人群。算法两大贡献在于引入时间正则项抑制模型腐败,以及采用ADMM高效迭代求解以保证实时性,配套材料完整覆盖思路推导、论文原文与Matlab工程实现。压缩包共包含22个文件,除Matlab源码、CVPR论文PDF及原理解读HTML文档外,还有系列辅助图片与展示图,便于对照论文梳理公式和代码结构,整体大小约24.46MB。目前已有443人学习/下载,尤其适合作为相关滤波方向入门与进阶的参考。资源既可直接运行调试,也能帮助读者改造算法,在遮挡和形变场景下提升跟踪鲁棒性。
1. STRCF 要解决的那个问题:遮挡下的模型漂移
跑过相关滤波跟踪的人基本都见过这个场景:目标在 80 帧前还稳稳锁在响应峰上,下一秒半个人被汽车挡了 2 秒,再出现时响应图已经变成一摊噪声,跟踪框从此挂在旁边的电线上。问题不在响应计算,而在模板更新——典型 DCF 把每一帧的学习结果都直接叠进滤波器,遮挡样本在更新序列里占比一大,模型就被污染了。STRCF(Spatial-Temporal Regularized Correlation Filters,CVPR 2018)正是冲着这个坑去的:在 SRDCF 的空间正则基础上加一条时间正则,同时把单帧求解换成 ADMM 迭代,既抑制模型漂移,又把跟踪速度拉回实时区间。适合正在复现相关滤波论文、或者想给自己的跟踪器补一个抗遮挡模块的工程师。
2. 从 DCF 到 STRCF:空间正则与时间正则如何写进目标函数
2.1 相关滤波跟踪的本质:岭回归与循环移位
相关滤波跟踪器把目标跟踪建模成一个岭回归问题:给定当前帧图像块的特征矩阵 X,学一个滤波器 f,使得 X 与循环移位后的期望响应 y 之间的误差最小。这个问题的标准形式是
f* = argmin_f 1/2 || X f - y ||^2_2 + λ/2 || f ||^2_2X 是由目标区域循环移位构成的循环矩阵,利用循环矩阵在傅里叶域可对角化的性质,f 的求解可以变成逐元素的除法运算,这也是 KCF 能把跟踪速度做到几百 FPS 的根本原因。注意这里 f 的维度等于特征图大小,不是模型参数的个数,所以循环移位既承担了样本扩充的作用,也决定了求解只能在频域进行。
这套框架的问题在于:它假设每个训练样本的置信度是等价的。现实中遮挡、形变、出视野都会让某些帧的样本质量极低,把这些低质量样本以同样权重学进滤波器,响应图自然会被带偏。所以后面几乎所有改进工作都在回答一个问题:如何让滤波器对“坏样本”不敏感。
2.2 SRDCF 的空间正则为什么会在长视频里失效
SRDCF 是 STRCF 的直接前身,它在岭回归基础上引入了一个空间权重图 w,惩罚滤波器在目标区域以外的响应:
f* = argmin_f 1/2 || X f - y ||^2_2 + 1/2 || w · f ||^2_2w 的作用直观理解就是:滤波器系数在目标中心附近可以自由取值,远离中心的地方被压到接近 0,从而抑制边界效应。SRDCF 因此比 DCF 系列在复杂背景上有明显提升,但它仍然使用逐帧独立求解再平滑的更新策略。每一帧 f 都是对当前样本的单独最优解,上一帧的信息只通过训练样本的历史池间接影响结果,一旦目标被完全遮挡,当前帧的 X 里就没有目标,SRDCF 会把遮挡物的纹理当作新目标学进去。
我见过不少人在这个阶段用降低学习率来缓解,比如把更新系数从 0.02 调到 0.005,效果确实有,但代价是目标真实形变时跟踪器反应变慢,等于用一个参数同时承担了“抗遮挡”和“适应性”两个互相矛盾的需求,这在长视频里基本无解。
2.3 STRCF 的完整目标函数与三项损失的职责
STRCF 的思路是不再降低学习率,而是在目标函数里直接约束滤波器在时间轴上的变化。它对 SRDCF 的模型加了一个时间正则项:
min_f 1/2 || Σ_{d=1}^D x_t^d * f^d - y ||^2_2 + 1/2 Σ_{d=1}^D || w · f^d ||^2_2 + γ/2 || f - f_{t-1} ||^2_2第一项是重建误差,保证滤波器对当前帧的响应仍然集中在 y 上;第二项是空间正则,继承 SRDCF 的边界抑制能力;第三项是 STRCF 的核心贡献——时间正则,它强制当前帧滤波器 f 和上一帧滤波器 f_{t-1} 不要差太多。γ 越大,滤波器在时间轴上越平滑。
这里有个容易被忽略的细节:时间正则不是对响应做平滑,而是对滤波器系数本身做平滑。响应平滑是把输出抹匀,目标快速移动时会产生延迟;滤波器平滑约束的是模型更新的幅度,当遮挡导致当前样本异常时,最优 f 会倾向于靠近历史模型,而不是被单帧样本拉走。这三项合在一起,让 STRCF 在保持实时性的前提下,把抗遮挡能力提升了一个量级,并且不需要显式判断当前帧是否遮挡——时间正则本身就是一种软性的遮挡检测。
3. ADMM 求解:把耦合目标拆成三个可闭式求解的子问题
3.1 引入辅助变量与增广拉格朗日形式
上一章的优化问题里,时间正则项把当前帧 f 和上一帧 f_{t-1} 耦合在一起,而且空间正则项里的 w 作用于 f 的前提是它在空间域,但重建误差在傅里叶域计算更方便。直接在频域求解会遇到两个正则项同时作用在 f 上,导致频域下的矩阵不是对角化的,直接求逆的复杂度会随特征维度爆炸。STRCF 的解法是用 ADMM 拆开,引入辅助变量 g,把空间正则从 f 上摘出来:
min_{f,g} 1/2 || Σ_{d=1}^D x_t^d * f^d - y ||^2_2 + 1/2 Σ_{d=1}^D || w · g^d ||^2_2 + γ/2 || f - f_{t-1} ||^2_2 s.t. g = f增广拉格朗日形式写成:
L(f, g, u) = 1/2 || X_t f - y ||^2_2 + 1/2 || w · g ||^2_2 + γ/2 || f - f_{t-1} ||^2_2 + μ/2 || f - g + u ||^2_2这里 u 是缩放后的对偶变量,μ 是惩罚因子,初始值一般取 0.01 到 0.05 之间。ADMM 的意义是把一个耦合的凸优化问题变成三个单变量子问题交替求解,每个子问题都有闭式解或者快速解法,不需要在每帧里跑一个完整的优化器。下面这张表总结了三个子问题的求解域和主要运算。
| 子问题 | 求解域 | 主要运算 | 复杂度 |
|---|---|---|---|
| f 子问题 | 傅里叶域 | Sherman-Morrison 公式加速求逆 | O(T),T 为单通道像素数 |
| g 子问题 | 空间域 | 逐元素除法与软阈值收缩 | O(T) |
| u 更新 | 空间域 | 逐元素加法 | O(T) |
| 收敛检查 | 空间域 | 计算原始残差的 Frobenius 范数 | O(T) |
3.2 f 子问题:频域下如何利用 Sherman-Morrison 加速
f 子问题固定 g 和 u,此时目标函数是:
min_f 1/2 || X_t f - y ||^2_2 + γ/2 || f - f_{t-1} ||^2_2 + μ/2 || f - g + u ||^2_2这里 X_t 是循环矩阵,频域下 X_t 变成对角矩阵,但后面两项是 f 在空间域的模长,存在频域和空间域的混合。STRCF 的处理是直接对该子问题做傅里叶变换,得到关于每个频点的一个 2c×2c 的小方程组(c 是通道数),再利用 Sherman-Morrison 公式把求逆化简为标量运算:先算一个公共分母,再做一次矩阵向量乘。
% 伪代码:f 子问题的频域求解骨架 % x_fd : 当前帧特征图的 FFT,维度 [height, width, channels] % f_prev : 上一帧滤波器系数的 FFT % g_fd : 辅助变量 g 的 FFT % u_fd : 对偶变量 u 的 FFT for p = 1:height for q = 1:width % 每个频点单独解一个 2C x 2C 的线性系统 A_11 = x_fd(p,q,:).' * x_fd(p,q,:) + (mu + gamma) * eye(C); A_12 = -mu * eye(C); A_21 = -mu * eye(C); A_22 = (mu + lambda) * eye(C); % lambda 由 w 的频域能量决定 rhs = [x_fd(p,q,:).' * y_fd(p,q); mu * (g_fd(p,q,:).' - u_fd(p,q,:).') + gamma * f_prev(p,q,:).']; sol = [A_11 A_12; A_21 A_22] \ rhs; f_fd(p,q,:) = sol(1:C); end end这个伪代码里 C 是特征通道数,height 和 width 是特征图尺寸。理论上的闭式解比逐像素求逆更快,因为 Sherman-Morrison 把 2C×2C 的矩阵求逆降到了 O(C) 的向量运算,整个子问题的复杂度是 O(HC) 即与像素数线性相关。实际调试中你会发现,这一块最大的坑不是公式,而是频域数据排列:MATLAB 的 fft2 结果直流分量在左上角,而论文推导默认 0 频率在中心,跑之前把 fftshift 的使用统一好,否则响应图会出现一个斜向的条纹噪声。
3.3 g 子问题与对偶变量更新
g 子问题固定 f 和 u,形式上是空间正则加二次项:
min_g 1/2 || w · g ||^2_2 + μ/2 || f - g + u ||^2_2因为 w 是逐元素的空间权重矩阵,这个子问题在空间域直接对着每个像素独立求解,不需要频域变换。令 w_i 为第 i 个像素的权重,解为 g_i = (μ (f_i + u_i)) / (w_i^2 + μ),本质是一个带权收缩操作。这也说明了空间正则项为什么必须和 f 解耦:如果 w 直接作用在 f 上,f 子问题的频域对角化就失效了,ADMM 在这里的价值就是把不可分的问题变成可分的问题。
对偶变量 u 的更新则是标准步:u = u + f - g。迭代终止条件一般看原始残差 ||f - g||_F 的最大值是否小于容差,通常设 1e-3 到 1e-5。ADMM 的迭代次数不需要很多,STRCF 论文在 2 次 ADMM 迭代时就能达到不错的精度,Matlab 实现里设 10 次以内即可——继续增加迭代次数对跟踪精度的提升远小于对计算时间的消耗,这个边界值得记录。
4. MATLAB 实现:跑通 demo、读懂迭代主循环与参数调整
4.1 资源包目录结构与运行前置条件
解压STRCF算法-matlab实现、论文及原理解读.rar后,你会看到几个核心内容:一端 STRFCF 的 Matlab 工程源码文件夹,一份 CVPR 2018 原版 PDF 论文,还有一份整理好的 HTML 版原理解读,里面嵌了论文核心公式和配图,适合不想来回翻 PDF 的时候对照着看。源码目录结构通常是 track 主函数、特征提取函数、ADMM 求解函数三个层次:
STRCF-master/ ├── run_tracker.m # 主入口:选视频、初始化参数、循环跟踪 ├── STRCF_optimization.m # ADMM 迭代求解滤波器 ├── extract_features.m # 提取 HOG 特征 ├── load_video_info.m # 读取跟踪序列 ├── parameters/ # 默认参数表 └── results/ # 跟踪结果输出目录运行前提是 MATLAB 版本不低于 R2018b,需要 Image Processing Toolbox,因为特征提取环节用到了 imresize 和 fspecial 系列函数。不需要额外的编译库,也不用装深度学习工具箱,这一点对于只想快速复现论文结果的人来说比较友好。注意,如果当前环境装了旧版 MEX 编译器,优先mex -setup选择与 R2018b 匹配的版本,否则特征提取里少数用 C 加速的步骤会掉回解释执行,速度损失肉眼可见。
4.2 主循环代码与公式的对应关系
在run_tracker.m里,每一帧定位的流程是先裁剪搜索区域、提取 HOG 特征、做汉宁窗处理,然后调用 ADMM 迭代求解当前帧滤波器。核心的滤波求解代码逻辑如下:
% 每一帧:x_patch 是裁剪并提取特征后的图像区域 for frame = 1:num_frames % 特征图是三维数组 [h, w, channels] x = extract_features(im_patch, cell_size); x = hann_window .* x; % 循环边界平滑,等价于空间正则的补充 x_fd = fft2(x); % 转频域 % 初始化:上一帧滤波器作为当前帧迭代起点 f = f_prev; g = f; u = zeros(size(f)); % ADMM 迭代求解 for iter = 1:max_iter % 子问题 f:频域内用 Sherman-Morrison 更新 f_fd = subproblem_f(x_fd, y_fd, g, u, f_prev, mu, gamma); % 子问题 g:空间域逐像素收缩 g = subproblem_g(real(ifft2(f_fd)), u, w, mu); % 对偶变量更新 u = u + (real(ifft2(f_fd)) - g); % 提前终止检查 if norm(real(ifft2(f_fd)) - g, 'fro') < 1e-4 break; end end f_prev = real(ifft2(f_fd)); end这段代码里subproblem_f对应 3.2 节的频域求解,入参mu是 ADMM 惩罚因子,gamma是时间正则系数,两者共同决定滤波器更新的激进程度;subproblem_g对应 3.3 节的空间域收缩,w是由汉宁窗导出的空间权重矩阵。运行前注意把搜索区域 padding 系数设置正确,这是新手最容易出错的地方——STRCF 的搜索区域是目标尺寸的padding × 目标尺寸,默认是 1.5 倍,如果设置太小,快速运动的目标会直接跳出搜索区域,ADMM 怎么调都救不回来。
4.3 参数调整表:哪些值值得动了会怎样
从工程角度看,STRCF 的默认参数在大多数 OTB 序列上已经表现良好,但不同场景下的调整空间仍然很大。下面给出我复现时常用的调整表:
| 参数 | 默认值范围 | 作用 | 调大效果 | 调小效果 |
|---|---|---|---|---|
| gamma(时间正则系数) | 3~5 | 约束滤波器相邻帧变化幅度 | 抗遮挡增强,目标快速形变时滞后 | 适应性强,遮挡时漂移风险上升 |
| mu(ADMM 惩罚因子) | 0.01~0.05 | 控制辅助变量与 f 的一致性 | 迭代收敛快,但可能震荡 | 收敛慢,需要更多迭代次数 |
| max_iter | 5~10 | ADMM 最大迭代次数 | 精度微升,速度明显下降 | 速度提升,遮挡场景下精度下滑 |
| padding | 1.5~2.5 | 搜索区域相对目标尺寸的倍数 | 容纳大位移,计算量增大 | 快速运动目标容易丢失 |
| cell_size | 4 | HOG 特征网格大小 | 特征粗糙,速度快 | 特征精细,速度慢 |
我一般在处理快速形变场景时把 gamma 从 4 降到 2,同时把 max_iter 从 5 提到 8,来补偿时间约束放松后引入的噪声;处理遮挡频繁的监控视频时反过来,gamma 调到 6,搜索区域 padding 提到 2.0。注意 max_iter 不要超过 15,超过之后的收益几乎全部被计算时间吃掉,没有实际意义。
5. 验证与落地:怎么判断时间正则真的在起作用
5.1 用 OTB 指标说话,而不是只看 visual 效果
接入 OTB 或者 LaSOT 评测脚本后,主要盯两个数:precision plot 和 success plot 的 AUC。前者计算跟踪中心误差小于 20 像素的帧占比,后者计算重叠率阈值从 0 到 1 的曲线下面积。STRCF 在你的数据上应该比同配置下的 SRDCF 高出 2~3 个百分点,特别是在 OTB 的occ、bc、def三个属性子集上拉开差距。如果这个差距不存在,优先怀疑时间正则项是否真的进入了梯度计算,检查subproblem_f里是否漏加了gamma * f_prev这一项。
5.2 遮挡场景下的响应图诊断
一个判断时间正则是否生效的方法是人为制造遮挡:把目标在中间连续 10 帧涂黑,再让目标恢复。跑完后画出每帧响应最大值的曲线。没有时间正则的跟踪器,遮挡期间响应峰值会持续下降且恢复后不可逆;正确实现的 STRCF,遮挡期间响应峰值虽然下降,但目标重新出现后能迅速恢复到原始水平。这比看跟丢没跟丢要灵敏得多,因为很多情况下滤波器已经轻微腐败,但目标恰好还在视野中,回调曲线能捕捉到这种早期退化。
% 在 run_tracker.m 主循环里插入响应峰记录 [~, max_idx] = max(response_map(:)); % response_map 为当前帧相关响应 peak_record(frame) = response_map(max_idx); % 跟踪结束后绘制曲线,遮挡帧落在 301:310 区间 plot(peak_record); xlabel('frame'); ylabel('peak response');Script 里注意response_map在代码中统一用ifft2( sum(f .* x, 3) )计算,不要对峰值做归一化处理——归一化会抹掉帧间变化的信息,这条曲线就失去了诊断价值。
5.3 参数边界与后续改进空间
时间正则项不是越大越好:gamma 超过 8 时,滤波器几乎停止更新,目标做剧烈形变或快速转身时跟踪器会贴在旧模板上。实际调试中把 gamma 做成指数扫描,0.5 到 8 之间取 5 个值,看 validation 序列的精度曲线,通常在一个平台上先升后降,平台区就是安全区间。对于平移运动为主的长视频,建议使用较小的 gamma 配合较大 padding;对于形变频繁的场景,可以去掉独立的时间正则,改用自适应权重,把响应图的置信度映射到 gamma 上。这么做之后,再考虑叠加深度特征分支——STRCF 的框架对深度特征天然兼容,只需要把 HOG 特征替换成 ResNet 某层输出,并相应调整通道数,就能获得更鲁棒的表征能力。最后的检查手段是画出算法流程图对照论文第 2 节的推导顺序,重点核对 f 子问题的 Sherman-Morrison 分支里,时间正则项是否同时对分子分母产生了贡献。
本文还有配套的精品资源,点击获取