3. 语义分割数据集详解

做语义分割,数据集就是你的「食材」。食材不好,厨艺再高也白搭。我这些年踩过的坑,有一半都跟数据集有关——不是标签对不上,就是颜色映射搞反了。今天咱们就把两个最经典的数据集掰开揉碎讲清楚。

核心观点:PASCAL VOC 2012适合入门和快速验证,Cityscapes才是工业级实战的标配。别搞反了。

3.1 PASCAL VOC 2012:入门首选

这个数据集,说白了就是计算机视觉界的「Hello World」。它最早是2005年出来的,后来2012年版本成了最常用的基准。我刚开始做分割时,第一个跑通的就是它。

基本概况:

  • 类别数:20个物体类 + 1个背景类
  • 训练集:1464张(原版),加上增强版有10582张
  • 验证集:1449张
  • 测试集:1456张(标签不公开)
  • 图像分辨率:平均500×375左右

嗯,这里要注意——原版训练集只有1464张,对于深度学习来说太少了。所以大家普遍用的是增强版(augmented),也就是VOC 2012 + SBD(Semantic Boundaries Dataset)的组合。我在项目中习惯直接用增强版,效果明显好一截。

类别列表:

类别ID 名称 颜色(RGB)
0背景(0, 0, 0)
1飞机(128, 0, 0)
2自行车(0, 128, 0)
3鸟(128, 128, 0)
4船(0, 0, 128)
5瓶子(128, 0, 128)
6公交车(0, 128, 128)
7汽车(128, 128, 128)
8猫(64, 0, 0)
9椅子(192, 0, 0)
10牛(64, 128, 0)
.........

我的小技巧:颜色映射表最好存成numpy数组,每次加载数据集时直接查表。我曾经手写if-else判断颜色,结果又慢又容易出错。

3.2 Cityscapes:工业级标准

Cityscapes是奔驰实验室搞出来的,专门针对街景理解。你想想看,自动驾驶、智慧城市,哪个离得开它?我个人觉得,如果你要做落地项目,Cityscapes比VOC有价值得多。

基本概况:

  • 类别数:30个类,但常用的是19个(去掉rare类)
  • 训练集:2975张精细标注 + 20000张粗糙标注
  • 验证集:500张
  • 测试集:1525张
  • 图像分辨率:2048×1024(高清!)

为什么说它「工业级」?你看分辨率就知道了——2048×1024,一张图顶VOC好几张。我刚开始跑Cityscapes时,显卡直接爆显存,后来才学会用滑动窗口或者下采样。

19类常用类别:

类别ID 名称 颜色(RGB)
0道路(128, 64, 128)
1人行道(244, 35, 232)
2建筑(70, 70, 70)
3墙(102, 102, 156)
4围栏(190, 153, 153)
5杆子(153, 153, 153)
6交通灯(250, 170, 30)
7交通标志(220, 220, 0)
8植被(107, 142, 35)
9地形(152, 251, 152)
10天空(70, 130, 180)
.........

避坑指南:我曾经在Cityscapes上犯过一个低级错误——直接用19类去训练,但忘了把ignore类(ID=255)排除掉。结果mIoU死活上不去,查了两天才发现是loss计算时把ignore类也算进去了。

3.3 数据集下载与目录结构

下载这事儿,说起来简单,但网络不好的时候能急死人。我建议直接用脚本下载,别手动点。

PASCAL VOC 2012下载:

# 方式一:直接wget
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar

# 方式二:用Python脚本
import urllib.request
url = "http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar"
urllib.request.urlretrieve(url, "VOCtrainval_11-May-2012.tar")

Cityscapes下载:需要注册账号,然后从官网下载。我个人习惯用脚本配合cookie,不然每次手动输密码太烦了。

目录结构对比:

# PASCAL VOC 2012
VOCdevkit/
  VOC2012/
    JPEGImages/        # 原始图像
    SegmentationClass/ # 语义分割标签(彩色)
    SegmentationObject/ # 实例分割标签
    ImageSets/         # 训练/验证/测试集划分
      Segmentation/
        train.txt
        val.txt
        trainval.txt

# Cityscapes
cityscapes/
  leftImg8bit/         # 原始图像
    train/
    val/
    test/
  gtFine/              # 精细标注
    train/
    val/
    test/
  gtCoarse/            # 粗糙标注(可选)
    train/
    val/

我的习惯:把两个数据集统一成一个加载接口。这样换数据集时,只需要改配置文件,不用改代码。具体做法就是写一个BaseDataset类,VOC和Cityscapes都继承它。

3.4 标签与颜色映射:最容易翻车的地方

标签映射,说白了就是「像素值」和「类别」之间的翻译。你想想看,模型输出的是类别ID(比如0,1,2...),但可视化时需要转成RGB颜色。这个映射关系一旦搞错,可视化出来的图就是一团乱码。

VOC的映射逻辑:

  • 标签图是彩色PNG,每个像素的RGB值直接对应类别
  • 比如(128, 0, 0)对应飞机,(0, 128, 0)对应自行车
  • 背景是(0, 0, 0)

Cityscapes的映射逻辑:

  • 标签图也是彩色PNG,但颜色更丰富
  • 有19个训练类 + 11个忽略类(用255标记)
  • 忽略类包括:摩托车、卡车、火车等(因为标注不一致)

颜色映射代码示例:

import numpy as np

# VOC颜色映射
voc_palette = {
    0: (0, 0, 0),        # 背景
    1: (128, 0, 0),      # 飞机
    2: (0, 128, 0),      # 自行车
    # ... 省略其他
}

def voc_label_to_color(label):
    """将类别ID转成RGB颜色"""
    h, w = label.shape
    color_img = np.zeros((h, w, 3), dtype=np.uint8)
    for cls_id, color in voc_palette.items():
        mask = (label == cls_id)
        color_img[mask] = color
    return color_img

# Cityscapes颜色映射
cityscapes_palette = {
    0: (128, 64, 128),   # 道路
    1: (244, 35, 232),   # 人行道
    # ... 省略其他
    255: (0, 0, 0),      # 忽略类(通常显示为黑色)
}

我曾经踩过的坑:有一次我直接用VOC的颜色映射去可视化Cityscapes,结果道路变成了飞机,天空变成了自行车。排查了半天才发现是调用了错误的调色板。后来我学乖了,每个数据集单独写一个映射函数,绝不混用。

3.5 知识体系总览

下面这张图,是我自己总结的数据集知识体系。你照着这个思路去学,不会乱。

语义分割数据集知识体系 数据集核心要素 数据集类型 PASCAL VOC 2012 Cityscapes 数据组成 原始图像 标签图像 关键操作 下载解压 颜色映射 核心原则 理解数据 = 理解任务 颜色映射是可视化基础,目录结构是代码基础

这张图把数据集的核心要素分成了三块:类型、组成、操作。你只要把这三块吃透了,不管换什么数据集,都能快速上手。

总结一下:VOC适合练手,Cityscapes适合实战。下载时注意网络,映射时注意别搞混。目录结构要记牢,因为后面写数据加载器时全靠它。