4. 深度学习跟踪入门:Siamese网络基础、SiamFC全卷积孪生网络
说到目标跟踪,很多人第一反应是“这不就是检测嘛”。其实不然。检测是每帧独立找目标,跟踪则要解决“目标长什么样、跑到哪去了”这两个问题。而深度学习时代,Siamese网络的出现,让跟踪这件事变得优雅了很多。
我个人最早接触Siamese网络是在做行人重识别的时候。那时候觉得“两个分支共享权重”这个设计很巧妙。后来发现,这个结构简直就是为跟踪量身定做的——你想想看,跟踪不就是“第一帧给个模板,后续帧去找最像的地方”吗?
4.1 为什么是Siamese网络?
传统跟踪方法,比如光流法、相关滤波法,都有各自的短板。光流法对快速运动不友好,相关滤波对形变敏感。而深度学习跟踪,说白了就是让网络学会“相似度比较”。
Siamese网络的核心思想很简单:
- 两个输入:一个模板图像(第一帧的目标),一个搜索图像(当前帧)
- 两个分支:共享权重的特征提取网络
- 一个输出:相似度得分图
嗯,这里要注意:共享权重是关键。如果不共享,那模板和搜索图像的特征空间就不一致,比较就没有意义了。我在项目中遇到过有人把两个分支用不同的预训练权重初始化,结果跟踪器完全跑飞了——这就是典型的“特征空间没对齐”。
4.2 SiamFC:全卷积孪生网络
SiamFC(Fully-Convolutional Siamese Networks)是2016年提出的,可以说是深度学习跟踪的里程碑。它把Siamese网络和全卷积结构结合在了一起。
为什么用全卷积?因为全卷积网络可以接受任意尺寸的输入,而且输出是空间密集的响应图。你想想看,如果输出是一个向量,那只能做全局分类;但输出是一张图,我们就可以知道“目标在哪个位置最像”。
SiamFC的核心流程:
- 模板图像(127×127)经过特征提取网络,得到6×6×128的特征图
- 搜索图像(255×255)经过同样的网络,得到22×22×128的特征图
- 对两个特征图做互相关操作,得到17×17的响应图
- 响应图中最大值的位置,就是目标所在位置
这里有个细节:互相关操作。说白了就是把模板特征当成卷积核,在搜索特征上滑动卷积。这样得到的响应图,每个位置的值就代表了“这个位置和模板的相似度”。
4.3 网络结构详解
SiamFC使用的骨干网络是修改版的AlexNet。我刚开始看论文时觉得“怎么还用AlexNet,太老了吧”。后来发现,对于跟踪任务,轻量级网络反而更好——速度快,而且不容易过拟合。
网络结构如下:
| 层名 | 卷积核 | 步长 | 输出尺寸(模板) | 输出尺寸(搜索) |
|---|---|---|---|---|
| Conv1 | 11×11×96 | 2 | 59×59×96 | 123×123×96 |
| Pool1 | 3×3 | 2 | 29×29×96 | 61×61×96 |
| Conv2 | 5×5×256 | 1 | 25×25×256 | 57×57×256 |
| Pool2 | 3×3 | 2 | 12×12×256 | 28×28×256 |
| Conv3 | 3×3×384 | 1 | 10×10×384 | 26×26×384 |
| Conv4 | 3×3×384 | 1 | 8×8×384 | 24×24×384 |
| Conv5 | 3×3×256 | 1 | 6×6×256 | 22×22×256 |
注意看,模板和搜索图像经过同样的网络,最后得到的特征图尺寸不同。模板是6×6,搜索是22×22。互相关之后得到17×17的响应图。
避坑指南:我曾经在实现SiamFC时,发现响应图尺寸不对。后来排查发现,是模板和搜索图像的输入尺寸比例没算对。记住:模板127×127,搜索255×255,这个比例是设计好的,不要随意改。
4.4 训练策略
SiamFC的训练很有意思。它不是在跟踪数据集上训练的,而是在ImageNet视频数据集上做“相似度学习”。
具体来说:
- 从视频中随机取两帧,一帧作为模板,一帧作为搜索
- 在搜索帧中,目标位置附近标为正样本,远处标为负样本
- 损失函数使用逻辑回归损失(二分类交叉熵)
为什么这样训练?因为跟踪的本质就是“判断每个位置是不是目标”。正样本是目标位置,负样本是背景位置。网络学会了区分目标和背景,自然就能跟踪了。
我记得第一次跑SiamFC训练时,看到损失下降很慢。后来发现是学习率设置的问题。SiamFC原文用的是对数衰减的学习率策略,从10^-2开始,每轮衰减到原来的0.87倍。这个细节很重要,直接影响了收敛速度。
4.5 在线跟踪流程
训练好的SiamFC怎么用?流程很简单:
# 伪代码:SiamFC在线跟踪
def track(initial_frame, bbox, model):
# 裁剪模板图像
template = crop_and_resize(initial_frame, bbox, size=127)
template_feat = model.forward(template)
for frame in video_frames:
# 以上一帧目标位置为中心,裁剪搜索区域
search = crop_and_resize(frame, prev_center, size=255)
search_feat = model.forward(search)
# 互相关得到响应图
response = cross_correlation(template_feat, search_feat)
# 找到响应最大值位置
max_loc = argmax(response)
# 加上尺度惩罚,更新目标位置
scale_factor = 1.02 # 多尺度搜索
best_scale = argmax_scale(response_scales)
# 更新目标位置和尺度
update_bbox(max_loc, best_scale)
这里有个小技巧:多尺度搜索。SiamFC会以1.02的倍数缩放模板,做三次搜索,选响应最大的那个尺度。这样可以应对目标尺寸变化。
注意:SiamFC的尺度适应能力很有限。如果目标快速变大或变小,跟踪器容易漂移。我在做无人机跟踪项目时,目标从远处飞近,尺寸变化很大,SiamFC就经常跟丢。后来加了尺度估计模块才解决。
4.6 SiamFC的优缺点
说实话,SiamFC在今天看来已经不算最先进的了。但它的思想影响了很多后续工作,比如SiamRPN、SiamMask、SiamBAN等。
优点:
- 速度快:全卷积结构,可以端到端训练和推理
- 简单优雅:不需要在线微调,模板只提取一次
- 可解释性强:响应图直观展示了网络关注的位置
缺点:
- 尺度适应差:只能通过多尺度搜索粗略估计
- 对形变敏感:模板固定不变,目标形变后容易跟丢
- 背景干扰:当背景中有相似物体时,响应图会出现多个峰值
嗯,这里要补充一点。SiamFC虽然简单,但它是理解后续所有Siamese跟踪器的基础。你如果能把SiamFC的代码手写一遍,后面的SiamRPN、SiamMask理解起来就轻松多了。
4.7 核心知识图谱
下面这张图展示了SiamFC的核心知识体系,从输入到输出,每一步都环环相扣:
这张图把SiamFC的整个流程串起来了。从左到右看:模板和搜索图像经过共享权重的网络提取特征,然后做互相关得到响应图,最后取最大值位置作为目标位置。整个过程干净利落,没有多余的步骤。
我的建议:如果你想深入理解SiamFC,最好的办法是自己实现一遍。不用太复杂,用PyTorch搭一个简化版,在OTB数据集上跑一跑。我当初就是这么做的,跑通的那一刻,对Siamese跟踪的理解会上一个台阶。
好了,这一章的内容就到这里。SiamFC虽然简单,但它是深度学习跟踪的基石。后面的SiamRPN、SiamMask都是在它的基础上改进的。理解了SiamFC,你就掌握了Siamese跟踪的核心思想。
可可精品资料库