Ultralytics YOLO 语义分割数据集指南:PNG 掩码、YOLO 多边形标签与 YAML 配置全解析
本文系统讲解 Ultralytics YOLO 语义分割任务的数据集格式:如何组织 PNG 像素级掩码、如何用现成的 YOLO 多边形标签直接训练语义模型、YAML 中 masks_dir 与 label_mapping 等字段的确切含义,以及 Cityscapes / ADE20K 等内置数据集配置的使用方法。读完本文,你将能够独立准备(或复用)一份语义分割数据集并完成 YOLO26 语义模型训练,同时理解数据加载器在底层如何区分两种标签格式、如何完成标签 ID 映射与背景类注入。
什么是语义分割数据集
语义分割(semantic segmentation)为图像中的每一个像素分配一个类别标签。与实例分割不同,语义分割不区分同一类别下的不同个体——训练目标是密集的类别图(dense class map),每个像素存储一个类别 ID。这意味着语义分割数据集的核心资产是与图像逐像素对齐的掩码图像(或可栅格化为掩码的多边形标签),而不是检测任务中的边界框。
支持的两种标签格式
数据加载器支持两种标签格式,且自动选择:当数据集 YAML 定义了 masks_dir 键,或数据集根目录下已存在 masks/ 文件夹时,走 PNG 掩码格式;否则回退到 YOLO 多边形标签格式。这一选择逻辑在 build_yolo_dataset 中实现:
elif cfg.task == "semantic":
data_path = Path(data.get("path", ""))
if "masks_dir" in data or (data_path / "masks").exists():
dataset = SemanticDataset
else:
dataset = PolygonSemanticDataset
因此,masks/ 文件夹的存在与否本身就是一条分支条件,这一点对自定义数据集的目录布局影响重大。
PNG 掩码格式
每个样本对应一个图像文件和一个掩码文件。掩码是单通道图像(通常为 PNG),其中每个像素的值即对应图像像素的类别索引。规则如下:
- 像素值
0、1、2、… 对应数据集names映射中的类别 ID; - 像素值
255被当作 ignore 标签,在损失计算与指标统计中完全排除; - 掩码文件必须与图像文件共享同一 stem(文件名主干),例如
frankfurt_000000_000294.png; - 掩码默认按
.png解析,找不到时会尝试其他受支持的图像扩展名(.jpg、.tiff等)。强烈建议使用无损格式(.png或.tiff),因为.jpg等有损压缩会破坏类别 ID 的像素值。
默认目录布局是图像与掩码平行存放,YAML 中 masks_dir 的值会替换 images 路径分量来定位掩码:
dataset/
├── images/
│ ├── train/
│ └── val/
└── masks/
├── train/
└── val/
例如当 masks_dir: masks 时,images/train/aachen_000000_000019.png 会自动配对 masks/train/aachen_000000_000019.png。
从源码结构看,掩码路径的解析由 SemanticDataset.get_label_files 完成:它调用 img2label_paths 并传入 self.data.get("masks_dir", "masks") 与后缀 .png,即在 YAML 未写 masks_dir 时默认也是 masks。掩码的实际读取在 load_mask 中:
mask = cv2.imread(mask_file, cv2.IMREAD_GRAYSCALE) # 灰度读取,保证单通道类别 ID
...
if int(self.data.get("nc", 0)) == 1 and self.labels[index]["is_1bit"]:
mask[mask == 255] = 1 # cv2 expands 1-bit PNG foreground to 255.
值得注意的是 is_1bit 分支:对于单类别(二分类)数据集,1 位深 PNG 的前景像素会被 OpenCV 扩展为 255,代码会将其重新写为 1,避免被误判为 ignore 标签。
YOLO 多边形标签格式
如果你的数据集已经有 Ultralytics YOLO 多边形标签(每张图一个 .txt,每行 <class-index> <x1> <y1> <x2> <y2> ...),可以直接用它训练语义分割,无需转换为 PNG 掩码。行级格式说明见实例分割数据集文档。
该路径的自动触发条件是:YAML 中省略 masks_dir,并且数据集根目录(与 images 同级)下不存在 masks/ 文件夹——即使 YAML 没写 masks_dir,只要残留一个 masks/ 目录,加载器就会切到 PNG 掩码模式去那里找掩码。务必删除或重命名它。行为细节:
- 多边形在加载时被转换为逐图像的语义掩码,且按面积排序,使小物体在重叠区域覆盖大物体;
- 多类别(
names中N > 1):会在已声明类别之后自动追加一个background类,用于任何多边形未覆盖的像素。模型以N + 1个输出通道构建,最后一个通道是背景; - 单类别(
N == 1):仍按 1 类训练,掩码是二值的——你声明的类别为1,未覆盖像素为0,不会向names追加背景类; - 数据增强填充(padding)新增的像素仍用
255作为 ignore 标签。
这一"自动追加背景类"的机制在 add_polygon_background 中实现:
def add_polygon_background(data: dict) -> dict:
if data.get("masks_dir") or data.get("_polygon_bg_added"):
return data
nc = int(data.get("nc") or len(data.get("names") or {}))
if nc == 1: # binary: bg=0, fg=1 (implicit); model uses BCE on a single output channel
data["bg_class_idx"] = 0
else:
names = dict(data.get("names") or {})
names[nc] = "background"
data["bg_class_idx"] = nc
data["nc"] = nc + 1
data["names"] = names
data["_polygon_bg_added"] = True
return data
多边形到掩码的栅格化逻辑位于 PolygonSemanticDataset.load_mask:先将归一化坐标反归一化到当前 (H, W),调用 polygons2masks_overlap 得到按面积排序的实例索引图(0 = 无多边形,1..N = 排序后的实例序号),再把实例序号映射回类别 ID;单类别时直接输出 {0=背景, 1=前景} 的二值掩码。
数据集 YAML 格式
语义分割数据集用 YAML 文件配置,主要字段如下:
| 键 | 说明 |
|---|---|
path |
数据集根目录 |
train |
训练图像路径(相对 path 或绝对路径) |
val |
验证图像路径(相对 path 或绝对路径) |
test |
可选的测试图像路径 |
masks_dir |
语义掩码目录名。省略此键(且根目录无 masks/ 文件夹)即切换到 YOLO 多边形标签格式 |
names |
类别 ID 到类别名的映射 |
label_mapping |
可选,将源数据集 ID 映射到训练 ID 或 ignore_label |
内置示例:Cityscapes8 配置
仓库内置 ultralytics/cfg/datasets/cityscapes8.yaml,完整展示了 masks_dir、19 类 names 和 label_mapping 三部分:
# Dataset root directory
path: cityscapes8 # dataset root dir
train: images/train # train images (relative to 'path') 4 images
val: images/val # val images (relative to 'path') 4 images
masks_dir: masks # semantic mask directory
# Cityscapes 19-class labels
names:
0: road
1: sidewalk
2: building
# ... 完整 19 类见原文件
18: bicycle
# Map source label IDs to train IDs; ignore_label is converted to 255.
label_mapping:
-1: ignore_label
0: ignore_label
# ... 源 ID 0-13、15-16、18、29-30 均映射为 ignore_label
7: 0 # road
8: 1 # sidewalk
11: 2 # building
# ... 其余 15 个 Cityscapes 源 ID 依次映射到 0-18
33: 18 # bicycle
何时需要 label_mapping:当源掩码的像素 ID 不是连续的、与训练类别 ID 不一致时。上例中 Cityscapes 官方 labelIds 是 0–33 的非连续编号(如 road 是 7、building 是 11、car 是 24),YAML 通过 label_mapping 把它们重排为 0–18 的连续训练 ID,并把无训练价值的标签(unlabeled、void 等)统一映射为 ignore_label。
从源码看,label_mapping 在 SemanticDataset._parse_label_mapping 中被解析为整数到整数的映射(ignore_label 归一化为 255),随后 _build_label_luts 构建 256 项的前向/反向查找表(LUT),读取掩码时通过 convert_label 用 cv2.LUT 一次性完成全图 ID 重映射——这是逐像素操作,性能上是 O(1) 查表。此外,get_cache_hash 会把 label_mapping 的 JSON 内容纳入缓存哈希,修改映射后旧缓存会自动失效,无需手动清理。
使用方式:训练 YOLO26 语义模型
Python API 或 CLI 均可训练语义分割模型:
# Python
from ultralytics import YOLO
# 加载预训练语义分割模型
model = YOLO("yolo26n-sem.pt")
# 在 Cityscapes8 语义分割数据集上训练
results = model.train(data="cityscapes8.yaml", epochs=100, imgsz=1024)
# CLI
yolo semantic train data=cityscapes8.yaml model=yolo26n-sem.pt epochs=100 imgsz=1024
对应的模型结构配置(n 档)位于 ultralytics/cfg/models/26/yolo26-sem.yaml。完整的预训练模型基准表见语义分割任务页。
内置支持的数据集
Ultralytics 为以下语义分割数据集提供了开箱即用的 YAML 配置:
- Cityscapes:城市街景语义分割数据集,19 个训练类别。对应 cityscapes.yaml,
train/val/test分别含 2975 / 500 / 1525 张图像,download字段是一个内联 Python 脚本:它遍历leftImg8bit下的*_leftImg8bit.png,将每份图像与gtFine中对应的*_gtFine_labelIds.png重命名后复制到images/{split}与masks/{split},掩码缺失会抛出FileNotFoundError。注意官方 Cityscapes 需手动下载解压到path下再运行脚本。 - Cityscapes8:8 张图的 Cityscapes 小子集(train/val 各 4 张),用于快速测试与 CI 检查,
download字段是一个可直接下载的 zip URL,拉取即用。 - ADE20K:场景解析数据集,150 个语义类别。对应 ade20k.yaml,
train: images/training、val: images/validation、masks_dir: annotations,其label_mapping将 ADE20K 的 1–150 源 ID 减一映射为 0–149 训练 ID,源 ID0映射为ignore_label。下载为手动步骤(源文件约 1 GB,解压后目录名ADEChallengeData2016)。
三个配置的共性:源 ID 与训练 ID 错位时一律用 label_mapping 弥合,忽略类统一收敛到 255。
添加你自己的数据集
方案 A — PNG 掩码
- 图像存入
images/train、images/val等分片目录; - 每张图对应一个单通道掩码,存入镜像的掩码目录
masks/train、masks/val(stem 一致); - 掩码像素值即类别 ID,需忽略的像素填
255; - 创建包含
path、train、val、masks_dir、names的数据集 YAML; - 仅当掩码 ID 需要转换为连续训练 ID 时才加
label_mapping。
path: path/to/my-semantic-dataset
train: images/train
val: images/val
masks_dir: masks
names:
0: background
1: road
2: building
方案 B — 多边形标签
- 图像与
.txt多边形文件按实例分割的布局摆放; - 创建含
path、train、val、names的 YAML——不要写masks_dir; - 确保数据集根目录不存在
masks/文件夹——它的存在会强制加载器切换到 PNG 掩码模式; - 不要在
names中手动添加 "background":多类别时加载器会自动追加;单类别时保持 1 类训练,你声明的类别在掩码中为1,未覆盖像素为0。
path: path/to/my-polygon-dataset
train: images/train
val: images/val
names:
0: person
1: car
此外,Ultralytics Platform 提供面向 semantic 任务的多边形标注工具与 SAM 辅助的 Smart 标注,可直接在浏览器内标注并导出/训练多边形标签数据集,无需手动搭目录结构。
高频问题(FAQ)
语义分割掩码与实例分割标签有什么区别? 语义掩码是密集像素图,每像素存一个类别 ID,每张训练图配一张掩码图;实例分割标签是文本文件,每个物体实例占一行多边形坐标。
训练时哪个像素值会被忽略?
255。这些像素在损失与指标计算中被跳过,适用于 void 区域、未标注像素或不在训练类别集内的类别。
掩码文件名必须与图像文件名一致吗?
是。加载器把 images 目录分量替换为 masks_dir 后按同名查找掩码;.png 找不到时会回退尝试 .jpg、.tiff 等其他扩展名,但回退并不校验无损性,因此仍应坚持无损格式。
能否直接使用原数据集的标签 ID?
若它们已与 names 的类别 ID 对齐,可以。若源 ID 非连续或含应忽略的标签,加 label_mapping 将源像素值转换为训练 ID。
能否用实例分割数据集训练语义分割?
可以。同一批 .txt 多边形标签可直接复用——省略 masks_dir 并确保根目录无 masks/ 文件夹,加载器会即时把多边形栅格化为逐图掩码;多类别(N > 1)时自动追加 background 类,模型以 N + 1 个输出通道构建;单类别(N == 1)时保持 1 类,掩码中声明类为 1、未覆盖像素为 0。
Ultralytics 内置哪些语义分割数据集? Cityscapes(19 个城市场景类)、轻量 Cityscapes8(管线测试用子集)与 ADE20K(150 个场景解析类),各自的文档页均记录精确的类别列表、下载步骤与已验证的训练示例。
小结
Ultralytics YOLO 的语义分割数据集体系可以归纳为三条主线:
- 两种标签格式,一条分支规则——YAML 含
masks_dir或根目录存在masks/即走 PNG 掩码(SemanticDataset),否则走多边形栅格化(PolygonSemanticDataset),二者共用同一套训练入口; 255是贯穿始终的 ignore 标签——无论是手写掩码、label_mapping归一化的ignore_label,还是增强填充的新增像素;label_mapping是源 ID 与训练 ID 之间的适配器,配合内置的 Cityscapes / ADE20K YAML,官方数据集"下载即用";而多边形路径下加载器还会自动处理背景类的注入,多类别 +1 通道、单类别保持二值掩码。
按上述布局组织好数据、写好 YAML,即可用 yolo semantic train 或 YOLO(...).train(...) 直接开始训练。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0626
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00