Cityscapes数据集详解:从数据标注到模型训练的最佳实践

1次阅读
没有评论

共计 3000 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

1. Cityscapes 数据集概述

Cityscapes 是自动驾驶领域最权威的街景语义分割数据集之一,由奔驰牵头采集,覆盖欧洲 50 个城市的多样化场景。数据集包含:

Cityscapes 数据集详解:从数据标注到模型训练的最佳实践

  • 5000 张精细标注图像(2975 训练 /500 验证 /1525 测试)
  • 20000 张粗标注图像(仅用于预训练)
  • 19 类语义标签(如道路、车辆、行人等)
  • 分辨率高达 2048×1024

特别适合训练需要理解复杂城市场景的模型,如自动驾驶感知系统。数据采集时使用车载摄像头,模拟真实行车视角。

2. 数据标注解析

标签类别分布

19 类常用标签按出现频率可分为三个梯队:

  • 高频类:road(12.1%)、building(11.2%)、sky(7.1%)
  • 中频类:car(5.8%)、vegetation(4.3%)、sidewalk(3.9%)
  • 低频类:motorcycle(0.1%)、bicycle(0.3%)、person(0.8%)

标注文件结构

每个精细标注样本包含:

  1. leftImg8bit.png – 原始 RGB 图像
  2. gtFine/xxx_labelIds.png – 类别 ID 图(单通道,像素值 = 类别 ID)
  3. gtFine/xxx_color.png – 可视化彩色标注图

标签 ID 与类名的映射关系存储在 cityscapesscripts/helpers/labels.py 中,官方提供了 ID 转换工具。

3. 数据加载实战

基础加载示例

import cv2
import numpy as np
from pathlib import Path

# 定义类别颜色映射(RGB 格式)COLORMAP = [(128, 64, 128),   # road
    (244, 35, 232),   # sidewalk
    (70, 70, 70),     # building
    # ... 其他类别颜色
]

def load_cityscapes_sample(img_path, label_path):
    """加载图像和对应的标注"""
    img = cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2RGB)
    label = cv2.imread(label_path, cv2.IMREAD_GRAYSCALE)

    # 将单通道标签转为三通道彩色图(可视化用)colored_label = np.zeros((*label.shape, 3), dtype=np.uint8)
    for class_id, color in enumerate(COLORMAP):
        colored_label[label == class_id] = color

    return img, label, colored_label

# 示例调用
img, label, vis_label = load_cityscapes_sample(
    "leftImg8bit/train/munster/munster_000000_000019_leftImg8bit.png",
    "gtFine/train/munster/munster_000000_000019_gtFine_labelIds.png"
)

高效批量加载建议

  • 使用 torch.utils.data.Dataset 构建数据管道
  • 提前缓存 labelIds 到内存(约需 6GB 内存)
  • 对图像进行分块加载(推荐使用mmcv.FileClient

4. 模型训练技巧

PyTorch 数据管道

from torch.utils.data import Dataset

class CityscapesDataset(Dataset):
    def __init__(self, root, split='train', transform=None):
        self.img_dir = Path(root)/'leftImg8bit'/split
        self.label_dir = Path(root)/'gtFine'/split
        self.samples = self._scan_files()
        self.transform = transform

    def _scan_files(self):
        return [(str(p), str(self.label_dir/p.parent.name/f'{p.stem[:-12]}_gtFine_labelIds.png'))
            for p in self.img_dir.rglob('*_leftImg8bit.png')
        ]

    def __getitem__(self, idx):
        img_path, label_path = self.samples[idx]
        img = cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2RGB)
        label = cv2.imread(label_path, cv2.IMREAD_GRAYSCALE)

        if self.transform:
            transformed = self.transform(image=img, mask=label)
            img, label = transformed['image'], transformed['mask']

        return img, label

关键训练参数

  • 输入分辨率:推荐 768×768 随机裁剪(平衡显存和细节)
  • 学习率:初始 3e-4,配合多项式衰减
  • 损失函数:CrossEntropyLoss + 类别权重(低频类权重 >1)
  • 评价指标:mIoU(mean Intersection-over-Union)

5. 性能优化建议

数据增强策略

  • 必须使用:随机水平翻转(p=0.5)
  • 推荐使用:
  • 颜色抖动(亮度±0.2,对比度±0.2)
  • 高斯模糊(σ≤1.0)
  • 随机缩放(0.75~2.0 倍)
  • 谨慎使用:旋转(可能扭曲建筑物几何结构)

类别不平衡处理

  1. 样本重加权:根据类别像素比例计算损失权重

    # 计算各类别权重
    class_weights = 1 / np.log(1.02 + class_pixel_counts)
    criterion = nn.CrossEntropyLoss(weight=torch.FloatTensor(class_weights).cuda())

  2. OHEM(在线难例挖掘):聚焦错误预测区域

  3. 联合使用:DeepLabv3+ 的 auxiliary loss

6. 避坑指南

常见问题及解决方案

  1. 标签 ID 不匹配
  2. 现象:模型输出全为某一类
  3. 检查:确认 labelIds.png 的像素值范围是否为 0~18

  4. 显存不足

  5. 方案:减小 batch size(≥4),使用梯度累积
  6. 技巧:启用torch.backends.cudnn.benchmark = True

  7. 评估指标异常

  8. 注意:测试集标签不可见,需提交预测到官方评估服务器
  9. 替代:用验证集(500 张)做本地验证

  10. 数据加载瓶颈

  11. 优化:使用num_workers=4,PIN_MEMORY=True
  12. 升级:换用 NVMe SSD 存储

  13. 过拟合

  14. 对策:添加 Label Smoothing(ε=0.1)
  15. 增强:MixUp 或 CutMix 数据增强

延伸思考

  1. 如何设计针对 Cityscapes 中极小目标(如交通灯)的特化处理模块?
  2. 在模型部署阶段,如何平衡 2048×1024 高分辨率的精度需求和实时性要求?
  3. 对比其他街景数据集(如 Mapillary Vistas),Cityscapes 的标注体系有哪些独特优势?

通过系统性地处理数据加载、模型训练和性能优化环节,开发者可以充分发挥 Cityscapes 数据集的价值。建议在实际项目中先复现官方基准模型(如 PSPNet),再逐步迭代优化。

正文完
 0
评论(没有评论)