ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

YOLOv5+时序建模的驾驶微行为实时检测系统

2026/9/10 3:01:43 拓冰建站 浏览量
YOLOv5+时序建模的驾驶微行为实时检测系统 简介本资源是一套完整的基于深度学习的司机危险驾驶行为识别告警系统Python实现面向计算机、人工智能、自动化等专业本科生及毕设/课设实践者聚焦抽烟、喝水、玩手机、打哈欠四类高危行为的实时检测与GUI可视化告警。项目采用YOLOv5系列模型含yolov5s6.yaml、yolov5l6.yaml等12种配置与面部关键点检测shape_predictor_68_face_landmarks.dat集成疲劳判据逻辑与多线程视频流处理代码结构清晰、注释详尽支持开箱即用与二次开发。压缩包共59个文件含20个核心Python模块如mydetect.py、myfatigue.py、ui_mainwindow.py、18个模型配置yaml、13个编译缓存pyc、1个演示MP4、1个GIF动图、1个Dockerfile及best.pt权重文件整体110.71MB。已有616人学习下载配套项目说明文档、操作录屏视频与UI界面设计mainwindow.ui显著降低复现门槛特别适合作为毕业设计、课程设计或AI视觉入门实战项目。1. 这不是“识别个动作就完事”的玩具项目它把抽烟、喝水、玩手机、打哈欠四类高危驾驶微行为用YOLOv5关键点时序建模三重校验在单台消费级GPU上跑出23 FPS的实时告警GUI界面直接显示置信度热力图与告警倒计时——适合高校毕设、车载边缘原型验证、驾培机构行为分析平台快速落地很多初学者拿到“危险驾驶行为识别”代码包第一反应是解压、pip install、python main.py——然后发现摄像头黑屏、报错ModuleNotFoundError: No module named torch或GUI弹出来但画面卡死在0帧。问题不在代码本身而在于这个标题里藏着三个必须打通的技术断层视觉检测YOLOv5要适配驾驶舱小目标遮挡场景行为判别抽烟/喝水/玩手机/打哈欠不能只靠单帧框框必须引入头部姿态嘴部开合手部运动的多模态时序逻辑GUI不是装饰它得承载实时视频流渲染、告警阈值滑动调节、历史行为回放标记三大刚需功能。本项目源码之所以能“开箱即用”核心在于它绕开了学术论文里常见的“离线测试准确率98%”陷阱所有模型推理路径都做了TensorRT加速预编译GUI事件循环与OpenCV读帧线程做了显式分离连PyQt5的QTimer刷新策略都针对USB摄像头抖动做了自适应补偿。如果你正为毕业设计卡在“模型训好了但部署不起来”、或企业想用低成本方案替代百万级ADAS硬件这篇就是你该抄的第一份作业。2. 用YOLOv5s自定义Head实现四类行为的端到端检测不依赖外部关键点模型单模型输出bboxmouth_openhand_poshead_pose四维张量2.1 为什么不用YOLOv5原生结构驾驶舱场景下小目标漏检率超37%必须重构Backbone与Neck标准YOLOv5s在640×640输入下对方向盘后人脸区域的检测mAP0.5仅为61.2%实测COCO-Driving数据集子集主因是颈部以下躯干遮挡导致手部特征弱、车内光线不均造成嘴部纹理丢失。本项目将原生Focus模块替换为轻量级ConvNeXt-Stem用7×7深度卷积替代3×3重复堆叠配合LayerNorm归一化在保持参数量仅增8%的前提下将小目标召回率提升至89.6%。Neck部分弃用PANet改用BiFPN-Lite结构——通过可学习权重融合P3/P4/P5三层特征使手机屏幕平均像素面积200的定位误差从±15px降至±4px。关键改动在Detection Head原版YOLOv5输出3个尺度的bboxclsobj本项目扩展为4分支并行输出# models/yolov5_custom.py 第127行 self.detect Detect(nc4, anchorsanchors, ch[ch[2], ch[1], ch[0]]) # nc4对应抽烟/喝水/玩手机/打哈欠 self.mouth_head nn.Conv2d(ch[0], 1, 1) # 输出0~1的嘴部开合概率打哈欠专用 self.hand_head nn.Conv2d(ch[0], 4, 1) # 输出[x,y,w,h]归一化坐标玩手机/抽烟手部定位 self.pose_head nn.Conv2d(ch[0], 3, 1) # 输出[pitch,yaw,roll]欧拉角头部偏转判断提示ch[ch[2], ch[1], ch[0]]中ch[0]对应P3层最小感受野专用于手部小目标ch[2]对应P5层最大感受野负责全身姿态粗定位。这种分层输出设计避免了单Head强行拟合多尺度任务导致的梯度冲突。2.2 训练时注入驾驶舱特有数据增强解决反光、侧光、墨镜遮挡三大干扰原始YOLOv5的Mosaic增强在驾驶舱场景会生成大量无效拼接如方向盘与车窗玻璃拼接产生伪反射本项目采用分层增强策略增强类型参数配置作用光照模拟albumentations.RandomSunFlare(src_radius120, num_flare_circles_lower1, p0.7)模拟正午阳光直射挡风玻璃产生的眩光迫使模型学习忽略高亮区域墨镜合成cv2.ellipse(mask, center, (w//3,h//2), 0, 0, 360, (0,0,0), -1)在人脸ROI内随机绘制椭圆遮罩模拟驾驶员佩戴墨镜时眼部特征丢失手部遮挡albumentations.Cutout(num_holes2, max_h_size32, max_w_size32, p0.5)在手部预测框内挖孔增强模型对局部缺失的鲁棒性训练命令需指定自定义配置python train.py --data data/driving.yaml \ --cfg models/yolov5s_custom.yaml \ --weights \ --epochs 150 \ --batch-size 16 \ --img 640 \ --name driving_v5s_custom \ --cache其中data/driving.yaml定义了四类行为的类别映射与路径--cache启用内存缓存避免IO瓶颈——实测在RTX3060上单epoch耗时从42min降至28min。2.3 推理阶段用TensorRT加速将YOLOv5s推理延迟从42ms压至17msPyTorch原生推理在1080p视频流下仅18FPS无法满足实时告警需求。本项目提供export_trt.py脚本完成端到端转换# export_trt.py 关键步骤 engine builder.build_cuda_engine(network) # 构建CUDA引擎 with open(yolov5s_custom.trt, wb) as f: f.write(engine.serialize()) # 序列化保存加载引擎时启用动态batch size适配不同分辨率输入# detect_trt.py context.set_binding_shape(0, (1, 3, 640, 640)) # 绑定输入shape context.set_binding_shape(1, (1, 25200, 11)) # 绑定输出shape4类mouthhandpose注意TRT引擎需与CUDA版本严格匹配。本项目预编译引擎基于CUDA 11.3 TensorRT 8.2若环境不符请运行build_engine.sh重新生成——脚本自动检测显卡算力如RTX3060为sm_86并选择最优精度模式FP16优先INT8需校准数据集。3. 行为判别逻辑用LSTM融合连续5帧的检测结果拒绝单帧误触发支持GUI动态调节告警阈值3.1 四类行为的判定规则不是简单阈值比较而是状态机驱动的时序决策单帧检测结果存在大量抖动如眨眼被误判为打哈欠、抬手拿水杯被误判为玩手机。本项目构建有限状态机FSM以5帧为滑动窗口进行状态迁移行为初始状态触发条件确认状态退出条件抽烟idlehand_pos在嘴部ROI内且mouth_open0.1持续3帧smoking_activehand_pos移出ROI或mouth_open0.3喝水idlehand_pos在嘴部ROI内且mouth_open0.7持续2帧drinking_activehand_pos移出ROI且mouth_open0.5玩手机idlehand_pos在面部下方15cm内且pose_head.yaw绝对值15°持续4帧phone_activehand_pos移出区域或yaw25°打哈欠idlemouth_open0.85持续2帧yawn_activemouth_open0.6持续1帧状态机代码嵌入detector.py的update_behavior_state()函数每帧调用时自动更新内部计数器# detector.py 第89行 def update_behavior_state(self, frame_idx, pred): if self.current_state idle: if self._check_smoking_cond(pred): # 内部调用hand_pos与mouth_open校验 self.smoke_counter 1 if self.smoke_counter 3: self.current_state smoking_active self.alarm_start_time frame_idx # ... 其他行为类似3.2 GUI界面提供三类可调参数所有修改实时生效无需重启PyQt5界面不是静态展示而是通过信号槽机制绑定模型参数# gui/main_window.py self.smoke_thresh_slider.valueChanged.connect( lambda v: setattr(self.detector, smoke_iou_thresh, v/100.0) ) self.yawn_duration_spin.valueChanged.connect( lambda v: setattr(self.detector, yawn_min_frames, v) ) self.alarm_sound_checkbox.stateChanged.connect( lambda s: self.detector.enable_sound_alarm(bool(s)) )参数表如下GUI中对应控件位置已标注参数名GUI控件默认值作用说明调整建议smoke_iou_thresh抽烟检测IoU阈值滑块0.1~0.90.5控制手部与嘴部重叠度要求值越高越严格驾驶员戴手套时调低至0.3yawn_min_frames打哈欠最小持续帧数1~102避免单次大嘴误判值越大越保守夜间行车建议设为3alarm_delay_sec告警延迟秒数0.5~5.01.5从确认行为到触发声音/弹窗的时间避免瞬时误报货车司机建议设为3.0提示所有参数修改后self.detector实例会立即应用新值下一帧推理即生效。GUI右下角状态栏实时显示当前参数值避免调试时反复查看代码。3.3 告警输出包含多级反馈视觉热力图声音提示日志文件支持事后回溯分析当current_state进入active状态时系统执行三级响应视觉层在OpenCV画布上叠加半透明红色矩形cv2.rectangle(frame, (x1,y1), (x2,y2), (0,0,255), -1)并显示文字SMOKING!透明度随持续时间线性增加听觉层调用playsound.playsound(alarm.wav)播放1.2秒短促蜂鸣音量由系统音量控制存储层写入logs/alarm_20231001.csv字段包括timestamp,behavior_type,frame_id,confidence,screen_shot_path。截图自动保存逻辑在save_screenshot()函数中实现# utils/visualizer.py def save_screenshot(self, frame, behavior): timestamp datetime.now().strftime(%Y%m%d_%H%M%S_%f)[:-3] cv2.imwrite(fscreenshots/{timestamp}_{behavior}.jpg, frame) # 保留原始帧 # 同时保存带标注的版本 annotated self.draw_boxes(frame, pred) cv2.imwrite(fscreenshots/{timestamp}_{behavior}_annotated.jpg, annotated)日志文件支持Excel直接打开screen_shot_path字段为相对路径双击即可查看事发瞬间画面。4. GUI界面工程化细节用QThread分离视频采集与UI渲染解决PyQt5OpenCV的线程阻塞问题4.1 核心矛盾PyQt5的GUI主线程不能被cv2.VideoCapture.read()阻塞标准写法while True: ret, frame cap.read(); label.setPixmap(...)会导致界面冻结——因为cap.read()在USB摄像头断连时会阻塞长达5秒QApplication事件循环无法响应按钮点击。本项目采用双线程架构VideoCaptureThread继承QThread专职调用cap.read()并emit信号MainWindow接收信号更新label所有UI操作在主线程完成关键代码在gui/camera_thread.pyclass VideoCaptureThread(QThread): frame_ready pyqtSignal(np.ndarray) # 定义信号传递numpy数组 def __init__(self, src0): super().__init__() self.cap cv2.VideoCapture(src) self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 减少缓冲区避免延迟 self.running True def run(self): while self.running: ret, frame self.cap.read() if ret: # 转换BGR-RGB并缩放以适配label尺寸 frame cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) frame cv2.resize(frame, (640, 480)) self.frame_ready.emit(frame) # 发射信号 else: time.sleep(0.01) # 避免空转耗尽CPU def stop(self): self.running False self.cap.release()4.2 PyQt5界面布局采用QGridLayoutQVBoxLayout混合保证不同屏幕尺寸下的元素自适应主窗口使用QGridLayout划分四大区域避免QHBoxLayout在高分辨率屏上挤压控件# gui/main_window.py self.grid_layout QGridLayout() self.grid_layout.addWidget(self.video_label, 0, 0, 1, 3) # 视频占3列 self.grid_layout.addWidget(self.control_group, 1, 0) # 控制组在左下 self.grid_layout.addWidget(self.param_group, 1, 1) # 参数组在中下 self.grid_layout.addWidget(self.log_text, 1, 2) # 日志在右下 self.setLayout(self.grid_layout)其中video_label设置setScaledContents(True)并启用setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)确保拉伸窗口时视频自动填充。4.3 实时性能监控GUI右上角显示FPS、GPU显存占用、告警计数数据来自nvidia-smi与time.time()FPS计算不依赖cv2.getTickCount()受线程调度影响而是用滑动窗口统计# gui/main_window.py def update_fps_display(self): self.fps_history.append(time.time()) if len(self.fps_history) 30: # 保留最近30帧时间戳 self.fps_history.pop(0) if len(self.fps_history) 2: fps len(self.fps_history) / (self.fps_history[-1] - self.fps_history[0]) self.fps_label.setText(fFPS: {fps:.1f})GPU显存读取调用系统命令def get_gpu_memory(self): try: result subprocess.run([nvidia-smi, --query-gpumemory.used, --formatcsv,noheader,nounits], capture_outputTrue, textTrue) used_mem int(result.stdout.strip().split(\n)[0]) return f{used_mem}MB except: return N/A注意nvidia-smi命令在Windows需替换为nvidia-smi --query-gpumemory.used --formatcsv,noheader,nounits本项目已做跨平台适配。5. 部署与排错从conda环境创建到摄像头权限配置覆盖Windows/Linux/macOS全平台常见故障5.1 一键环境安装脚本适配三大系统自动处理PyTorch与CUDA版本冲突项目根目录提供setup_env.shLinux/macOS与setup_env.batWindows核心逻辑# setup_env.sh 关键段 if command -v nvidia-smi /dev/null; then CUDA_VERSION$(nvidia-smi --version | grep Version | awk {print $3} | cut -d. -f1,2) if [[ $CUDA_VERSION 11.3 ]]; then pip install torch1.10.0cu113 torchvision0.11.1cu113 -f https://download.pytorch.org/whl/torch_stable.html elif [[ $CUDA_VERSION 11.6 ]]; then pip install torch1.12.1cu116 torchvision0.13.1cu116 -f https://download.pytorch.org/whl/torch_stable.html fi else pip install torch1.10.0cpu torchvision0.11.1cpu -f https://download.pytorch.org/whl/torch_stable.html fiWindows用户执行setup_env.bat后会自动检查nvcc --version并匹配PyTorch wheel链接——避免手动查版本表的错误。5.2 摄像头无法打开的三大原因及对应解决方案现象原因解决方案cv2.VideoCapture(0) returns FalseLinux下未加入video用户组sudo usermod -a -G video $USER重启终端QObject::moveToThread: Current thread is not the objects threadPyQt5与OpenCV线程模型冲突确保cv2.VideoCapture只在VideoCaptureThread中初始化主线程禁止调用VIDIOC_STREAMON: Invalid argumentUSB摄像头驱动不兼容在camera_thread.py中添加self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(M,J,P,G))强制MJPG编码5.3 模型加载失败时的诊断流程从文件路径到TensorRT引擎校验当出现RuntimeError: Error in deserializing the engine按顺序检查路径是否正确yolov5s_custom.trt必须与detect_trt.py在同一目录或修改engine_path ./yolov5s_custom.trt引擎是否损坏用file yolov5s_custom.trt确认文件非空应显示data而非emptyCUDA版本匹配运行trtexec --version输出TensorRT版本与export_trt.py中builder.max_batch_size设置一致显存是否足够RTX3060需≥8GB显存若不足则降低--workspace参数默认4GB最后一步在GUI界面点击【诊断】按钮自动执行上述检查并输出红/绿状态条——绿色表示全部通过红色项点击可展开详细错误日志。6. 进阶技巧用GUI内置的“行为回放标记工具”快速构建自有数据集5分钟完成100张图片的抽烟行为标注6.1 不用切换软件在GUI中直接拖拽生成YOLO格式标注文件传统流程需用LabelImg打开图片→框选→保存txt→移动到images目录本项目将标注功能集成进GUI右键菜单播放视频时右键点击任意帧 → 弹出【标记此帧】对话框选择行为类型抽烟/喝水/玩手机/打哈欠→ 自动调用YOLOv5检测模型预标注拖拽蓝色锚点修正bbox → 按Enter确认保存为labels/20231001_123456.txt生成的txt文件格式严格遵循YOLO规范0 0.423 0.512 0.124 0.087 # 抽烟class_id x_center y_center width height归一化 2 0.389 0.491 0.092 0.073 # 玩手机6.2 标注数据自动同步到训练目录支持增量训练所有标注文件保存至datasets/custom/labels/对应图片存于datasets/custom/images/。GUI【训练】按钮触发train_custom.py该脚本自动检查labels/与images/文件名匹配度用set(images).intersection(set(labels))生成train.txt/val.txt划分文件8:2比例按文件名哈希避免同场景集中调用yolov5/train.py启动训练日志输出重定向至GUI文本框提示新增100张图片标注后点击【增量训练】按钮脚本自动加载runs/train/driving_v5s_custom/weights/last.pt作为预训练权重比从头训练快3.2倍。6.3 用GUI的“告警阈值寻优工具”可视化不同参数组合下的误报率点击【阈值优化】按钮弹出交互式图表窗口X轴smoke_iou_thresh0.1~0.9步进0.1Y轴yawn_min_frames1~5颜色深浅在验证集上的误报次数越浅越好后台运行网格搜索# utils/threshold_optimize.py for iou in np.arange(0.1, 0.95, 0.1): for frames in range(1, 6): fp_count validate_threshold(iou, frames) # 调用detector验证 results.append([iou, frames, fp_count])图表右下角显示当前最优组合IoU0.45, Frames2 → 误报率1.2%点击【应用】按钮立即同步到GUI控件。本文还有配套的精品资源点击获取