共计 2849 个字符,预计需要花费 8 分钟才能阅读完成。
1. Cityscapes 数据集的结构与特点
Cityscapes 是专注于城市道路场景理解的权威数据集,包含来自 50 个欧洲城市的街景图像。它的核心价值在于提供像素级语义标注,适合训练自动驾驶感知模型。数据集主要分为三部分:

- 2975 张精细标注训练图(fine annotation):逐像素人工标注,标注质量极高
- 500 张精细标注验证图:用于模型调参和验证
- 19998 张粗糙标注图(coarse annotation):通过半自动方法生成,适合预训练
19 类语义标签详解
标签采用分层结构,实际训练常用 19 个可分类别(按 trainIds 编号):
- 道路(road)
- 人行道(sidewalk)
- 建筑(building)
…(完整列表见官方文档)
特别需要注意 void 类(编号 255),表示不参与评估的忽略区域,如车辆遮挡部分。
2. 数据加载的痛点与解决方案
精细标注 vs 粗糙标注
- 精细标注:
- 文件路径示例:
gtFine/train/munster/munster_000000_000019_gtFine_labelIds.png - 每个像素值对应 trainIds 编号
-
推荐优先使用
-
粗糙标注:
- 文件命名带
coarse字样 - 存在标注噪声,适合数据饥渴场景
- 需特殊处理标注不一致问题
常见问题
- 路径匹配混乱:原始图像(leftImg8bit)与标注文件在不同子目录
- 标注文件版本 :注意使用
labelIds而非color版本 - 城市子文件夹:不同城市场景存在分布差异
3. 完整数据加载实现(PyTorch)
import os
from PIL import Image
import torch
from torch.utils.data import Dataset
import torchvision.transforms as T
class CityscapesDataset(Dataset):
def __init__(self, root, split='train', crop_size=(512, 1024)):
self.root = root
self.split = split
self.images = []
self.targets = []
# 自动收集文件路径
img_dir = os.path.join(root, 'leftImg8bit', split)
label_dir = os.path.join(root, 'gtFine', split)
for city in os.listdir(img_dir):
city_img_dir = os.path.join(img_dir, city)
city_label_dir = os.path.join(label_dir, city)
for img_name in os.listdir(city_img_dir):
if '_leftImg8bit.png' in img_name:
base_name = img_name.replace('_leftImg8bit.png', '')
label_name = f"{base_name}_gtFine_labelIds.png"
self.images.append(os.path.join(city_img_dir, img_name))
self.targets.append(os.path.join(city_label_dir, label_name))
# 数据增强
self.transform = T.Compose([T.RandomCrop(crop_size),
T.RandomHorizontalFlip(),
T.ToTensor(),])
def __getitem__(self, idx):
image = Image.open(self.images[idx]).convert('RGB')
target = Image.open(self.targets[idx])
# 同步变换
seed = torch.random.seed()
torch.random.manual_seed(seed)
image = self.transform(image)
torch.random.manual_seed(seed)
target = self.transform(target)
return image, target.squeeze(0).long()
关键说明:
– 使用 labelIds 版本保证像素值对应 trainIds
– RandomCrop 时同步变换图像和标注
– 返回的 target 需要 squeeze 和转为 long 类型
4. 语义分割模型训练示例
import torch.nn as nn
from torch.optim import Adam
# 简易 UNet 定义(实际可用 torchvision 的 FCN 等)model = UNet(num_classes=19).cuda()
criterion = nn.CrossEntropyLoss(ignore_index=255)
optimizer = Adam(model.parameters(), lr=1e-4)
# 训练循环
for epoch in range(100):
for images, targets in dataloader:
images = images.cuda()
targets = targets.cuda()
outputs = model(images)
loss = criterion(outputs, targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
注意事项:
– 必须设置 ignore_index=255 排除 void 区域
– 输入尺寸建议保持 1024×2048 比例
– 验证时需切换到评估模式
5. 性能优化建议
内存管理
- 使用
torch.utils.data.DataLoader的pin_memory=True加速 GPU 传输 - 对大数据集启用
persistent_workers=True减少进程开销 - 采用
memory_format=torch.channels_last提升卷积效率
数据并行
model = nn.DataParallel(model) # 单机多卡
# 或者
model = nn.parallel.DistributedDataParallel(model) # 多机训练
6. 常见问题排查
标注对齐问题
- 现象:预测结果与输入图像偏移
- 检查:确认数据增强时使用了相同的随机种子
指标计算异常
- mIoU 过低:检查是否正确处理了 ignore_index
- 类别不平衡:尝试加权交叉熵损失
迁移与应用思考
Cityscapes 的城市场景特性使其非常适合:
1. 自动驾驶感知系统开发
2. 街景理解模型预训练
3. 数据合成研究
尝试将学到的技术迁移到:
– 自定义数据标注(使用 labelme 等工具)
– 其他城市场景数据集(如 Mapillary Vistas)
– 视频序列分析(利用 Cityscapes 的视频片段)
通过本指南,希望你能快速上手 Cityscapes 数据集,避开笔者当年踩过的坑。建议从精细标注的小子集开始实验,逐步扩展到完整训练集。
正文完
发表至: 计算机视觉
近一天内
