|
### 计算机视觉三大任务
| 任务 | 输出 | 理解粒度 |
|------|------|----------|
| **图像分类** | 整张图的类别概率 | 整图 |
| **目标检测** | 目标的 bounding box + 类别 | 目标级别 |
| **图像分割** | 每个像素的类别标签 | 像素级别 |
图像分割又可细分为:
- **语义分割(Semantic Segmentation)**:为每个像素赋予类别标签,但不区分同类别的不同实例。
- **实例分割(Instance Segmentation)**:在语义分割的基础上,进一步区分同一类别的不同个体(如羊 1、羊 2、羊 3)。
- **全景分割(Panoptic Segmentation)**:语义分割 + 实例分割的统一,既标注"可计数事物(things)"的实例,也标注"不可计数背景(stuff)"的语义类别。
> 📌 **课件缺失补充**:课件只介绍了语义分割与实例分割,未涉及**全景分割**。在工业界和学术界的 Cityscapes、COCO 等评测中,全景分割已成为标准任务之一。
### 图像分割的定义
图像分割(Image Segmentation)是将数字图像细分为多个图像子区域(像素集合)的过程,要求:
- 同一子区域内的像素特征具有相似性;
- 不同子区域之间的特征差异明显。
本质上,图像分割的目标是为图像中的**每个像素进行分类**。
### 应用领域
- **自动驾驶**:道路、车道线、行人、车辆的像素级感知。
- **医疗影像诊断**:病灶、器官、肿瘤的精确勾画。
- **图像美化/人像分割**:背景虚化、换背景、抠图。
- **三维重建/AR**:通过分割辅助深度估计与场景理解。
- **遥感**:土地利用分类、建筑物提取。
|
|
### 任务类型
#### 语义分割
语义分割就是把图像中每个像素赋予一个类别标签,例如将图像中的像素分类为人、羊、狗、草地等。
#### 实例分割
实例分割相对于语义分割来讲,不仅要区分不同类别的像素,还需要对同一类别的不同个体进行区分。例如不仅需要进行类别的划分,还要将各个个体划分出来:羊 1,羊 2,羊 3 等。
目前图像分割的任务主要集中在语义分割,而目前的难点也在于"语义",表达某一语义的同一物体并不总是以相同的形象出现,如包含不同的颜色、纹理等,这对精确分割带来了很大的挑战。
#### 任务描述
简单来说,我们的目标是输入一个 RGB 彩色图片(height × width × 3)或者一个灰度图(height × width × 1),然后输出一个包含各个像素类别标签的分割图(height × width × 1)。
预测目标可以采用 one-hot 编码,即为每一个可能的类创建一个输出通道。通过取每个像素点在各个 channel 的 argmax 可以得到最终的预测分割图。当将预测结果叠加到单个 channel 时,称这为一个掩膜 mask,它可以给出一张图像中某个特定类的所在区域。
|
|
### 常用开源数据集
| 数据集 | 任务 | 类别数 | 特点 |
|--------|------|--------|------|
| **PASCAL VOC 2012** | 语义/实例分割 | 20 + 背景 | 经典基准,标注质量高 |
| **Cityscapes** | 语义/实例/全景分割 | 19/30 | 街景自动驾驶场景,专业权威 |
| **MS COCO** | 实例/全景/语义分割 | 80 things + stuff | 大规模,场景复杂 |
| **ADE20K** | 语义分割 | 150 | 场景理解,类别丰富 |
| **Oxford-IIIT Pet** | 宠物语义分割 | 前景/背景/不确定 | 教学常用小数据集 |
#### VOC 数据集分割结构
```
VOCdevkit/VOC2012/
├── JPEGImages/ # 原始图片
├── ImageSets/Segmentation/ # 训练/验证/测试列表
├── SegmentationClass/ # 语义分割标注(PNG)
└── SegmentationObject/ # 实例分割标注(PNG)
```
#### Cityscapes 数据集结构
```
cityscapes/
├── leftImg8bit/ # 左摄像头 8bit RGB 图像
│ ├── train/
│ ├── val/
│ └── test/
└── gtFine/ # 精细标注
├── train/
├── val/
└── test/
├── xxx_gtFine_color.png # 可视化
├── xxx_gtFine_instanceIds.png # 实例分割
├── xxx_gtFine_labelIds.png # 语义分割
└── xxx_gtFine_polygons.json # 多边形标注
```
|
|
### 评价指标
假设共有 \(k+1\) 个类别(含背景),\(p_{ij}\) 表示本属于类 \(i\) 但被预测为类 \(j\) 的像素数,则 \(p_{ii}\) 为预测正确的像素数。
#### 像素精度(Pixel Accuracy, PA)
$$
PA = \frac{\sum_{i=0}^{k} p_{ii}}{\sum_{i=0}^{k}\sum_{j=0}^{k} p_{ij}}
$$
即预测正确的像素占总像素的比例。
> ⚠️ **局限性**:在类别不平衡场景(如医学影像中背景占 99%)下,PA 会严重偏高,无法反映模型对前景的识别能力。
#### 平均像素精度(Mean Pixel Accuracy, MPA)
$$
MPA = \frac{1}{k+1} \sum_{i=0}^{k} \frac{p_{ii}}{\sum_{j=0}^{k} p_{ij}}
$$
先计算每个类别内被正确分类的像素比例,再对所有类别取平均。
#### 平均交并比(Mean IoU, MIoU)
$$
MIoU = \frac{1}{k+1} \sum_{i=0}^{k} \frac{p_{ii}}{\sum_{j=0}^{k} p_{ij} + \sum_{j=0}^{k} p_{ji} - p_{ii}}
$$
MIoU 是语义分割最常用的标准度量,计算真实值与预测值的交集与并集之比。
> 📌 **课件缺失补充**:工业实践中还会使用 **FWIoU(Frequency Weighted IoU)**、**Dice 系数**、**Hausdorff 距离(医学)** 等指标。Dice 系数与 IoU 正相关,但在小目标分割中更稳定。
|
|
### 从 CNN 到 FCN
传统分类 CNN(如 VGG、ResNet)最后连接全连接层(FC),输出整图的类别概率,无法得到每个像素的类别信息。
**FCN(Fully Convolutional Networks)** 的核心思想:
> 将网络后几层的全连接层替换为卷积层,使网络输出与输入尺寸相同的二维特征图,再对每个像素做 softmax 分类。
**CNN vs FCN**:
| 网络 | 卷积层之后 | 输出 |
|------|------------|------|
| CNN | 全连接层 | 整图类别向量 |
| FCN | 卷积层 | 与输入等大的特征图 |
|
|
### 网络结构
FCN 整体分为两大部分:
1. **全卷积部分(Encoder)**:使用预训练 CNN(如 VGG、AlexNet、ResNet)提取特征,去掉全连接层。
2. **上采样部分(Decoder)**:将深层特征图上采样回原图尺寸。
以 VGG/AlexNet 为例:
| 阶段 | 相对输入尺寸 | 操作 |
|------|--------------|------|
| input | \(H \times W\) | 原图 |
| pool1 | \(H/2 \times W/2\) | max pooling |
| pool2 | \(H/4 \times W/4\) | max pooling |
| pool3 | \(H/8 \times W/8\) | max pooling |
| pool4 | \(H/16 \times W/16\) | max pooling |
| pool5 | \(H/32 \times W/32\) | max pooling |
经过多次卷积和 pooling 以后,得到的图像越来越小,分辨率越来越低。对最终的特征图进行 upsampling,把图像进行放大到原图像的大小,就得到原图像的分割结果。
|
|
### 上采样:反卷积 / 转置卷积
FCN 采用**反卷积(Deconvolution / Transposed Convolution)**实现上采样。
通俗理解:在输入特征图元素之间插入 0,再进行正向卷积,从而达到放大特征图的效果。
输出尺寸公式:
$$
m = s(n - 1) + k - 2p
$$
其中:
- \(n\):输入尺寸
- \(m\):输出尺寸
- \(s\):stride(放大倍数)
- \(k\):卷积核大小
- \(p\):padding
> **注意**:这里的 stride 应理解为"输入放大的倍数",而不是普通卷积中 kernel 滑动的步长。
|
|
### 跳层连接(Skip Connections)
仅对最后一层特征图做 32 倍上采样(FCN-32s),会丢失大量细节。FCN 提出**跳层连接**,将深层语义信息与浅层空间细节融合:
| 变体 | 融合策略 | 特点 |
|------|----------|------|
| **FCN-32s** | pool5 直接 32× 上采样 | 最粗糙,细节差 |
| **FCN-16s** | pool5 2× 上采样 + pool4 相加后 16× 上采样 | 中等精度 |
| **FCN-8s** | pool4+pool3 与上采样特征多次融合后 8× 上采样 | 最精细 |
可以看到随着上采样做得越多,分割结果越来越精细。
|
|
### FCN 的优缺点
**优点**:
- 端到端训练,可接受任意尺寸输入;
- 全卷积结构高效,可利用预训练分类模型参数;
- 奠定了语义分割的基本框架。
**局限性**:
- 上采样结果仍较模糊,对细节不敏感;
- 未显式建模像素之间的关系;
- 对小型目标和复杂边界分割效果有限。
> 📌 **课件缺失补充**:FCN 之后,工业界更常用的语义分割网络是 **DeepLab 系列** 和 **PSPNet**。DeepLab 引入空洞卷积(Atrous Convolution)扩大感受野,使用 ASPP(Atrous Spatial Pyramid Pooling)捕获多尺度上下文;PSPNet 使用金字塔池化模块聚合全局上下文。
|
|
### 整体架构
UNet 由 Ronneberger 等人于 2015 年提出,最初用于生物医学图像分割。它建立在 FCN 的编码器-解码器思想之上,但通过**对称的 U 型结构**和**密集跳跃连接**取得了更精细的分割效果。
UNet 整体形如字母 "U",由两部分组成:
- **编码器(左侧)**:逐层下采样提取语义特征;
- **解码器(右侧)**:逐层上采样恢复空间分辨率,并与编码器对应层特征拼接融合。
最后一层使用 \(1 \times 1\) 卷积,将通道数映射到类别数,再接 softmax 得到每个像素的类别概率。
|
|
### 编码器(下采样路径)
编码器由重复的卷积块组成,每个块通常包含:
1. 两个 \(3 \times 3\) 卷积层 + ReLU;
2. 一个 \(2 \times 2\) max pooling 层(stride=2)。
每次下采样后,特征通道数加倍。
编码器特点是:
- 架构中含有一种重复结构,每次重复中都有 2 个 3×3 卷积层、非线性 ReLU 层和一个 2×2 max pooling 层(stride 为 2)
- 每一次下采样后我们都把特征通道的数量加倍
- 每次重复都有两个输出:一个用于编码部分进行特征提取,一个用于解码部分的特征融合
|
|
### 解码器(上采样路径)
解码器每个块通常包含:
1. \(2 \times 2\) 反卷积(up-convolution),特征通道数减半、空间尺寸加倍;
2. 与编码器对应层特征进行 **Concatenate(通道拼接)**;
3. 两个 \(3 \times 3\) 卷积层 + ReLU。
> **裁剪(Crop)**:由于卷积未使用 same padding,编码器特征图尺寸会略大于解码器特征图,需要裁剪后再拼接。现代实现通常使用 `padding='same'` 避免此问题。
解码器特点:
- 每一步都首先使用反卷积(up-convolution),每次使用反卷积都将特征通道数量减半,特征图大小加倍
- 反卷积过后,将反卷积的结果与编码部分中对应步骤的特征图拼接起来
- 编码部分中的特征图尺寸稍大,将其修剪过后进行拼接
- 对拼接后的 map 再进行 2 次 3×3 的卷积
|
|
### UNet 为什么有效
| 设计 | 作用 |
|------|------|
| 对称编解码结构 | 逐步恢复空间分辨率 |
| 跳跃连接 | 融合深层语义与浅层细节,保留边缘信息 |
| 全卷积 | 支持端到端训练,可处理任意尺寸输入 |
| 数据增强友好 | 在小样本医学数据上表现突出 |
类似于一个大大的 U 字母:首先进行卷积和池化来完成下采样;然后通过反卷积进行上采样,crop 之前的低层 feature map,进行融合;然后再次上采样。重复这个过程,直到获得输出的 feature map,最后经过 softmax 获得输出分割结果。
|
|
### 任务与数据集简介
**Oxford-IIIT Pet Dataset** 是用于宠物图像分割的公开数据集:
- 37 个宠物类别(12 种猫 + 25 种狗);
- 每个类别约 200 张图片;
- 共约 7349 张图像;
- 标注包含:宠物品种、头部 ROI、像素级分割掩码。
分割任务将每个像素分为 3 类:
- **1:前景(宠物)**
- **2:背景**
- **3:不确定边界**
数据集目录结构:
```
segdata/
├── images/ # 原始图像(*.jpg)
│ ├── Abyssinian_1.jpg # 猫:大写开头
│ └── pug_10.jpg # 狗:小写开头
└── annotations/
├── list.txt # 类别与品种标注
└── trimaps/ # 像素级分割掩码(*.png)
```
|
|
### 数据读取与预处理
#### 导入工具包
```python
import os
import random
import numpy as np
import PIL
from PIL import ImageOps
from tensorflow import keras
from tensorflow.keras.preprocessing.image import load_img
from IPython.display import Image, display
```
#### 参数设置
```python
input_dir = "segdata/images/"
target_dir = "segdata/annotations/trimaps/"
img_size = (160, 160)
batch_size = 32
num_classes = 4 # 实际 3 类 + 1 个忽略/填充位
input_img_paths = sorted([
os.path.join(input_dir, fname)
for fname in os.listdir(input_dir)
if fname.endswith(".jpg")
])
target_img_paths = sorted([
os.path.join(target_dir, fname)
for fname in os.listdir(target_dir)
if fname.endswith(".png") and not fname.startswith(".")
])
```
> **one-hot 编码技巧**:标签 1、2、3 分别编码为 `0010`、`0100`、`1000`,因此类别数可设为 4。
#### 标注可视化
```python
# 原图
display(Image(filename=input_img_paths[10]))
# 标注图:使用 autocontrast 增强对比度
img = PIL.ImageOps.autocontrast(load_img(target_img_paths[10]))
display(img)
```
`PIL.ImageOps.autocontrast` 会将最暗像素映射为 0(黑),最亮像素映射为 255(白),中间值按直方图拉伸显示。
#### 构建 Keras 数据生成器
```python
class OxfordPets(keras.utils.Sequence):
def __init__(self, batch_size, img_size, input_img_paths, target_img_paths):
self.batch_size = batch_size
self.img_size = img_size
self.input_img_paths = input_img_paths
self.target_img_paths = target_img_paths
def __len__(self):
return len(self.target_img_paths) // self.batch_size
def __getitem__(self, idx):
i = idx * self.batch_size
batch_input_img_paths = self.input_img_paths[i: i + self.batch_size]
batch_target_img_paths = self.target_img_paths[i: i + self.batch_size]
x = np.zeros((batch_size,) + self.img_size + (3,), dtype="float32")
for j, path in enumerate(batch_input_img_paths):
img = load_img(path, target_size=self.img_size)
x[j] = img
y = np.zeros((batch_size,) + self.img_size + (1,), dtype="uint8")
for j, path in enumerate(batch_target_img_paths):
img = load_img(path, target_size=self.img_size, color_mode="grayscale")
y[j] = np.expand_dims(img, 2)
return x, y
```
> 📌 **课件缺失补充**:工业项目通常不会手写 `Sequence`,而是使用更专业的数据增强库 **Albumentations**,它支持同步对图像和 mask 做随机翻转、旋转、裁剪、颜色抖动、弹性形变等操作。
|
|
### 模型构建
#### 导入工具包
```python
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.layers import (
Input, Conv2D, Conv2DTranspose, MaxPooling2D,
Cropping2D, Concatenate, Lambda, Activation,
BatchNormalization, Dropout
)
from tensorflow.keras.models import Model
```
#### 下采样模块(编码器)
```python
def downsampling_block(input_tensor, filters):
# 输入:input_tensor, 通道数:filters
# 卷积
x = Conv2D(filters, kernel_size=(3, 3), padding='same')(input_tensor)
# BN
x = BatchNormalization()(x)
# 激活
x = Activation('relu')(x)
x = Conv2D(filters, kernel_size=(3, 3), padding='same')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
# 返回:下采样后的特征 + 未下采样的特征(用于跳跃连接)
return MaxPooling2D(pool_size=(2, 2))(x), x
```
对应网络结构:**编码器中的重复卷积块**,包含 2 个 3×3 卷积 + BN + ReLU,以及一个 2×2 max pooling。
#### 上采样模块(解码器)
```python
def upsampling_block(input_tensor, skip_tensor, filters):
# input_tensor: 输入特征图,skip_tensor: 编码部分的特征图,filters: 通道数
# 反卷积
x = Conv2DTranspose(
filters, kernel_size=(2, 2), strides=(2, 2), padding="same"
)(input_tensor)
_, x_height, x_width, _ = x.shape
_, s_height, s_width, _ = skip_tensor.shape
h_crop = s_height - x_height
w_crop = s_width - x_width
if h_crop == 0 and w_crop == 0:
y = skip_tensor
else:
cropping = (
(h_crop // 2, h_crop - h_crop // 2),
(w_crop // 2, w_crop - w_crop // 2)
)
y = Cropping2D(cropping=cropping)(skip_tensor)
x = Concatenate()([x, y])
x = Conv2D(filters, kernel_size=(3, 3), padding="same")(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Conv2D(filters, kernel_size=(3, 3), padding="same")(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
return x
```
对应网络结构:**解码器中的上采样块**,包含反卷积(2×2,stride=2)+ 特征拼接 + 2 个 3×3 卷积 + BN + ReLU。
#### 完整 UNet
```python
def unet(img_size, classes, features=64, depth=3):
inputs = keras.Input(shape=img_size + (3,))
x = inputs
skips = []
# 编码器
for i in range(depth):
x, x0 = downsampling_block(x, features)
skips.append(x0)
features *= 2
# 瓶颈层
x = Conv2D(features, kernel_size=(3, 3), padding="same")(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Conv2D(features, kernel_size=(3, 3), padding="same")(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
# 解码器
for i in reversed(range(depth)):
features //= 2
x = upsampling_block(x, skips[i], features)
# 输出层:1×1 卷积映射到类别数
outputs = Conv2D(classes, kernel_size=(1, 1), padding="same", activation='softmax')(x)
model = keras.Model(inputs, outputs)
return model
# 构建模型
model = unet(img_size, classes=4)
model.summary()
# 可视化
keras.utils.plot_model(model, to_file="unet_model.png", show_shapes=True)
```
对应网络结构:
- **编码器**:3 个下采样块,特征数从 64 → 128 → 256 → 512
- **瓶颈层**:2 个 3×3 卷积 + BN + ReLU,特征数 512
- **解码器**:3 个上采样块,特征数从 512 → 256 → 128 → 64
- **输出层**:1×1 卷积,softmax 激活
|
|
### 训练与预测
#### 数据集划分
```python
val_samples = 1000
# 使用相同随机种子,保证图像与标签一一对应
random.Random(1337).shuffle(input_img_paths)
random.Random(1337).shuffle(target_img_paths)
train_input_img_paths = input_img_paths[:-val_samples]
train_target_img_paths = target_img_paths[:-val_samples]
val_input_img_paths = input_img_paths[-val_samples:]
val_target_img_paths = target_img_paths[-val_samples:]
```
#### 生成训练与验证数据
```python
train_gen = OxfordPets(
batch_size, img_size, train_input_img_paths, train_target_img_paths
)
val_gen = OxfordPets(
batch_size, img_size, val_input_img_paths, val_target_img_paths
)
```
#### 编译与训练
```python
model.compile(
optimizer="rmsprop",
loss="sparse_categorical_crossentropy"
)
epochs = 15
model.fit(train_gen, epochs=epochs, validation_data=val_gen)
```
训练日志示例:
```text
Epoch 1/15
199/199 [==============================] - 44s 223ms/step - loss: 0.9539 - val_loss: 13.5056
...
Epoch 15/15
199/199 [==============================] - 44s 222ms/step - loss: 0.1901 - val_loss: 0.4150
```
> 📌 **课件缺失补充**:课件仅使用 `sparse_categorical_crossentropy`。在图像分割,尤其是医学影像、小目标分割中,**Dice Loss**、**Focal Loss**、**Tversky Loss**、**Lovász-Softmax** 等损失函数通常效果更好。它们能缓解类别不平衡问题。
#### 模型预测
```python
val_preds = model.predict(val_gen)
def display_mask(i):
mask = np.argmax(val_preds[i], axis=-1)
mask = np.expand_dims(mask, axis=-1)
img = PIL.ImageOps.autocontrast(
keras.preprocessing.image.array_to_img(mask)
)
display(img)
# 显示原图、真实标注、预测结果
i = 10
display(Image(filename=val_input_img_paths[i]))
img = PIL.ImageOps.autocontrast(load_img(val_target_img_paths[i]))
display(img)
display_mask(i)
```
|
|
### 分割任务全景
课件只覆盖了语义分割与实例分割。实际行业中,分割任务已发展为更丰富的谱系:
| 任务 | 说明 | 代表数据集/模型 |
|------|------|-----------------|
| **语义分割** | 每个像素一个类别标签 | DeepLabV3+、PSPNet |
| **实例分割** | 区分同类别的不同实例 | Mask R-CNN、SOLO |
| **全景分割** | 统一语义与实例分割 | Panoptic FPN、Mask2Former |
| **视频分割** | 对视频序列逐帧分割 | Video Object Segmentation |
| **交互式分割** | 用户点击/框选辅助分割 | SAM、SegGPT |
| **医学图像分割** | 3D、小样本、高精度 | nnU-Net、Swin-UNETR |
|
|
### 主流分割网络演进
| 时间 | 方法 | 核心贡献 |
|------|------|----------|
| 2015 | **FCN** | 首个端到端全卷积语义分割网络 |
| 2015 | **UNet** | U 型结构 + 跳跃连接,医学分割标配 |
| 2016 | **SegNet** | 使用 max-pooling 索引进行上采样 |
| 2016 | **DeepLabV2** | 空洞卷积 + ASPP |
| 2017 | **PSPNet** | 金字塔场景解析,聚合全局上下文 |
| 2017 | **Mask R-CNN** | 实例分割里程碑 |
| 2018 | **DeepLabV3+** | 编码器-解码器 + 可分离空洞卷积 |
| 2018 | **UNet++** | 嵌套跳跃连接,更密集的 feature fusion |
| 2020 | **UNet 3+** | 全尺度跳跃连接 |
| 2020 | **nnU-Net** | 自配置框架,医学分割 SOTA |
| 2021 | **Swin-UNETR** | Transformer + UNet,医学 3D 分割 |
| 2021 | **SegFormer** | 轻量高效的 Transformer 分割 |
| 2022 | **Mask2Former** | 通用图像分割架构 |
| 2023 | **SAM** | 基于提示的通用图像分割大模型 |
|
|
### UNet 常见变体
| 变体 | 改进点 | 适用场景 |
|------|--------|----------|
| **UNet++** | 嵌套、密集的跳跃连接 | 小目标、复杂边界 |
| **Attention UNet** | 在跳跃连接中加入注意力门控 | 抑制无关背景 |
| **Residual UNet** | 残差连接 | 训练更深的网络 |
| **Inception UNet** | 多尺度 Inception 模块 | 多尺度目标 |
| **UNet 3+** | 全尺度特征融合 | 更丰富的上下文 |
| **TransUNet** | Transformer 编码器 + CNN 解码器 | 医学图像 |
| **nnU-Net** | 自动配置预处理、网络、训练 | 医学分割竞赛首选 |
|
|
### 损失函数选择
| 损失函数 | 特点 | 适用场景 |
|----------|------|----------|
| **Cross Entropy** | 简单直接 | 类别均衡 |
| **Weighted CE** | 给少数类更高权重 | 类别不平衡 |
| **Dice Loss** | 直接优化重叠区域 | 医学、小目标 |
| **IoU Loss** | 直接优化 IoU | 语义分割 |
| **Focal Loss** | 降低易分类样本权重 | 前景背景极不平衡 |
| **Tversky Loss** | 可调 Precision/Recall 权衡 | 医学分割 |
| **Lovász-Softmax** | 直接优化 IoU 代理 | 复杂类别不平衡 |
| **Boundary Loss** | 优化边界距离 | 边界质量要求高 |
**Dice Loss 公式**:
$$
Dice = \frac{2 |X \cap Y|}{|X| + |Y|}
$$
$$\mathcal{L}_{Dice} = 1 - Dice$$
|
|
### 训练技巧与部署优化
#### 训练技巧
1. **使用预训练 Backbone**:ResNet、EfficientNet、Swin Transformer 作为编码器可显著提升精度。
2. **学习率策略**:Warmup + Cosine Annealing 或 Poly 衰减。
3. **多尺度训练/测试**:训练时随机缩放输入,测试时使用多尺度融合。
4. **OHEM / Hard Negative Mining**:关注难分样本。
5. **标签平滑**:缓解过拟合。
6. **模型集成**:多模型投票或概率平均。
#### 数据增强策略
- **几何变换**:随机翻转、旋转、缩放、裁剪、弹性形变;
- **颜色变换**:亮度、对比度、饱和度、色相抖动;
- **混合增强**:Mixup、CutMix、Mosaic;
- **医学专用**:弹性形变(Elastic Deformation)、高斯噪声、随机直方图均衡;
- **工具推荐**:[Albumentations](https://albumentations.ai/) 是工业界最常用的高效图像增强库。
#### 推理与部署优化
| 阶段 | 工具/技术 | 说明 |
|------|-----------|------|
| 模型导出 | ONNX | 跨框架中间表示 |
| 推理加速 | TensorRT | NVIDIA GPU 高性能推理 |
| 移动端部署 | NCNN / MNN / TFLite | 轻量框架 |
| 量化 | INT8 / FP16 | 降低显存占用、提升速度 |
| 动态尺寸 | TensorRT Dynamic Shape | 支持可变输入尺寸 |
| 服务化 | Triton Inference Server | 模型服务部署 |
#### 标注工具与数据工程
| 工具 | 特点 |
|------|------|
| **LabelMe** | 开源,支持多边形标注 |
| **CVAT** | 企业级,支持视频、团队协作 |
| **Label Studio** | 通用数据标注平台 |
| **SAM / SegGPT** | 半自动/自动标注,可极大提升标注效率 |
#### 行业应用案例
- **自动驾驶**:BEV 感知、车道线分割、可行驶区域检测;
- **医疗影像**:肺结节、肿瘤、眼底血管、细胞核分割;
- **遥感**:建筑物、道路、水体、农作物提取;
- **工业质检**:缺陷检测、划痕分割;
- **人像/视频**:背景替换、虚拟背景、智能抠图;
- **机器人**:场景理解、抓取区域分割。
|
FCN: Fully Convolutional Networks for Semantic Segmentation (CVPR 2015)
U-Net: Convolutional Networks for Biomedical Image Segmentation (MICCAI 2015)
DeepLabV3+: Encoder-Decoder with Atrous Separable Convolution (ECCV 2018)
Segment Anything (ICCV 2023)