目前语义分割的方法中,主要是以FCN为主导的一系列基于encoder-decoder的方法,但这类方法在捕捉long-range信息上的能力较弱:
本文方法:
1、将图片转化成序列化的patch:
将 x ∈ R H × W × 3 x\in R^{H\times W \times 3} x∈RH×W×3 切分成统一大小的 H 16 × W 16 \frac{H}{16} \times \frac{W}{16} 16H×16W,然后将这些patch拉平
2、线性投影: f : p → e ∈ R C f : p \to e \in R^C f:p→e∈RC
使用线性投影 f 将 patch 映射到一个 C 维的 embedding space,于是就从一个2维的图像得到了一个一维的序列
3、位置编码:
为了对每个patch的空间信息编码,作者给每个位置 i i i上的 patch 学习了一个特殊的位置编码 p i p_i pi,加到 e i e_i ei 上,来得到最终的输入 E = e 1 + p 1 , e 2 + p 2 , . . . , e l + p l E = {e_1+p_1, e_2+p_2,...,e_l+p_l} E=e1+p1,e2+p2,...,el+pl
4、Transformer:
Transformer 使用上述得到的 E 作为输入,则意味着其可以获得全局的感受野,解决 FCN 等方法感受野有限的问题。
Decoder的作用:生成和原图大小一致的2维分割结果
所以,这里需要把 encoder 的特征 Z 从 H W 256 \frac{HW}{256} 256HW reshape 成 H 16 × W 16 × C \frac{H}{16} \times \frac{W}{16} \times {C} 16H×16W×C。
方法一:Naive upsampling (Naive)
① 将transformer得到的特征 Z L e Z^{L_e} ZLe 映射到分割类别数(如cityscape就是19)
1x1 conv + sync batch norm (with relu) + 1x1 conv
② 使用双线性插值进行上采样,然后计算loss
方法二:Progressive UPsampling (PUP)
使用渐进上采样,使用卷积核上采样交替变换来实现,为了避免直接上采样多倍带来的误差,这个上采样方法每次只上采样2倍,也就是说如果要把大小为 H 16 × W 16 \frac{H}{16} \times \frac{W}{16} 16H×16W 的 Z L e Z^{L_e} ZLe 上采样到原图大小,需要进行4次操作。
方法三:Multi-Level feature Aggregation(MLA)
使用多层特征聚合,也就是将跨层分布的特征 { Z m } ( m ∈ { L e m , 2 L e m , . . . , M L e m } ) \{Z^m\} (m \in \{\frac{L_e}{m}, 2\frac{L_e}{m},..., M\frac{L_e}{m}\}) {Zm}(m∈{mLe,2mLe,...,MmLe}) 作为输入(间隔步长为 L e m \frac{L_e}{m} mLe),输入到decoder中。
之后,部署了M个流(stream),每个着重注意一个layer,每个流内:
5、Auxiliary loss:
每个 auxiliary loss 后面都跟一个 2 层的网络,作者在以下不同的 transformer layers 都加了 auxiliary loss:
在 ADE20K 和 Pascal VOC 的效果对比:
代码路径:https://github.com/fudan-zvg/SETR
框架:mmsegmentation
# 1、source 环境
source activate mmsegmentation
# 2、编译库路径
python setup develop.py
# config 文件
configs/SETR/
configs/_base_/dataset/cityscapes/py