1. 项目概述:交通信号灯智能识别系统
这个基于YOLO的交通信号灯检测与分类项目,本质上是在解决自动驾驶和辅助驾驶系统中的核心感知难题。我在实际道路测试中发现,传统图像处理方法在复杂光照、遮挡和天气条件下表现极不稳定,而深度学习模型能够显著提升识别准确率。
系统包含三个核心模块:数据集构建、模型训练和GUI界面开发。其中数据集需要覆盖不同天气、光照条件和拍摄角度,模型采用YOLOv5/v8实现实时检测,最后通过PyQt5封装成可交互的软件界面。这个方案特别适合车载设备、交通监控和驾考系统等场景。
2. 数据集构建与处理
2.1 数据采集与标注规范
我们采用混合数据源策略:
- 80%来自公开数据集(如BDD100K、LISA Traffic Light)
- 15%来自实地采集(使用车载摄像头)
- 5%为模拟数据(用于极端场景补充)
标注时特别注意三个要点:
- 交通灯状态分类:红/绿/黄/灭
- 灯组结构标注:箭头方向、倒计时显示
- 环境因素标注:逆光、夜间、雨雾等标签
重要提示:标注时务必保持灯组完整性,避免将单个灯泡作为检测目标,这会导致实际应用中出现误判。
2.2 数据增强策略
针对交通灯检测的特殊性,我们设计了分层增强方案:
| 增强类型 | 具体操作 | 适用场景 |
|---|---|---|
| 基础增强 | 色彩抖动、随机裁剪 | 所有数据 |
| 环境模拟 | 添加雨雾、运动模糊 | 晴天数据 |
| 极端情况 | 过曝/欠曝调整 | 测试集专用 |
实测表明,加入模拟遮挡(20%-30%遮挡率)能显著提升模型抗干扰能力。
3. 模型选型与优化
3.1 YOLOv5与v8的对比测试
我们在RTX 3060显卡上对比了两个版本的性能:
| 指标 | YOLOv5s | YOLOv8n |
|---|---|---|
| 参数量 | 7.2M | 3.2M |
| 推理速度 | 8.2ms | 6.5ms |
| mAP@0.5 | 0.89 | 0.91 |
| 显存占用 | 1.8GB | 1.2GB |
最终选择YOLOv8n作为基础模型,因其在保持精度的同时具有更好的实时性。
3.2 关键改进点
- 注意力机制改进:
class LightAttention(nn.Module): def __init__(self): super().__init__() self.conv = nn.Conv2d(64, 3, kernel_size=1) def forward(self, x): # 针对交通灯的色彩特征强化 rgb_weights = torch.sigmoid(self.conv(x)) return x * rgb_weights- 自适应锚框调整:
- 初始锚框:[[12,16], [19,36], [40,28]]
- 优化后:[[8,12], [15,24], [30,20]](更适合小目标检测)
- 分类头改进:
- 原始输出:红/绿/黄/灭
- 增加状态置信度:闪烁状态检测
4. 训练技巧与参数调优
4.1 关键训练参数
lr0: 0.01 # 初始学习率 lrf: 0.1 # 最终学习率系数 warmup_epochs: 3 # 热身训练 box: 0.05 # 框损失权重 cls: 0.5 # 分类损失权重 obj: 1.0 # 目标存在损失权重4.2 提升小目标检测的技巧
- 多尺度训练:
- 输入尺寸:640->896->1152 渐进增大
- 每10个epoch增加一次输入尺寸
- 负样本挖掘:
- 对误检区域进行重点采样
- 保持正负样本比例1:3
- 分类平衡策略:
- 使用Focal Loss解决红灯样本不足问题
- 类别权重:[1.0, 1.2, 1.5, 0.8](红/绿/黄/灭)
5. GUI界面开发与系统集成
5.1 PyQt5界面设计要点
采用模块化设计架构:
MainWindow ├── VideoLoader (视频/摄像头输入) ├── DetectionView (检测结果可视化) ├── LogPanel (状态日志) └── ControlPanel (参数调整)关键交互功能实现:
def update_result(self, results): # 结果可视化处理 for *xyxy, conf, cls in results: label = f'{self.classes[int(cls)]} {conf:.2f}' plot_one_box(xyxy, self.image, label=label, color=self.colors[int(cls)]) # 状态机判断 self.traffic_light_state_machine(cls)5.2 性能优化技巧
- 视频流处理:
- 使用OpenCV的DNN模块加速推理
- 采用双缓冲队列避免I/O阻塞
- 内存管理:
- 设置图像尺寸上限(1920x1080)
- 每10帧强制释放显存
- 状态机设计:
stateDiagram [*] --> Red Red --> Green: 持续3秒确认 Green --> Yellow: 检测到变化 Yellow --> Red: 持续1秒确认6. 部署与性能测试
6.1 不同平台的推理速度对比
测试环境:1080p视频,平均每帧检测目标数5个
| 平台 | 推理时间 | FPS | 功耗 |
|---|---|---|---|
| RTX 3080 | 8ms | 120 | 220W |
| Jetson Xavier | 35ms | 28 | 30W |
| Raspberry Pi 4 | 280ms | 3.5 | 5W |
6.2 实际道路测试结果
在100公里城市道路测试中:
| 场景 | 准确率 | 误检率 |
|---|---|---|
| 晴天日间 | 98.7% | 0.3% |
| 晴天逆光 | 95.2% | 1.1% |
| 夜间照明 | 93.8% | 1.5% |
| 雨天 | 90.1% | 2.3% |
主要误检来源:广告牌红黄色块、车尾灯集群。
7. 常见问题与解决方案
7.1 典型错误案例
- 红灯误判为黄灯:
- 原因:色域压缩导致红色饱和度降低
- 解决:在HSV空间增加红色范围阈值
- 远处小目标漏检:
- 原因:下采样丢失细节
- 解决:添加浅层特征融合分支
- 闪烁状态不稳定:
- 原因:单帧检测局限
- 解决:引入3帧滑动窗口投票机制
7.2 模型压缩技巧
- 通道剪枝:
- 对Conv层进行L1-norm排序
- 剪枝率控制在30%以内
- 量化部署:
# TensorRT量化示例 builder = trt.Builder(logger) network = builder.create_network() parser = trt.OnnxParser(network, logger) # 设置FP16模式 builder.fp16_mode = True- 知识蒸馏:
- 使用大模型生成软化标签
- 重点学习困难样本
这个项目最关键的收获是认识到交通灯检测不能单纯依赖视觉算法,必须结合场景理解。比如在十字路口,当检测到左转箭头红灯时,需要结合车道线信息判断是否适用于当前车辆。这些业务逻辑的融入,才是提升系统实用性的关键。