分类给整图一个标签,检测给物体画框,分割做到最细:给每个像素分配类别。医学影像勾画肿瘤区域、自动驾驶理解可行驶区域、证件照抠背景,都是分割的活。这篇把三类分割分清,并从传统方法讲到 U-Net 实战。
前置阅读:深度学习课程 04:CNN、OpenCV 轮廓处理。
三种分割,三种难度
- 语义分割:每个像素分类别,不区分同类个体——图里三只羊,所有”羊像素”都是同一类。
- 实例分割:区分同类个体——三只羊各自一个掩码(Mask R-CNN 是代表)。
- 全景分割:两者结合——可数物体做实例分割,背景(天空、道路)做语义分割。
入门主线先攻语义分割:U-Net 一座大山翻过去,实例/全景都是它的延伸。
传统方法:什么时候够用
不用深度学习的场景比想象中多——前景背景对比强、形态规则的任务,OpenCV 经典方法快速可解释:
import cv2
img = cv2.imread("cells.png", 0)
# Otsu 自动阈值:找类间方差最大的分割点
_, binary = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 形态学清理:开运算去噪点,闭运算补空洞
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
clean = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)
# 分水岭:分离粘连的个体(细胞计数经典场景)
阈值法(Otsu、自适应阈值)+ 形态学 + 分水岭这条传统管线,在工业质检、细胞计数等背景可控的场景至今是主力——背景可控就先试传统方法,半小时出结果;背景复杂、类别语义丰富的才需要深度模型。
U-Net:分割领域的 ResNet
U-Net 2015 年为医学影像设计,至今仍是分割任务的第一基线。结构如其名,一个 U 形:
- 编码器(左半边):卷积 + 池化逐步下采样,提取语义(“是什么”)——就是普通 CNN 主干。
- 解码器(右半边):逐步上采样恢复分辨率,还原空间细节(“在哪里”)。
- 跳跃连接(灵魂):把编码器每一层的特征直接拼到解码器对应层——深层有语义、浅层有细节,拼接后两者兼得。没有跳跃连接,上采样恢复的边界全是糊的。
输出通道数 = 类别数,每个像素位置是一个小的分类问题。损失常用交叉熵 + Dice loss(分割专用,衡量掩码重叠度,对前景占比小的任务友好)。
# 用 segmentation_models_pytorch 三行起一个 U-Net
# pip install segmentation-models-pytorch
import segmentation_models_pytorch as smp
model = smp.Unet(
encoder_name="resnet34", # 编码器用预训练主干,小数据友好
encoder_weights="imagenet",
in_channels=3,
classes=2, # 前景/背景
)
# 训练循环与分类任务相同,只是标签从"一个数"变成"一张掩码图"
评估:IoU 与 Dice
先说明指标按单图平均还是按全数据像素汇总,背景是否参与平均,以及没有前景的图片怎样处理。几张大面积前景图片可能掩盖小目标的失败;总分之外,应单独查看小区域、边界和空前景样本。
分割不看准确率(背景像素占 95% 时全猜背景也 95 分),看:
- IoU(预测掩码与真值的交并比):和检测篇的 IoU 同概念,像素级版本。
- Dice 系数:,医学影像的标准指标,和 IoU 单调相关。
小目标任务(肿瘤占画面 1%)要特别报告前景类的 IoU,整体平均会掩盖前景全漏的惨剧——这和分类任务”类别不均衡看宏 F1”是同一个道理。
数据:分割最贵的部分
分割标注是像素级描边,成本是分类标注的几十倍。应对策略按性价比排序:
- 预训练编码器 + 小数据微调:U-Net 配 ImageNet 主干,几百张标注常常够用。
- 强数据增广:弹性形变(医学影像标配)、旋转翻转、色彩抖动——掩码要同步变换。
- 弱监督/半自动:用传统方法或 SAM(Segment Anything)预标注,人工修正。
踩坑排查
| 症状 | 原因 | 处理 |
|---|---|---|
| 预测全是背景 | 类别极度不均衡 | Dice/focal loss;看前景 IoU |
| 边界锯齿模糊 | 跳跃连接缺失/上采样粗糙 | 检查 U 形结构完整性 |
| 掩码和图像错位 | 增广时只变了图没变掩码 | 用 albumentations 同步变换 |
| 小数据全崩 | 编码器从头训练 | ImageNet 预训练主干 |
| 推理结果有色偏块 | 归一化参数和训练不一致 | 统一预处理 |
| 大图像爆显存 | 整图直接进网络 | 滑窗切片 + 重叠融合 |
练习
- 用 Otsu + 形态学完成一个前景背景分明的分割,计算 IoU。
- 用 smp 的 U-Net 在公开医学数据集上微调,报告前景 Dice。
- 消融跳跃连接(改纯编解码),对比边界质量。
- 实现滑窗推理 + 重叠区域融合,处理一张 4K 大图。
面试常问
Q:U-Net 为什么适合小数据医学影像? 预训练编码器提供通用特征;跳跃连接保留浅层细节减少学习目标;强增广(弹性形变)扩充有效样本;对称结构参数高效。四个因素叠加,几百张标注可训。
Q:分割为什么常用 Dice loss? 像素级任务前景占比常极低,交叉熵被背景主导;Dice 直接优化预测与真值的重叠度,天然对类别不均衡稳健。实践中 Dice + CE 混合损失最常见。
Q:语义分割和实例分割的区别与代表模型? 语义分割不区分同类个体(U-Net、DeepLab);实例分割区分个体(Mask R-CNN,在检测框架上加掩码分支);全景分割统一两者(Panoptic FPN)。
Q:SAM(Segment Anything)改变了什么? 通用分割基础模型:点/框提示即可分割任意物体,零样本迁移。它更多是标注工具(预标注大幅降低人工成本)和交互式分割方案,不直接替代特定领域的精调 U-Net。
💬 评论
这套方案在哪一步卡住了?也欢迎补充你的实现方式或踩坑经验。