语义分割(Semantic Segmentation)是计算机视觉中的一种图像理解任务:将图像中的每一个像素分配到一个预定义的类别标签,从而实现对图像按语义区域进行像素级划分。其中有一些较强可尝试的模型和方案,可以在对应场景需要时尝试。
SegFormer
SegFormer是一种较为轻量的语义分割模型,他的思路是将传统的CNN分割网络的倒金字塔结构保留,然后引入注意力,这主要是靠MiT实现的。MiT靠Overlap Patch Embedding实现倒金字塔的降分辨率操作,然后使用MiT Transformer Layer进行注意力和FFN,他对注意力和FFN进行了修改,使用Efficient Self-Attention和Mix-FFN。其中Efficient Self-Attention就是将KV进行了降采样,使用带步长的卷积核堆叠,将KV的Token数下降到较低水平,来降低注意力开销。然后是Mix-FFN,他在第一个Linear后加了3x3 Depthwise Convolution来进行局部空间信息交互。一方面这个DWConv在这里提供了局部空间信息交互,另一方面他还提供了一定的Patch空间信息。在SegFormer里面,他还去掉了Attention的位置编码,因为ViT中一般使用的位置编码是绝对位置编码,他不利于扩展输入图片大小,所以他去掉了,而这里的DWConv就补了一定空间信息。
SegFormer的Encoder一般是有四层Layer,分别下采样到1/4、1/8、1/16、1/32。而且其中为了降低注意力的开销的步长卷积堆叠数也会依次降低,因为在Layer中已经进行了下采样,具体为8、4、2、1个Conv。SegFormer的Decoder十分简单,因为Encoder的各个Layer输出会导致特征的channel数不断增大,他的Decoder第一步就是统一各个Layer输出的channel,然后他再统一将各个Layer输出的尺寸upsample到1/4,然后concat之后完全展平,最后直接一个Linear映射到class维进行分类。他的特点就是轻量,因此在Benchmark上分数并不是很高,适合做快速实验以及做Baseline。
graph TD
Image[Input Image] --> MiT
subgraph MiT Encoder
MiT --> L1[Stage 1: 1/4]
L1 --> L2[Stage 2: 1/8]
L2 --> L3[Stage 3: 1/16]
L3 --> L4[Stage 4: 1/32]
end
L1 --> MLP1[MLP]
L2 --> MLP2[MLP]
L3 --> MLP3[MLP]
L4 --> MLP4[MLP]
MLP1 --> Concat[Concat]
MLP2 --> Concat
MLP3 --> Concat
MLP4 --> Concat
Concat --> Linear[Linear Classification]
Linear --> SegMap[Segmentation Map]UPerNet
UPerNet是一种多尺度语义分割Decoder/Head。因此他不是一种具体模型,但是他可以用来作为进阶Decoder使用,接在各种Backbone后。
UPerNet接受像SegFormer那样的分层特征。在最高层特征上,他会进行PPM(Pyramid Pooling Module),使用不同核大小的Mean Pool,例如:
1x12x23x36x6
然后获取对应Pool结果之后再upsample回高层特征的size,然后直接将这些与原始的最高层特征concat,然后用卷积融合进去或者一个与初始的最高层特征的shape相同的特征。PPM能给最高级语义特征增加不同尺度的全局Context。
然后就是FPN。对于上面的最高层语义特征进行PPM获得的产物和其他层的特征,我们对他们分别进行一次channel统一,然后依次将最高层特征与更低一层的特征upsample的结果进行相加,然后用3x3 Conv融合获得新的融合特征,然后让这个新的融合特征与下一层特征相加然后融合,获得各层的融合特征,最后将它们相连之后再进行一次卷积融合,然后用一个Linear层将最后一维映射到class维上。
相比于SegFormer的这种简单的Decoder,UPerNet很适合用来作为下一步,测试Decoder是否是瓶颈项来提升分数。
graph TD
subgraph Backbone
C1[C1: 1/4]
C2[C2: 1/8]
C3[C3: 1/16]
C4[C4: 1/32]
end
C4 --> PPM[PPM]
PPM --> FPN_C4
C3 --> Conv1x1_3[1x1 Conv]
Conv1x1_3 --> FPN_C3
C2 --> Conv1x1_2[1x1 Conv]
Conv1x1_2 --> FPN_C2
C1 --> Conv1x1_1[1x1 Conv]
Conv1x1_1 --> FPN_C1
FPN_C4 --> Up1[Upsample]
Up1 --> Add1((+))
FPN_C3 --> Add1
Add1 --> Conv3x3_3[3x3 Conv]
Conv3x3_3 --> FPN_Out3
FPN_Out3 --> Up2[Upsample]
Up2 --> Add2((+))
FPN_C2 --> Add2
Add2 --> Conv3x3_2[3x3 Conv]
Conv3x3_2 --> FPN_Out2
FPN_Out2 --> Up3[Upsample]
Up3 --> Add3((+))
FPN_C1 --> Add3
Add3 --> Conv3x3_1[3x3 Conv]
Conv3x3_1 --> FPN_Out1
FPN_Out1 --> Up4[Upsample to 1/4]
FPN_Out2 --> Up5[Upsample to 1/4]
FPN_Out3 --> Up6[Upsample to 1/4]
FPN_C4 --> Up7[Upsample to 1/4]
Up4 --> Concat[Concat]
Up5 --> Concat
Up6 --> Concat
Up7 --> Concat
Concat --> FinalConv[Conv + Linear]
FinalConv --> Pred[Prediction]Mask2Former
Mask2Former也是一种分割Decoder,他统一了语义分割、实例分割、全景分割。它由Backbone Encoder,Pixel Decoder还有Transformer Decoder。他对Encoder的要求与上面的其他的分割头一样,要求输出多层特征,典型层次还是1/4、1/8、1/16、1/32,然后这些分层特征会先经过Pixel Decoder。
其中1/8、1/16、1/32会进入到一个分支,1/4进入另一个分支。对于前三个,他们进行1x1 Conv将channel统一到256之后加入2D Position Embedding和Learnable Level Embedding然后将他们展平都作为Token,然后进入6层MSDeformAttn(Multi-Scale Deformable Attention)。这里并非Transformer式的Attn,而是一种独特的方式来降低消耗。对于每个Query Token,他对每个注意力Head,每个Level,采样4个Token进行注意力计算,因此需要 个位置信息,他通过一个Linear,将每个Token的256映射出对应需要的维度,这里的2指的是他的2D位置信息。当位置信息非标准Token位置的时候,他并非舍入,而是用附近的Token双线性插值来解决,同时在这套操作中他给每个Token的2D位置都加了0.5,来表示每个Patch的中心位置。获取了这些Sample Offsets之后,他还要获取对于每个Token的Attention Weights,同样通过Linear映射出来。然后进行注意力计算。
其中 正是Sample Offsets,而 就是进行了Softmax保证权重总和为1,这里的 正是双线性插值。他的最后输出就是通过Split将Level和Size维度恢复回来的特征,这些Level和Size信息在他一开始Flatten之前就存储了。
然后其中1/4的分支,也先用1x1 Conv,让他的channel变成256,然后将上面的这里的MSDeformAttn输出的1/8特征上采样到1/4,然后与上层特征相加,然后用3x3 Conv结合,然后再经过一个1x1 Conv保证输出的channel为256,最后就获得了Mask Feature。
然后是Transformer Decoder,他有100个可学习的Query Feature和100个可学习的Query Embedding,第一层对Query Feature进行LayerNorm之后通过一个三层MLP得到每个Query的256维嵌入,然后与Pixel Decoder的Mask Feature进行内积获得100个Query各自的Mask,然后按照这一层要Query的层次特征进行Mask Bilinear Interpolation Resize到对应Size,然后以0.5为阈值进行Mask构建。然后他就开始计算Mask Attention,原本说的Query Embedding就会加在Q上,K就是层次特征加上位置信息,V就是层次特征,并且加上上面的Mask,然后再接上标准Attention和FFN,然后就到了下一层。经过上一层信息交互的Query Feature再次构建Mask,只不过这次的要Query的层次特征变成了更底层的那一个,即1/32、1/16、1/8这样每层被Query。然后他的Class Head就是取每层后的Query Feature进行预测,对每个Query预测一个Class,并用3层MLP预测对应的Mask。再加上一般他会让第一层之前还没做交互的Query Feature进行一次预测,也就是 Layer+1 次预测,一般是10次,也就是9层,意味着这些层次特征一般会被Query 3次。最后取真的预测Mask的时候,他只用最后一层的预测。在推理阶段,对于每个像素,将每个Query预测的类别概率与其对应的Mask概率相乘,得到每个类别在该像素上的得分,然后将所有Query对同一类别的贡献求和,最后取得分最大的类别作为该像素的最终预测。
Mask2Former的分割效果一般强于UPerNet,通过和较强的Backbone组合,他能达到分割的SOTA水平,例如与DINOv2和他的Adapter结合,即使冻结DINO,也能达到SOTA,或者与Swin Transformer等等结合等,也能获得很好的效果。
graph TD
subgraph Backbone
C1[1/4]
C2[1/8]
C3[1/16]
C4[1/32]
end
subgraph Pixel Decoder
C2 --> Enc[MSDeformAttn x6]
C3 --> Enc
C4 --> Enc
Enc -->|仅 1/8 层| Up1[Upsample to 1/4]
C1 --> Lat[1x1 Conv]
Lat --> Add((+))
Up1 --> Add
Add --> Fuse[3x3 Conv + 1x1 Conv]
Fuse --> MaskFeat[Mask Features]
end
subgraph Transformer Decoder
Q[100 Learnable Queries] --> MLP[3层 MLP]
MLP --> Dot((与 Mask Features 内积))
MaskFeat --> Dot
Dot --> Mask[Mask, 0.5 二值化]
Mask -->|作为 attention mask| MCA[Masked Cross-Attention]
Enc -->|K/V, 轮流 query 1/32, 1/16, 1/8| MCA
MCA --> FFN[Self-Attention + FFN]
FFN --> Q
end
Q --> ClassHead[Class Head]
Q --> MaskHead[Mask Head]
MaskFeat --> MaskHead
MaskHead --> Pred[最终 Mask 预测]