共计 2886 个字符,预计需要花费 8 分钟才能阅读完成。
背景介绍
CCTSDB(Chinese Traffic Sign Detection Benchmark)是国内常用的交通标志检测数据集,包含上万张真实场景下的交通标志图像。对于新手来说,这个数据集有几个明显特点:

- 标注格式多样(部分为 PASCAL VOC 格式,部分为自定义格式)
- 图像尺寸不统一(从 640×480 到 1920×1080 不等)
- 存在类别不平衡问题(常见标志样本多,稀有标志样本少)
在实际应用中,这个数据集常被用于智能驾驶系统中的标志识别模块开发,也是学习目标检测的经典练手材料。
数据预处理
处理不规则标注
首先需要统一标注格式。假设原始标注是混乱的 XML 和 TXT 混合格式,我们可以用以下代码进行转换:
import xml.etree.ElementTree as ET
import pandas as pd
def parse_xml(xml_path):
tree = ET.parse(xml_path)
objects = []
for obj in tree.findall('object'):
obj_data = {'filename': tree.find('filename').text,
'class': obj.find('name').text,
'xmin': int(obj.find('bndbox/xmin').text),
'ymin': int(obj.find('bndbox/ymin').text),
'xmax': int(obj.find('bndbox/xmax').text),
'ymax': int(obj.find('bndbox/ymax').text)
}
objects.append(obj_data)
return pd.DataFrame(objects)
统一图像尺寸
使用 OpenCV 进行图像 resize 时,建议保持宽高比进行填充,避免形变:
import cv2
def resize_with_pad(image, target_size=(640, 640)):
h, w = image.shape[:2]
scale = min(target_size[0]/w, target_size[1]/h)
new_w, new_h = int(w * scale), int(h * scale)
resized = cv2.resize(image, (new_w, new_h))
# 计算填充尺寸
top = (target_size[1] - new_h) // 2
bottom = target_size[1] - new_h - top
left = (target_size[0] - new_w) // 2
right = target_size[0] - new_w - left
# 使用灰色填充边界
return cv2.copyMakeBorder(resized, top, bottom, left, right,
cv2.BORDER_CONSTANT, value=(114, 114, 114))
模型选型
在交通标志识别任务中,常见模型架构的表现对比如下:
- CNN 分类模型 (如 ResNet)
- 优点:实现简单,训练速度快
- 缺点:需要先进行目标检测裁剪
-
适用场景:已知标志位置的分类任务
-
YOLO 系列 (如 YOLOv5)
- 优点:端到端检测,推理速度快
- 缺点:小目标检测效果可能不佳
-
适用场景:实时性要求高的车载系统
-
Faster R-CNN
- 优点:检测精度高
- 缺点:计算资源消耗大
- 适用场景:对精度要求极高的场景
完整训练流程
以 PyTorch 实现 YOLOv5 训练为例:
-
安装依赖
pip install torch torchvision pip install yolov5 # 官方实现 -
数据准备
按照 YOLO 格式组织数据集:dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/ -
配置文件
创建 data.yaml 指定数据集路径和类别:train: ../dataset/images/train/ val: ../dataset/images/val/ nc: 58 # 类别数 names: ['prohibitory', 'mandatory', 'danger', ...] # 类别名称 -
启动训练
from yolov5 import train train.run( data='data.yaml', cfg='yolov5s.yaml', weights='yolov5s.pt', epochs=100, batch_size=16 )
避坑指南
标注错误处理
常见问题包括:
- 标志被部分遮挡但未标注
- 同一标志被重复标注
- 标注框偏离实际标志
解决方案:
- 使用标注可视化工具检查
import matplotlib.pyplot as plt import matplotlib.patches as patches def visualize_annotation(image_path, annotation_df): img = plt.imread(image_path) fig, ax = plt.subplots(1) ax.imshow(img) for _, row in annotation_df.iterrows(): rect = patches.Rectangle((row['xmin'], row['ymin']), row['xmax'] - row['xmin'], row['ymax'] - row['ymin'], linewidth=1, edgecolor='r', facecolor='none') ax.add_patch(rect) plt.show()
数据增强技巧
针对交通标志的特殊性,推荐使用:
- 色彩抖动(模拟不同光照条件)
- 随机透视变换(模拟视角变化)
- 添加噪声(模拟摄像头噪点)
避免使用:
- 过度旋转(可能导致标志不可读)
- 剧烈裁剪(可能丢失小标志)
性能优化
量化推理
使用 TorchScript 导出量化模型:
model = torch.load('best.pt')['model'].float()
model.eval()
# 转换为 TorchScript
traced = torch.jit.trace(model, torch.rand(1, 3, 640, 640))
torch.jit.save(traced, 'traced.pt')
# 动态量化
quantized_model = torch.quantization.quantize_dynamic(model, {torch.nn.Linear}, dtype=torch.qint8
)
准确率与速度平衡
通过修改 YOLO 的模型宽度和深度参数:
# yolov5s.yaml
depth_multiple: 0.33 # 控制深度
width_multiple: 0.50 # 控制宽度
延伸思考
- 如何处理极端天气条件(雨雪雾)下的交通标志识别?
- 当遇到数据集未包含的新型交通标志时,如何让模型具备增量学习能力?
- 在嵌入式设备上部署时,有哪些进一步的优化手段可以提升推理速度?
通过本文的完整流程实践,你应该已经能够独立完成从数据准备到模型部署的交通标志识别系统开发。建议先从 YOLOv5s 这样的小模型开始实验,逐步尝试更大的模型和更复杂的优化技巧。
正文完
