4. 深度学习跟踪入门:Siamese网络基础、SiamFC全卷积孪生网络

说到目标跟踪,很多人第一反应是“这不就是检测嘛”。其实不然。检测是每帧独立找目标,跟踪则要解决“目标长什么样、跑到哪去了”这两个问题。而深度学习时代,Siamese网络的出现,让跟踪这件事变得优雅了很多。

我个人最早接触Siamese网络是在做行人重识别的时候。那时候觉得“两个分支共享权重”这个设计很巧妙。后来发现,这个结构简直就是为跟踪量身定做的——你想想看,跟踪不就是“第一帧给个模板,后续帧去找最像的地方”吗?

4.1 为什么是Siamese网络?

传统跟踪方法,比如光流法、相关滤波法,都有各自的短板。光流法对快速运动不友好,相关滤波对形变敏感。而深度学习跟踪,说白了就是让网络学会“相似度比较”。

Siamese网络的核心思想很简单:

  • 两个输入:一个模板图像(第一帧的目标),一个搜索图像(当前帧)
  • 两个分支:共享权重的特征提取网络
  • 一个输出:相似度得分图

嗯,这里要注意:共享权重是关键。如果不共享,那模板和搜索图像的特征空间就不一致,比较就没有意义了。我在项目中遇到过有人把两个分支用不同的预训练权重初始化,结果跟踪器完全跑飞了——这就是典型的“特征空间没对齐”。

4.2 SiamFC:全卷积孪生网络

SiamFC(Fully-Convolutional Siamese Networks)是2016年提出的,可以说是深度学习跟踪的里程碑。它把Siamese网络和全卷积结构结合在了一起。

为什么用全卷积?因为全卷积网络可以接受任意尺寸的输入,而且输出是空间密集的响应图。你想想看,如果输出是一个向量,那只能做全局分类;但输出是一张图,我们就可以知道“目标在哪个位置最像”。

SiamFC的核心流程:

  1. 模板图像(127×127)经过特征提取网络,得到6×6×128的特征图
  2. 搜索图像(255×255)经过同样的网络,得到22×22×128的特征图
  3. 对两个特征图做互相关操作,得到17×17的响应图
  4. 响应图中最大值的位置,就是目标所在位置

这里有个细节:互相关操作。说白了就是把模板特征当成卷积核,在搜索特征上滑动卷积。这样得到的响应图,每个位置的值就代表了“这个位置和模板的相似度”。

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全卷积孪生网络知识体系 模板图像 127×127×3 搜索图像 255×255×3 共享权重 AlexNet骨干网络 模板特征 6×6×256 搜索特征 22×22×256 互相关操作 模板特征作为卷积核,在搜索特征上滑动 响应图 17×17,每个位置代表相似度得分 目标位置:响应最大值处 训练:逻辑回归损失 推理:argmax定位

这张图把SiamFC的整个流程串起来了。从左到右看:模板和搜索图像经过共享权重的网络提取特征,然后做互相关得到响应图,最后取最大值位置作为目标位置。整个过程干净利落,没有多余的步骤。

我的建议:如果你想深入理解SiamFC,最好的办法是自己实现一遍。不用太复杂,用PyTorch搭一个简化版,在OTB数据集上跑一跑。我当初就是这么做的,跑通的那一刻,对Siamese跟踪的理解会上一个台阶。

好了,这一章的内容就到这里。SiamFC虽然简单,但它是深度学习跟踪的基石。后面的SiamRPN、SiamMask都是在它的基础上改进的。理解了SiamFC,你就掌握了Siamese跟踪的核心思想。

可可精品资料库