【语义分割】从架构演进到实战选型:12个核心模型解析、数据集实践与前沿趋势
1. 语义分割:从“像素涂色”到“场景理解”的进化之路
如果你玩过给黑白线稿上色的游戏,或者用过Photoshop里的“魔棒”工具,那你对“分割”这个概念就不陌生。简单说,就是把图片里不同的东西用不同颜色标出来。而语义分割,就是这个游戏的“终极智能版”。它的任务,是让计算机像我们人眼一样,不仅能看出图片里哪里是猫、哪里是狗,还能精确到每一个像素点,给它们都打上正确的标签:“这是猫的耳朵像素”,“那是狗尾巴的像素”。
听起来好像只是高级一点的“涂色”?其实远不止。我干了这么多年AI项目,从早期的医疗影像分析到现在的自动驾驶感知模块,语义分割都是底层核心的“眼睛”。在自动驾驶里,它要实时分辨出路上的每一个像素是属于车道线、车辆、行人还是路沿,差一个像素可能就是事故;在医疗领域,它要从CT片里精准勾勒出肿瘤的边界,帮助医生制定手术方案,多切或少切一毫米都关乎生命。
所以,为什么我们需要研究这么多不同的模型架构?因为现实世界太复杂了。一张城市街景图,里面有远处模糊的招牌、近处清晰的车辆、被遮挡一半的行人、反光的地面……没有一种“万能”的模型能通吃所有场景。有的场景要求速度(比如手机上的实时滤镜),有的追求极致的精度(比如卫星影像分析),有的则数据稀少(比如某些罕见病的病理切片)。这就好比木匠的工具箱,你不能指望一把锤子搞定所有活,得有锯子、刨子、凿子,针对不同的木头和工艺,选用最趁手的家伙。
接下来,我就带你沿着技术演进的时间线,看看这十年来,研究者们是如何一步步打造出这个“工具箱”里的12件核心利器。我们会从最经典的U-Net讲起,一直聊到最新的基于Transformer的“新贵”,并结合一个真实的数据集,手把手带你看看它们在实际任务中的表现到底如何,最后聊聊当标签数据不够时,我们还有哪些前沿“黑科技”可以用。
2. 编码-解码的基石:CNN时代的传承与精进
如果把语义分割模型比作建房子,那么编码器-解码器(Encoder-Decoder) 就是最经典、最可靠的地基和房型设计。编码器负责“理解”图像,像压缩包一样把图片信息提炼成高度抽象的特征;解码器则负责“还原”,把这些抽象特征再变回一张张细致的分割图。这个思想,贯穿了早期绝大多数模型的演进。
2.1 开山鼻祖:U-Net与它的“对称美学”
时间回到2015年,医学图像分析领域正急需一种能精准分割细胞、器官的算法。传统的CNN分类网络(比如VGG)虽然特征提取能力强,但经过层层下采样(池化),图片分辨率变得极低,细节全丢了——这好比把一张高清地图不断折叠,最后只剩一个小点,你当然找不到具体的街道。
U-Net 的提出,完美解决了这个问题。它的结构如其名,像一个英文字母“U”。左边是编码器,通过卷积和池化一路“下采样”,提取特征;右边是解码器,通过转置卷积(Transposed Convolution) 一路“上采样”,恢复尺寸。但最妙的是中间那几条“跳跃连接”(Skip Connection),它把编码器每一层的高分辨率特征图(包含很多细节信息,比如边缘),直接拷贝、拼接到解码器对应的层。
我最早用U-Net是在一个工业瑕疵检测项目上。产品表面的划痕、污点非常细微。当时试过直接用分类网络的特征图去预测,效果很差,边界模糊。换成U-Net后,因为跳跃连接把浅层的边缘细节传递到了深层,模型能清晰地勾勒出瑕疵的边界,效果立竿见影。它的代码实现也异常简单,用PyTorch几十行就能搭出来,这让它迅速成为众多研究和工业项目的首选基线模型。
# 一个简化的U-Net跳跃连接核心代码示意(PyTorch风格)
class UNetBlock(nn.Module):
def __init__(self, in_channels, out_channels):
super().__init__()
self.conv = nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),
nn.ReLU(inplace=True)
)
def forward(self, x):
return self.conv(x)
# 在下采样(编码)过程中,我们需要保存特征图供跳跃连接使用
encoder_features = []
for block in encoder_blocks:
x = block(x)
encoder_features.append(x) # 保存特征
x = nn.MaxPool2d(2)(x) # 下采样
# 在上采样(解码)过程中,融合之前保存的特征
for i, block in enumerate(decoder_blocks):
x = nn.ConvTranspose2d(...)(x) # 上采样
# 将编码器对应层的特征与当前特征在通道维度拼接(concat)
x = torch.cat([x, encoder_features[-(i+1)]], dim=1)
x = block(x)
2.2 效率探索:SegNet与PSPNet的差异化思路
U-Net火了之后,大家开始思考:跳跃连接需要保存大量的特征图,非常消耗内存,尤其是在处理高分辨率图像时。2016年的 SegNet 提出了一个巧妙的思路:记录池化索引(Pooling Indices)。它在编码器进行最大池化时,不光输出池化后的值,还记录每个最大值在原图中的位置。在解码器进行反池化(Unpooling) 时,根据这些索引把值放回原位,再用卷积细化。这样就不需要存储整个特征图,大大节省了内存。我在一些嵌入式设备(如 Jetson Nano)上部署模型时,SegNet这种设计对内存受限的场景非常友好。
但SegNet在恢复细节上有时不如U-Net,因为索引只记录了位置,丢失了部分特征值信息。与此同时,另一个问题凸显出来:物体尺度多变。一张图里可能有近处的大车和远处的小车。2017年的 PSPNet 给出了“金字塔”解决方案。它在主干网络提取特征后,接了一个金字塔池化模块(Pyramid Pooling Module, PPM)。这个模块并行地对特征图进行不同尺度的全局平均池化(比如1x1, 2x2, 3x3, 6x6),得到不同区域的上下文信息,然后再上采样、拼接回原特征。这就好比你先看整张图的概貌(全局上下文),再看分成4块、9块、36块后的局部概貌,最后综合所有这些信息来判断每个像素的类别,对于理解“车”无论大小都很有帮助。
2.3 连接革命:UNet++与DeepLabv3+的深度优化
到了2018年,大家不满足于简单的U型结构,开始在“连接”上做文章。UNet++ 可以看作是U-Net的“豪华升级版”。它借鉴了DenseNet的思想,在编码器和解码器之间建立了密集的跳跃连接。不再是U-Net那样一对一的连接,而是每一层解码器都接收来自所有更浅层编码器的特征输入,形成了一个密集连接的网络。这种设计让梯度流动更顺畅,特征融合更充分。我试过在细胞核分割任务上,UNet++通常能比U-Net提升1-2个百分点的IoU(交并比,分割常用指标),但代价是网络更复杂,训练速度稍慢。
同年,谷歌的 DeepLabv3+ 则代表了另一条优化路径:空洞卷积(Atrous Convolution)与空间金字塔池化。它的核心是空洞空间金字塔池化(ASPP)模块。这个模块用不同膨胀率的空洞卷积并行处理特征图,相当于用多个不同“视野”的镜头同时观察特征,既能捕捉近距离细节(小膨胀率),又能获取远距离上下文(大膨胀率),完美解决了多尺度物体问题。DeepLabv3+还改进了解码器,融合了更底层的特征来恢复边缘。在实际应用中,尤其是街景、室内场景分割,DeepLabv3+的表现非常稳健,成为了许多竞赛和商业项目的首选。
2.4 高分辨率之道:HRNet家族的坚持
前面提到的模型,编码器大多是一路“下采样”的,高分辨率细节在早期就丢失了,后续再靠解码器“回忆”和恢复,总有些失真。2019年提出的 HRNet 反其道而行之,它整个网络过程始终保持高分辨率表征。你可以把它想象成多条并行的流水线,一条处理原图分辨率,一条处理1/2分辨率,一条处理1/4分辨率……这些流水线之间不断进行信息交换和融合。这样,高分辨率分支始终保有丰富的细节,低分辨率分支则提供了良好的语义上下文。
我曾在一个人体姿态估计项目中使用HRNet,其关键点定位精度明显优于先下采样再上采样的网络。在语义分割任务中,HRNet对于边缘精细、结构复杂的类别(如自行车辐条、栅栏)分割效果更好。后续的 HRNet-OCR 在HRNet多分辨率特征的基础上,引入了物体上下文表征(OCR) 模块。这个模块会先粗略估计每个像素属于哪个“物体区域”,然后聚合同一区域内所有像素的特征来增强每个像素的表征。这有点像“物以类聚”,让模型在判断一个像素时,不仅看它自己,还看它所在的整个物体区域的特征,使得分割结果在物体内部更一致。
3. 视觉Transformer的冲击:从SETR到SegFormer的范式转变
当自然语言处理领域被Transformer统治时,计算机视觉的研究者也在思考:CNN的局部归纳偏置(认为相邻像素关联性强)固然有效,但会不会也限制了模型建立长距离依赖的能力?2020年,Vision Transformer (ViT) 证明,将图像切块后直接送入Transformer,在大规模数据上预训练后,能在图像分类上媲美甚至超越CNN。语义分割领域也随之迎来了一场“Transformer革命”。
3.1 破局者:SETR的纯Transformer尝试
2021年的 SETR 是第一个用纯Transformer做语义分割编码器的模型。它彻底抛弃了CNN,把图像切成一个个16x16的图块,拉直成序列,然后送入标准的Transformer Encoder进行编码。解码器则采用一个简单的CNN来上采样恢复分辨率。
我复现SETR时感受最深的是其巨大的感受野。由于Self-Attention机制,每个图块在理论上都能与图像上任何位置的图块建立联系,这对于理解“天空”与“远山”、“马路”与“车流”这种大范围上下文关系非常有利。在一些场景宏大的遥感图像分割任务中,SETR表现出了潜力。但它的缺点也很明显:计算量极大。将图像视为序列,序列长度是图块数量的平方级,对高分辨率图像极其不友好。此外,完全抛弃CNN,也意味着失去了对图像局部性、平移不变性的先天归纳偏置,需要海量数据才能训练好。
3.2 优雅的平衡:Swin-UNet与SegFormer
既然纯Transformer有缺陷,那么结合CNN和Transformer优点,或者设计更高效的Transformer就成了方向。Swin-UNet 采用了 Swin Transformer 作为主干。Swin Transformer的核心是滑动窗口(Shifted Window) 自注意力。它把自注意力计算限制在一个个局部窗口内,大幅降低了计算复杂度,同时通过层与层之间窗口的移动,实现了跨窗口的信息传递。Swin-UNet用Swin Transformer构建了一个U型对称结构,形成了“Transformer版的U-Net”。它在保持全局建模能力的同时,效率比SETR高很多,在多个医学图像分割基准上取得了SOTA(当时最佳)效果。
而我认为在实用化道路上走得更远的是 SegFormer。它的设计非常巧妙:
- 重叠图块嵌入:不像ViT那样切分独立的图块,而是用有重叠的卷积方式进行嵌入,更好地保持了局部连续性。
- 分层Transformer编码器:输出多尺度特征图(类似CNN的金字塔特征),无需复杂的解码器。
- 轻量级MLP解码器:仅用多层感知机(MLP)就能融合多尺度特征并预测分割图。因为编码器感受野足够大,解码器无需设计得很复杂。
SegFormer在精度和速度上取得了极佳的平衡。我在部署一个道路场景分割模型到边缘计算设备时,对比了多个模型,SegFormer(MiT-B2 backbone)在保持高精度的同时,推理速度比同精度的DeepLabv3+(ResNet-101)快了近40%,参数量也更少,非常适合对实时性有要求的应用。
3.3 卷积的复兴:SegNeXt的反思
就在大家以为Transformer要一统天下时,2022年的 SegNeXt 发出了不同的声音:卷积注意力比自注意力更有效? SegNeXt的核心是一个新颖的多尺度卷积注意力(MSCA)模块。它使用不同空洞率的深度可分离卷积来捕获多尺度上下文,再用1x1卷积进行通道交互。整个模型没有使用任何Transformer中的自注意力。
这个工作给我的启发是,不要盲目追逐热点。Transformer的自注意力机制强大,但计算复杂,且需要精心设计位置编码。而经过精心设计的卷积模块,同样可以高效地融合多尺度上下文信息。SegNeXt在多个标准数据集上超越了当时的Transformer模型,这提醒我们,在工程选型时,简单、稳定、高效的卷积结构依然具有强大的生命力,尤其是在数据量不是特别巨大,或者对推理效率要求极高的场景下。
4. 实战!用CeyMo数据集评测主流模型
理论说得再多,不如实际跑一跑。为了让大家对这些模型有更直观的感受,我选取了一个公开的、易于上手的道路标记数据集 CeyMo Dataset 进行实测。这个数据集包含了各种天气和光照条件下的道路图像,标注了11种道路标记。为了方便快速实验和对比,我将其处理成了二分类任务(道路标记 vs 背景)。
我在TensorFlow 2.0环境下,使用相同的训练策略(数据增强、学习率、迭代轮数),测试了从U-Net到SegNeXt的多个代表性模型。以下是部分模型在测试集上的性能对比:
| 模型 | 参数量 (M) | GFLOPs | F1-Score (%) | mIoU (%) | 推理速度 (FPS) * |
|---|---|---|---|---|---|
| U-Net | 31.0 | 252 | 91.00 | 82.81 | 45 |
| DeepLabv3+ (ResNet-50) | 39.8 | 457 | 89.96 | 81.12 | 28 |
| PSPNet (ResNet-50) | 46.7 | 412 | 88.10 | 78.15 | 32 |
| HRNetV2-W48 | 65.9 | 696 | 86.36 | 75.46 | 18 |
| SegFormer (MiT-B2) | 27.5 | 62 | 88.91 | 79.43 | 62 |
| SegNeXt (Tiny) | 13.9 | 180 | 90.29 | 82.98 | 48 |
注:推理速度在单张NVIDIA V100 GPU上测试,输入尺寸为512x512。
从结果中我们能读出什么?
- 经典依然能打:U-Net在这个任务上表现非常出色,F1和mIoU都名列前茅,而且结构简单,推理速度快。这印证了其作为基线的强大鲁棒性。
- 精度与速度的权衡:DeepLabv3+和PSPNet精度稍低,但参数量和计算量更大,速度慢一些。它们的优势在于更复杂的多尺度上下文建模,可能在物体尺度变化更大的场景(如Cityscapes)中更有优势。
- HRNet的代价:HRNet保持了高分辨率,但带来了巨大的计算开销(GFLOPs最高),导致推理速度最慢。它更适合对精度要求极高、且对实时性不敏感的任务,如医学影像分析。
- 新架构的优势:SegFormer 在参数量和计算量上具有压倒性优势,速度最快,同时保持了不错的精度(79.43 mIoU)。这体现了Transformer架构在效率上的潜力。SegNeXt 则展示了卷积的优化方向,以较小的模型尺寸取得了最佳的精度(82.98 mIoU),速度也很快。
给新手的实操建议: 如果你想在自己的数据集上快速验证,我的建议是:
- 第一步,无脑用U-Net:它实现简单,训练稳定,是完美的基线。跑通整个流程,建立一个性能基准。
- 第二步,根据需求选型:
- 追求极致精度,且资源充足:尝试 HRNet 或 DeepLabv3+ 配合更强的Backbone(如ResNet-101)。
- 追求最佳速度-精度平衡:SegFormer 是当前非常热门和实用的选择。
- 追求模型轻量化:考虑 SegNeXt 的小型变体,或者使用 DeepLabv3+ 搭配 MobileNetV3 作为Backbone。
- 第三步,魔改与调优:在基线模型上,加入注意力模块(如SE、CBAM)、尝试不同的损失函数(如Dice Loss, Focal Loss)、使用更激进的数据增强,往往能带来比换模型更显著的提升。
5. 面向不同场景的模型选型与改造指南
看了这么多模型和评测,到底该怎么选?这里我结合自己的项目经验,给出一些场景化的选型建议和简单的改造思路。
5.1 自动驾驶场景:实时性与精度的钢丝绳
自动驾驶的感知模块需要在毫秒级内完成分割。速度是第一生命线,但同时不能容忍关键物体(行人、车辆)的漏检。
- 选型推荐:SegFormer、BiSeNet(另一个专为实时分割设计的网络)、轻量级 DeepLabv3+(Backbone用MobileNetV2/V3)。
- 改造技巧:
- 输入分辨率:不要盲目使用高分辨率(如1024x2048)。可以尝试降至512x1024甚至更低,用速度换精度损失,通常损失不大但速度提升明显。
- 知识蒸馏:用一个大型复杂模型(教师模型)指导一个小型轻量模型(学生模型)训练,让小模型获得接近大模型的性能。
- 注意力机制:在解码器或跳跃连接处添加轻量级注意力模块(如坐标注意力CA),让模型更关注道路、障碍物等关键区域,抑制天空、植被等背景干扰。
5.2 医学影像分析:当精度关乎生命
在分割肿瘤、血管、细胞时,精度是绝对核心,尤其是边界的分割精度,直接影响到诊断和手术规划。对速度要求相对宽松。
- 选型推荐:U-Net及其变体(UNet++, UNet3+)、Swin-UNet、HRNet。医学图像往往对比度低、边界模糊,U-Net系列的跳跃连接能很好地保留细节。
- 改造技巧:
- 深度监督:在解码器的中间层也添加辅助损失函数,让浅层网络也能学到有效的特征,加速训练并提升性能。
- 混合损失函数:交叉熵损失(CE)对像素分类敏感,但可能对边界不友好。结合 Dice Loss 或 Boundary Loss,可以强制模型优化物体内部区域的连续性和边界的准确性。
- 预处理与后处理:针对医学图像特点,加强对比度拉伸、直方图均衡化等预处理;分割后使用连通域分析等后处理去除小噪点。
5.3 遥感与地理信息:处理“大场面”与多尺度
遥感图像尺寸巨大,地物尺度差异悬殊(从小型车辆到大型建筑群),且类别不平衡问题严重。
- 选型推荐:DeepLabv3+、PSPNet、SETR(如果算力允许)。它们的多尺度上下文聚合能力(ASPP, PPM, 全局注意力)对于理解广袤场景至关重要。
- 改造技巧:
- 多尺度训练/测试:训练时随机缩放输入图像;测试时使用多尺度输入并融合结果(TTA),能显著提升模型对不同尺度物体的鲁棒性。
- 针对类别不平衡:使用 Focal Loss 或为不同类别设置不同的损失权重,让模型更关注那些样本数少的稀有类别。
- 滑动窗口推理:对于超大图像,无法一次性输入网络。需要采用重叠的滑动窗口进行预测,并对重叠区域的结果进行融合(如取平均、取最大值)以避免接缝。
6. 前沿趋势:当标签数据不再“奢侈”
我们上面讨论的所有模型,都严重依赖大量精准标注的数据。但现实中,标注成本极高。医学图像需要医生逐像素勾勒,遥感图像需要专业解译,工业缺陷数据更是稀少。如何用更少的标签,甚至无标签数据训练出好模型?这是当前最前沿的方向。
自监督学习(Self-Supervised Learning, SSL) 是解决之道。它的核心思想是:让模型从数据本身构造监督信号进行预训练,学习到强大的通用视觉特征,然后再用少量标注数据在下游任务(如分割)上进行微调。
目前主流的方法有:
- 掩码图像建模(Masked Image Modeling, MIM):借鉴BERT,随机遮盖图像的部分块,让模型预测被遮盖部分。MAE、SimMIM等方法都属于此类。经过MIM预训练的模型,对图像内容、结构有了深刻理解,初始化分割网络编码器后,微调效果极佳。我尝试过用MAE预训练的ViT作为SETR的编码器,在仅使用10%标注数据的情况下,达到了原来用100%数据训练效果的90%以上。
- 对比学习(Contrastive Learning):让模型学会区分“相似”与“不相似”的样本。对同一张图像做两次不同的数据增强(裁剪、变色等),得到两个视图,它们在特征空间里应该很接近;而不同图像的视图则应该远离。MoCo、SimCLR是代表作。学到的特征同样可以迁移到分割任务。
半监督学习(Semi-Supervised Learning) 则是同时利用少量标注数据和大量无标注数据。常用方法如 FixMatch,对弱增强的标注数据计算有监督损失,对强增强的无标注数据,当模型预测置信度高时,将其伪标签(Pseudo-label)作为监督信号。这相当于让模型自己从无标注数据中“挖矿”。
在实际项目中,我的策略通常是“自监督预训练 + 半监督微调”:
- 收集领域内所有图像(无需标注),用MAE等方法进行自监督预训练,得到一个强大的特征提取器。
- 用这个预训练模型初始化分割网络(如U-Net的编码器)。
- 利用手头少量的标注数据和大量的无标注数据,进行半监督微调。
这条路子能极大地降低对标注数据的依赖,尤其是在医疗、工业等专业领域,效果提升非常明显。未来,如何设计更适合分割任务的预训练目标,如何更高效地利用无标注数据,仍然是研究的热点和工程落地的关键。
更多推荐
所有评论(0)