共计 2712 个字符,预计需要花费 7 分钟才能阅读完成。
Cityscapes 数据集特点解析
Cityscapes 是自动驾驶领域最具挑战性的街景理解数据集之一,其核心价值在于:

- 精细化标注:5000 张高分辨率图像(2048×1024)包含 19 类语义标签,每个实例都带有多边形轮廓
- 三维属性:额外提供 30k 张弱标注图像和 3D 点云数据(需特别注意 license 限制)
- 场景复杂度:覆盖 50 个欧洲城市的不同季节、天气条件和交通场景
主流数据集横向对比
| 特性 | Cityscapes | KITTI | BDD100K |
|---|---|---|---|
| 标注类型 | 实例分割 | 3D 框 | 多任务 |
| 图像分辨率 | 2048×1024 | 1242×375 | 1280×720 |
| 动态物体占比 | 32% | 28% | 41% |
| 标注精细度 | 多边形 | 立方体 | 矩形框 |
数据加载实战技巧
JSON 标注解析示范
import json
from pathlib import Path
def parse_cityscapes_annot(annot_path):
"""
处理 Cityscapes 的 JSON 标注文件
:param annot_path: gtFine 文件夹下的 JSON 文件路径
:return: 解析后的标注字典
"""
try:
with open(annot_path, 'r') as f:
data = json.load(f)
objects = []
for obj in data['objects']:
# 处理多边形标注
if obj['label'] not in IGNORE_LABELS: # 预定义忽略类别
poly = np.array(obj['polygon']).reshape(-1, 2)
objects.append({'label': obj['label'],
'polygon': poly,
'group': obj.get('group', ''), # 处理可能缺失的 group 字段
})
return {'imagePath': data['imagePath'], 'objects': objects}
except Exception as e:
print(f"解析失败 {annot_path}: {str(e)}")
return None
关键注意点:
group字段表示同一物体的不同部分(如被遮挡的车辆)- 必须过滤
license plate等隐私相关类别 - 建议使用相对路径存储图像引用
内存优化 DataLoader 实现
class CityscapesDataset(torch.utils.data.Dataset):
def __init__(self, root, transform=None, downscale=2):
self.root = Path(root)
self.transform = transform
self.downscale = downscale # 降采样因子
# 预加载所有标注路径(避免频繁 IO)self.annotations = list(self.root.glob('gtFine/**/*.json'))
def __getitem__(self, idx):
annot_path = self.annotations[idx]
img_path = self.root / 'leftImg8bit' / annot_path.relative_to(self.root/'gtFine').with_suffix('.png')
# 使用 PIL 延迟加载 + 降采样
img = Image.open(img_path).resize((2048//self.downscale, 1024//self.downscale))
annot = parse_cityscapes_annot(annot_path)
if self.transform:
img, annot = self.transform(img, annot)
return img, annot
优化手段:
- 使用
PIL.Image替代 OpenCV 减少内存占用 - 通过降采样控制显存消耗(建议训练时设为 4,验证时用原尺寸)
- 对图像路径进行预缓存
模型训练关键策略
类别不平衡解决方案
- 样本加权法(适用于 CrossEntropyLoss)
# 计算类别权重
class_counts = np.array([142312, 8543, ..., 128]) # 各类别像素统计
class_weights = 1 / torch.log(1.02 + class_counts)
criterion = nn.CrossEntropyLoss(weight=class_weights.to(device))
- 动态数据增强(针对稀有类别)
from albumentations import (
RandomCrop, HorizontalFlip, ColorJitter,
MaskDropout # 专门处理 mask 的增强
)
def get_augmentations():
rare_classes = ['motorcycle', 'rider']
def check_rare(mask):
return any(c in mask for c in rare_classes)
return A.Compose([
A.OneOf([A.RandomCrop(800, 800),
A.HorizontalFlip(),], p=0.3),
A.RandomSunFlare(p=0.1),
A.MaskDropout(
max_objects=3,
image_fill_value=0,
p=0.5 if check_rare else 0.1 # 对稀有类别增强概率更高
)
])
多 GPU 训练配置
# 使用 DDP 启动方式(PyTorch>=1.7)python -m torch.distributed.launch \
--nproc_per_node=4 \
--master_port=1234 \
train.py \
--sync_bn \
--batch_size 16
注意事项:
- 必须设置
persistent_workers=True避免重复加载 - 验证时使用单 GPU 模式保证指标一致性
- 通过
torch.cuda.max_memory_allocated()监控显存
避坑指南
- 标注陷阱
group字段相同的物体必须视为同一实例-
注意
iscrowd=1的标注表示密集区域(应特殊处理) -
数据泄漏防范
- 严格按官方划分使用 train/val/test
-
避免对连续帧同时出现在训练和验证集
-
预处理建议
- YOLOv5 需保持原始宽高比进行 resize
- Mask R-CNN 建议使用 800px 短边缩放
延伸思考
- 如何处理视频序列中的动态物体标注连续性?
- 当遇到
void类别时,应该忽略还是作为负样本? - 如何设计适用于夜间场景的数据增强策略?
推荐工具链:
– cityscapesscripts 官方工具包
– labelme2coco 转换脚本
– FiftyOne 可视化分析平台
正文完
发表至: 未分类
近两天内
