Cityscapes数据集实战指南:从数据加载到模型训练的全流程解析

1次阅读
没有评论

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

image.webp

1. Cityscapes 数据集的结构与特点

Cityscapes 是专注于城市道路场景理解的权威数据集,包含来自 50 个欧洲城市的街景图像。它的核心价值在于提供像素级语义标注,适合训练自动驾驶感知模型。数据集主要分为三部分:

Cityscapes 数据集实战指南:从数据加载到模型训练的全流程解析

  • 2975 张精细标注训练图(fine annotation):逐像素人工标注,标注质量极高
  • 500 张精细标注验证图:用于模型调参和验证
  • 19998 张粗糙标注图(coarse annotation):通过半自动方法生成,适合预训练

19 类语义标签详解

标签采用分层结构,实际训练常用 19 个可分类别(按 trainIds 编号):

  1. 道路(road)
  2. 人行道(sidewalk)
  3. 建筑(building)
    …(完整列表见官方文档)

特别需要注意 void 类(编号 255),表示不参与评估的忽略区域,如车辆遮挡部分。

2. 数据加载的痛点与解决方案

精细标注 vs 粗糙标注

  • 精细标注
  • 文件路径示例:gtFine/train/munster/munster_000000_000019_gtFine_labelIds.png
  • 每个像素值对应 trainIds 编号
  • 推荐优先使用

  • 粗糙标注

  • 文件命名带 coarse 字样
  • 存在标注噪声,适合数据饥渴场景
  • 需特殊处理标注不一致问题

常见问题

  1. 路径匹配混乱:原始图像(leftImg8bit)与标注文件在不同子目录
  2. 标注文件版本 :注意使用labelIds 而非 color 版本
  3. 城市子文件夹:不同城市场景存在分布差异

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.DataLoaderpin_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 数据集,避开笔者当年踩过的坑。建议从精细标注的小子集开始实验,逐步扩展到完整训练集。

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