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

1次阅读
没有评论

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

image.webp

数据集结构与特点

Cityscapes 数据集包含来自 50 个不同城市的街道场景图像,主要用于语义分割任务。数据集的核心特点包括高分辨率(2048×1024)、精细标注(fine annotation)和粗糙标注(coarse annotation)两种标注类型,以及 19 类语义标签。

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

  1. 数据组织方式:
  2. leftImg8bit:原始 RGB 图像
  3. gtFine:精细标注(2975 张)
  4. gtCoarse:粗糙标注(19998 张)

  5. 19 类语义标签(按 trainId 顺序):

  6. 0: 可忽略区域
  7. 1: 道路
  8. 2: 人行道
  9. 3: 建筑
  10. 4: 围墙
  11. 5: 栅栏
  12. 6: 电线杆
  13. 7: 交通灯
  14. 8: 交通标志
  15. 9: 植被
  16. 10: 地形
  17. 11: 天空
  18. 12: 行人
  19. 13: 骑行者
  20. 14: 小车
  21. 15: 卡车
  22. 16: 巴士
  23. 17: 火车
  24. 18: 摩托车

数据加载痛点与解决方案

  1. 标注文件解析难点:
  2. 精细标注使用 labelIds 格式(每个像素对应一个类别 ID)
  3. 粗糙标注的标注质量较低,建议优先使用精细标注
  4. 解决方案:使用官方提供的 cityscapesscripts 工具包

  5. 内存管理问题:

  6. 高分辨率图像直接加载会消耗大量内存
  7. 解决方案:

    • 使用 PIL.Image 的懒加载模式
    • 实现按需裁剪的数据流
  8. 标注对齐问题:

  9. 原始图像和标注文件需要严格匹配
  10. 解决方案:维护文件名映射表

完整数据加载代码实现

import os
from PIL import Image
import torch
from torch.utils.data import Dataset
from torchvision import transforms

class CityscapesDataset(Dataset):
    """Cityscapes 数据集加载器"""

    def __init__(self, root_dir, split='train', crop_size=(512, 1024)):
        self.root_dir = root_dir
        self.split = split
        self.crop_size = crop_size

        # 文件路径收集
        self.image_paths = []
        self.label_paths = []

        cities = os.listdir(os.path.join(root_dir, 'leftImg8bit', split))
        for city in cities:
            img_dir = os.path.join(root_dir, 'leftImg8bit', split, city)
            label_dir = os.path.join(root_dir, 'gtFine', split, city)

            for img_name in os.listdir(img_dir):
                if img_name.endswith('_leftImg8bit.png'):
                    base_name = img_name.replace('_leftImg8bit.png', '')
                    label_name = base_name + '_gtFine_labelIds.png'

                    self.image_paths.append(os.path.join(img_dir, img_name))
                    self.label_paths.append(os.path.join(label_dir, label_name))

        # 数据增强
        self.transform = transforms.Compose([transforms.RandomHorizontalFlip(),
            transforms.ColorJitter(brightness=0.5, contrast=0.5, saturation=0.5)
        ])

    def __len__(self):
        return len(self.image_paths)

    def __getitem__(self, idx):
        # 加载图像和标注
        image = Image.open(self.image_paths[idx]).convert('RGB')
        label = Image.open(self.label_paths[idx])

        # 随机裁剪
        i, j, h, w = transforms.RandomCrop.get_params(image, output_size=self.crop_size)
        image = transforms.functional.crop(image, i, j, h, w)
        label = transforms.functional.crop(label, i, j, h, w)

        # 数据增强(仅对图像)image = self.transform(image)

        # 转换为 Tensor
        image = transforms.ToTensor()(image)
        label = torch.from_numpy(np.array(label)).long()

        return image, label

PyTorch 模型训练示例

  1. 基础训练流程:
import torch.nn as nn
from torch.utils.data import DataLoader

# 初始化数据集
dataset = CityscapesDataset('path/to/cityscapes', split='train')
dataloader = DataLoader(dataset, batch_size=4, shuffle=True, num_workers=4)

# 定义模型(示例使用简化版 UNet)model = UNet(num_classes=19).cuda()
criterion = nn.CrossEntropyLoss(ignore_index=255)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)

# 训练循环
for epoch in range(100):
    for images, labels in dataloader:
        images = images.cuda()
        labels = labels.cuda()

        # 前向传播
        outputs = model(images)
        loss = criterion(outputs, labels)

        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
  1. 评估指标计算:
  2. 使用 IoU(Intersection over Union)作为主要指标
  3. 注意忽略标签(255)的处理

性能优化建议

  1. 内存优化:
  2. 使用混合精度训练(AMP)
  3. 实现动态分辨率调整

  4. 数据并行:

  5. 使用 DistributedDataParallel 替代DataParallel
  6. 调整 num_workers 数量(通常设为 CPU 核心数的 2 - 4 倍)

  7. 预处理加速:

  8. 预先把小尺寸样本缓存到内存
  9. 使用 torchvision.transforms.functional 替代 PIL 操作

常见问题排查

  1. 标注不对齐:
  2. 检查文件名匹配逻辑
  3. 验证图像和标注的尺寸是否一致

  4. 评估指标异常:

  5. 确认是否正确处理了 ignore_index
  6. 检查预测结果是否经过 softmax/sigmoid

  7. 显存不足:

  8. 减小 batch_size
  9. 使用梯度累积技术

实践建议

Cityscapes 数据集是理解城市场景语义分割的绝佳起点。建议读者:

  1. 先在小规模数据上验证流程
  2. 尝试将模型迁移到其他城市场景数据集
  3. 探索多任务学习(如同时进行分割和深度估计)

通过掌握 Cityscapes 数据集的使用方法,开发者可以快速构建适用于真实场景的计算机视觉系统。数据集中的挑战性场景(如遮挡、光照变化等)也能帮助提升模型的鲁棒性。

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