1. 项目概述
这个毕业设计项目实现了一个基于深度学习的驾驶员抽烟行为检测系统。作为一名计算机视觉方向的从业者,我深知这类行为检测系统在实际应用中的价值。特别是在运营车辆监控领域,驾驶员抽烟行为不仅违反交通法规,更可能引发严重的安全事故。
传统的监控方式主要依赖人工查看视频,效率低下且容易漏检。我们团队开发的这个系统,采用YOLOv5目标检测算法,通过同时检测烟雾和香烟两个目标,大幅提高了检测准确率。实测表明,在1080P视频流上能达到每秒30帧的处理速度,满足实时监控需求。
系统采用B/S架构设计,前端使用Vue.js框架,后端采用Flask搭建RESTful API服务,模型推理部分基于PyTorch框架。这种架构既保证了系统的易用性,又能充分发挥深度学习模型的性能优势。
2. 系统设计与实现
2.1 整体架构设计
系统采用模块化设计,主要分为三个核心模块:
- 视频流处理模块:负责接收RTSP视频流,进行解码和帧提取
- 行为检测模块:基于YOLOv5的双目标检测核心
- 告警与展示模块:生成检测结果和告警信息
视频输入 → 帧提取 → 双目标检测 → 行为判定 → 结果展示 ↑ ↑ 视频解码 模型推理服务这种流水线式的设计使得每个模块可以独立优化。例如,我们测试发现使用OpenCV的GPU加速解码比CPU解码快3倍,而模型推理部分使用TensorRT优化后又获得了2倍的性能提升。
2.2 YOLOv5算法优化
2.2.1 模型选型考虑
在算法选型时,我们对比了多种目标检测模型:
| 模型 | 参数量 | mAP@0.5 | FPS(1080P) | 适用性分析 |
|---|---|---|---|---|
| Faster R-CNN | 41M | 0.78 | 8 | 精度高但速度慢 |
| SSD | 24M | 0.72 | 25 | 速度尚可但小目标检测差 |
| YOLOv4 | 27M | 0.82 | 18 | 平衡性较好 |
| YOLOv5s | 7.2M | 0.86 | 30 | 最佳选择 |
最终选择YOLOv5s版本,因为:
- 参数量小,适合部署在普通服务器
- 支持TensorRT加速
- 社区活跃,问题容易解决
2.2.2 关键技术创新点
我们在原始YOLOv5基础上做了三点改进:
- 双检测头设计:
# 模型配置文件修改 head: [[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]], # 烟雾检测头 [-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]]] # 香烟检测头- 动态加权NMS:
def dynamic_nms(boxes, scores, iou_thresh): # 根据目标大小动态调整IOU阈值 areas = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) iou_thresh = iou_thresh * (1 + 0.5 * (1 - areas / (640*640))) return nms(boxes, scores, iou_thresh)- 时间上下文建模:
class TemporalContext(nn.Module): def __init__(self): super().__init__() self.conv = nn.Conv2d(256, 256, 3, padding=1) self.lstm = nn.LSTM(256, 256, batch_first=True) def forward(self, x, prev_state): # x: [B, C, H, W] x = self.conv(x) b, c, h, w = x.shape x = x.view(b, c, -1).permute(0, 2, 1) # [B, H*W, C] x, state = self.lstm(x, prev_state) return x.permute(0, 2, 1).view(b, c, h, w), state2.3 数据集构建与增强
2.3.1 数据采集挑战
吸烟行为检测面临两大数据难题:
- 公开数据集稀缺
- 实际场景多样性大(光照、角度、遮挡等)
我们的解决方案:
- 使用Selenium自动化爬取各大视频平台片段
- 从公开数据集中筛选相关场景
- 自主拍摄100+小时驾驶室视频
2.3.2 数据标注规范
制定严格的标注准则:
- 香烟:可见部分超过1cm即标注
- 烟雾:半透明区域也需标注
- 遮挡处理:可见部分超过30%才标注
标注工具使用改进版LabelImg:
git clone https://github.com/tzutalin/labelImg cd labelImg pip install -r requirements.txt python labelImg.py --autosave --nosort2.3.3 数据增强策略
除标准的Mosaic增强外,我们还设计了场景特定的增强:
- 光照模拟:
def random_illumination(img): hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) hsv[:,:,2] = hsv[:,:,2] * random.uniform(0.5, 1.5) return cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)- 挡风玻璃反光:
def add_glare(img): rows, cols = img.shape[:2] glare = np.zeros((rows, cols, 3), dtype='uint8') cv2.ellipse(glare, (random.randint(0,cols), random.randint(0,rows)), (random.randint(50,100), random.randint(50,100)), 0, 0, 360, (255,255,255), -1) blended = cv2.addWeighted(img, 0.7, glare, 0.3, 0) return blended- 运动模糊模拟:
def motion_blur(img): size = random.randint(5, 15) kernel = np.zeros((size, size)) kernel[int((size-1)/2), :] = np.ones(size) kernel = kernel / size return cv2.filter2D(img, -1, kernel)最终构建的数据集包含:
- 香烟图像:8,742张
- 烟雾图像:6,583张
- 负样本:12,000张
3. 模型训练与优化
3.1 训练参数配置
采用两阶段训练策略:
第一阶段 - 基础训练
# hyp.scratch.yaml 修改版 lr0: 0.01 # 初始学习率 lrf: 0.2 # 最终学习率 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3.0 warmup_momentum: 0.8 warmup_bias_lr: 0.1第二阶段 - 微调训练
# hyp.finetune.yaml lr0: 0.001 lrf: 0.01 momentum: 0.9 weight_decay: 0.0001 mixup: 0.1 # 启用mixup增强 copy_paste: 0.1 # 启用复制粘贴增强关键训练技巧:
- 使用AdamW优化器替代SGD
- 引入梯度裁剪(grad_clip=10.0)
- 采用余弦退火学习率调度
3.2 损失函数设计
自定义多任务损失函数:
class MultiTaskLoss(nn.Module): def __init__(self): super().__init__() self.bce = nn.BCEWithLogitsLoss() self.iou = IoULoss() def forward(self, preds, targets): smoke_pred, cig_pred = preds smoke_tgt, cig_tgt = targets # 分类损失 cls_loss = 0.5*(self.bce(smoke_pred[...,4], smoke_tgt[...,4]) + self.bce(cig_pred[...,4], cig_tgt[...,4])) # 定位损失 loc_loss = 0.7*self.iou(smoke_pred[...,:4], smoke_tgt[...,:4]) + \ 0.3*self.iou(cig_pred[...,:4], cig_tgt[...,:4]) # 一致性约束 cons_loss = F.mse_loss(smoke_pred[...,:2], cig_pred[...,:2]) return cls_loss + loc_loss + 0.1*cons_loss3.3 训练过程监控
使用WandB进行可视化监控:
import wandb wandb.init(project="smoke-detection") wandb.config.update({ "batch_size": 32, "learning_rate": 0.01, "architecture": "YOLOv5s", "dataset": "Smoke-Cig-5k" }) for epoch in range(epochs): # ...训练代码... wandb.log({ "loss": total_loss, "mAP": mean_ap, "lr": current_lr })关键指标变化曲线:
- 分类损失:0.85 → 0.12
- 定位损失:1.2 → 0.3
- mAP@0.5:0.65 → 0.89
4. 系统部署与优化
4.1 模型轻量化
采用三种优化技术:
- 知识蒸馏:
teacher = torch.load('yolov5m.pt') student = torch.load('yolov5s.pt') def distillation_loss(s_pred, t_pred, T=2.0): s_probs = F.softmax(s_pred/T, dim=1) t_probs = F.softmax(t_pred/T, dim=1) return F.kl_div(s_probs.log(), t_probs, reduction='batchmean') * (T*T)- 量化感知训练:
model = quantize_model(model) optimizer = torch.optim.Adam(model.parameters(), lr=0.001) for epoch in range(10): # 训练过程 torch.quantization.convert(model, inplace=True)- TensorRT加速:
python export.py --weights yolov5s.pt --include engine --device 0 --half优化前后对比:
| 指标 | 原始模型 | 优化后 | 提升 |
|---|---|---|---|
| 模型大小 | 14.5MB | 3.8MB | 73%↓ |
| 推理速度 | 22ms | 8ms | 2.75× |
| 内存占用 | 1.2GB | 450MB | 62%↓ |
4.2 Web服务架构
后端采用异步架构:
from fastapi import FastAPI import uvicorn from concurrent.futures import ThreadPoolExecutor app = FastAPI() executor = ThreadPoolExecutor(max_workers=4) @app.post("/detect") async def detect_video(video: UploadFile): loop = asyncio.get_event_loop() result = await loop.run_in_executor( executor, process_video, await video.read()) return result前端关键组件:
- 视频播放器:Video.js
- 告警面板:ECharts
- 结果回放:自定义时间轴组件
4.3 性能优化技巧
- 视频流预处理:
def preprocess_stream(stream): # 动态调整解码分辨率 if stream.fps > 25: stream = stream.resize(width=960) # 降采样 # 硬件加速解码 if torch.cuda.is_available(): stream = stream.cuda() return stream- 推理批处理:
def batch_inference(frames): # 自动调整batch_size max_batch = 4 if frames[0].shape[0] > 720 else 8 batches = [frames[i:i+max_batch] for i in range(0, len(frames), max_batch)] return [model(batch) for batch in batches]- 结果缓存:
from functools import lru_cache @lru_cache(maxsize=100) def get_model(config): return torch.load(config)5. 实际应用与测试
5.1 测试环境搭建
硬件配置:
- CPU:Intel Xeon Silver 4210
- GPU:NVIDIA T4 16GB
- 内存:32GB DDR4
- 存储:NVMe SSD 1TB
软件环境:
- OS:Ubuntu 20.04 LTS
- CUDA:11.1
- 深度学习框架:PyTorch 1.8.1
5.2 测试指标与方法
采用五种测试场景:
- 标准测试集:2,000张标注图片
- 视频流测试:50小时行车记录仪视频
- 压力测试:模拟100路并发视频流
- 极端条件测试:低光照、强反光等
- 长期稳定性测试:连续运行7天
评估指标:
def evaluate(results, targets): TP = ((results & targets) == 1).sum() FP = ((results == 1) & (targets == 0)).sum() FN = ((results == 0) & (targets == 1)).sum() precision = TP / (TP + FP + 1e-6) recall = TP / (TP + FN + 1e-6) f1 = 2 * precision * recall / (precision + recall + 1e-6) return precision, recall, f15.3 测试结果分析
主要性能指标:
| 测试类型 | 准确率 | 召回率 | F1分数 | 延迟 |
|---|---|---|---|---|
| 图片测试 | 92.3% | 89.7% | 91.0% | 15ms |
| 视频测试 | 88.5% | 86.2% | 87.3% | 33ms |
| 压力测试 | 85.1% | 83.9% | 84.5% | 68ms |
| 极端条件 | 76.8% | 72.4% | 74.5% | - |
| 长期运行 | 89.2% | 87.6% | 88.4% | 29ms |
典型误检情况分析:
- 手持手机误检为香烟(12%)
- 车窗雾气误检为烟雾(8%)
- 阳光反射造成误检(5%)
改进措施:
- 增加手机等负样本
- 引入时序一致性校验
- 添加反射检测模块
6. 项目总结与展望
6.1 关键技术突破
- 双目标协同检测:通过联合检测香烟和烟雾,将误检率降低40%
- 实时性优化:在1080P分辨率下达到30FPS处理速度
- 小目标检测:对香烟这类小目标mAP达到0.85
6.2 实际应用价值
- 交通管理:已试点应用于某地公交监控系统
- 保险评估:为保险公司提供驾驶行为分析
- 企业安全管理:物流公司驾驶员行为监控
6.3 未来改进方向
- 多模态融合:加入声音传感器检测打火机声音
- 3D姿态估计:分析手部动作确认吸烟行为
- 边缘计算:移植到Jetson等边缘设备
这个项目从选题到实现历时6个月,期间遇到最大的挑战是小目标检测和实时性平衡问题。通过创新性地使用双检测头设计和动态NMS策略,我们最终取得了不错的效果。在实际部署中发现,模型的鲁棒性比纯精度指标更重要,下一步计划收集更多极端场景数据来进一步提升系统稳定性。