简介这是基于YOLOv5与DeepSORT实现驾驶员分心驾驶行为预警监测的完整工程面向深度学习、计算机视觉方向的毕设学生与项目开发者可用于疲劳状态识别、危险动作检测等实时预警场景。紧凑包内共60个文件涵盖20个Python源码脚本、18个YAML模型配置文件、训练好的模型权重与脸部关键点数据同时附带GUI界面文件、演示视频及说明文档整体大小约110.69MB结构清晰便于直接部署调试。目前已有121人学习查看项目经本地编译验证可运行评审得分达98分属于难度适中的高分毕设资源。资源内不仅包含主检测流程、疲劳判定逻辑、界面交互模块等代码还提供了数据集、模型文件与运行录屏可帮助使用者快速理解从目标检测到多目标跟踪的完整链路并直接用于毕业设计、期末大作业或课程设计。1. 驾驶员分心预警这套源码为什么直接能跑而不只是能看拿到一套驾驶员分心检测的项目最怕的是“代码很全、跑不起来”。这套基于YOLOv5DeepsortPython实现的源码把检测、跟踪、疲劳判定和GUI界面搭成了完整链路YOLOv5负责从视频流里锁定驾驶员人脸和危险行为目标Deepsort负责在视频序列里稳住每个目标的IDdlib的68点关键点模型单独撑起闭眼和打哈欠的疲劳判定最后通过PyQt5界面把实时检测结果和报警状态展示出来。我拆完整目录之后确认best.pt权重、人脸关键点模型、演示视频和数据集都在包里确实按“能演示、能答辩”的标准做的。它适合正在做毕设、需要一套完整系统的同学也适合课程设计做到后半程、想借鉴一条成熟检测链路的人。2. 先看清推理链路YOLOv5检测、Deepsort跟踪与疲劳判定如何串成一条线整套系统的推理链路拆开看是四段视频帧进来后YOLOv5做目标检测把驾驶员的脸和危险行为目标框出来Deepsort接手检测框在时序上做多目标跟踪给每个目标一个稳定ID随后dlib的68点关键点模型在人脸框内取眼睛轮廓点用EAR公式算出开眼程度最后由myfatigue.py按连续帧数累计疲劳得分。下面按代码里的模块顺序把这四段拆开讲。2.1 mydetect.py单帧检测做了什么做驾驶行为监测最容易犯的错是把检测器当成全部。实际YOLOv5的输出只是一堆框每个框带xyxy坐标、类别ID和置信度。mydetect.py封装的就是这一步加载best.pt把输入帧缩放成检测器需要的640×640跑一次前向推理再把结果恢复到原始分辨率。# mydetect.py 的核心检测流程简化 def detect_frame(frame, model, conf_thres0.5, iou_thres0.45): # 预处理letterbox等比缩放保持宽高比不变 img, ratio, (pad_w, pad_h) letterbox(frame, new_shape640) img img[:, :, ::-1].transpose(2, 0, 1) # BGR转RGBHWC转CHW img np.ascontiguousarray(img) # 前向推理返回目标框 results model(img, size640)[0] # 把框还原到原图坐标去掉letterbox的pad dets results.xyxy[0].cpu().numpy() return [det for det in dets if det[4] conf_thres]逻辑说明letterbox是做等比缩放四周用灰边填充避免直接拉伸导致目标变形results.xyxy[0]里的xyxy是目标框左上角和右下角的坐标第5列是置信度第6列是类别ID。参数说明new_shape640要和训练时保持一致改到416会更快但小目标容易漏conf_thres0.5是置信度阈值调低会引入更多误检但在驾驶员场景里漏检比误检更致命——司机低头的那几帧如果没框住疲劳判断就断了。2.2 Deepsort跟踪为什么单帧检测不够单帧检测最大的问题是抖动同一张脸这一帧框出来了下一帧因为头部转动或遮挡漏检再下一帧又出现于是同一个驾驶员会变成两个目标。Deepsort用卡尔曼滤波预测目标位置再用匈牙利算法把当前帧检测框和上一帧轨迹做匹配让每个驾驶员维持一个稳定ID。# 跟踪状态维护的常见写法 tracker DeepSort(model_pathweights/deepsort.t7) ... bbox_xywh xyxy2xywh(det[:, :4]) # xyxy转成中心点宽高 outputs tracker.update(bbox_xywh, det[:, 4], det[:, 5], frame)逻辑说明DeepSort.update()输入的是当前帧检测结果内部做预测和匹配输出带track_id的跟踪框。在分心驾驶监控里疲劳分数是按人累计的ID一旦跳变前面累计的闭眼帧数就清零重来所以跟踪质量直接影响疲劳判定连续性。参数说明bbox_xywh需要中心点坐标加宽高不能直接喂xyxydet[:, 4]是置信度、det[:, 5]是类别IDDeepsort在关联时会把低置信度的框过滤掉。2.3 68点关键点与EAR公式疲劳判定不是玄学疲劳判定的输入是人眼状态。shape_predictor_68_face_landmarks.dat是dlib预训练的68点人脸关键点模型能从人脸框里取到眼睛周围6个点用EAR眼纵横比判断眼睛是否闭合。def eye_aspect_ratio(eye): # 传入单眼6个关键点计算EAR p1, p4 eye[0], eye[3] # 水平方向两点 p2, p3 eye[1], eye[2] # 垂直方向两组点 p5, p6 eye[4], eye[5] vertical (np.linalg.norm(p2 - p6) np.linalg.norm(p3 - p5)) / 2.0 horizontal np.linalg.norm(p1 - p4) return vertical / horizontal逻辑说明EAR的计算原理是“眼睛高度除以宽度”。睁眼时垂直距离占水平距离比例约0.25闭眼时垂直距离趋近于零EAR掉到0.1以下。参数说明myfatigue.py里一般设两个阈值——EAR绝对值比如0.2判断眼睛是否闭合闭合持续帧数比如连续20帧判断是否进入疲劳。光看单帧EAR不够因为眨眼也是闭合状态必须用连续帧数把眨眼和闭眼区分开这是很多初版代码漏掉的细节。2.4 三条线怎么汇合mydetect.py出框myframe.py负责帧预处理和跟踪器状态维护myfatigue.py拿关键点算分数main.py里用线程把这三段接到GUI上。这个拆法也决定了你后续改功能时的切入点想加打哈欠检测就去myfatigue.py里加嘴部MAR指标想加手机使用检测就在YOLO目标列表里加类别跟踪器完全不用动。3. 把工程跑起来环境搭配、三个入口脚本与最小启动命令拿到源码先别急着双击main.py。我见过太多人一上来就跑GUI结果界面弹出来立刻报错分不清是环境问题还是代码问题。正确顺序是先理清入口再按部就班验证。3.1 版本搭配能用就不要追新这个项目涉及的库偏老Python 3.8是首选。PyQt5负责界面dlib是关键点模型运行环境opencv-python做视频读写。dlib的安装是整条链路里最容易翻车的一环后面避坑章我会专门展开。依赖库推荐版本作用Python3.8兼容性最稳torch1.10.xYOLOv5推理和训练opencv-python4.5.x视频读写、图像缩放、画框PyQt55.15.xGUI界面dlib19.22.x人脸68点关键点提取numpy1.21.x数值计算scipy1.7.xDeepsort的线性分配依赖版本建议是“能用就不升级”。torch超过2.0的话部分YOLOv5旧代码里model(img, size640)的写法会报错因为新版本接口改成了model(img, imgsz640)。如果确实用高版本torch改这一行就好。3.2 三个入口脚本先分清main.py是GUI总入口启动后能在界面上选择视频或摄像头实时显示检测结果和疲劳状态。mydetect.py是纯检测入口适合先验证权重和视频是否正常。myfatigue.py是疲劳检测专用入口输出闭眼和哈欠的判断结果适合单独调阈值。# 1. 跑通GUI python main.py # 2. 用视频验证检测链路 python mydetect.py --source demo.mp4 --weights weights/best.pt --conf-thres 0.5 # 3. 单独调疲劳判定阈值 python myfatigue.py逻辑说明第一次跑通建议用视频不要直接上摄像头。视频出错你能看到帧卡在哪一步摄像头出错你会分不清是硬件问题还是代码问题。参数说明--source指定输入源可以是视频文件路径、摄像头索引0或图片目录--conf-thres是置信度阈值和检测脚本里的conf_thres保持一致如果摄像头输出画面是黑屏先检查cap cv2.VideoCapture(0)里的0是不是被占用。3.3 目录结构里的小细节mainwindow.ui是Qt Designer生成的界面文件ui_mainwindow.py由pyuic5生成。如果你要改界面布局用Qt Designer打开ui文件修改再重新生成py文件不要直接改ui_mainwindow.py不然下次生成全被覆盖。images目录里那个gif是测试素材可以用来快速验证检测效果。4. 换数据重训自己的模型数据集结构、训练命令与效果判断用现成best.pt能跑通但毕设答辩时老师大概率会问“模型是你自己训的吗”。所以这一章讲怎么把这套代码的模型换成自己训练的。4.1 数据集标注格式先对齐YOLOv5训练用的是YOLO格式的txt标注每行一个目标类别ID、中心点x、中心点y、宽度、高度全部归一化到0到1。注意不是像素坐标是相对原图的比值。datasets/ mydriver/ images/ train/ img001.jpg val/ img002.jpg labels/ train/ img001.txt val/ img002.txt标注文件里每一行对应图片里的一个目标比如0 0.5 0.45 0.3 0.2 1 0.6 0.3 0.2 0.18第一列是类别ID后面四列是归一化后的框坐标。如果你手里只有VOC格式的xml标注需要先转成这个格式网上有转换脚本注意类别顺序要和训练yaml里的names一致。4.2 训练配置自定义yaml文件在数据集同级目录放一个mydata.yaml定义路径、类别数和类别名。# mydata.yaml train: datasets/mydriver/images/train val: datasets/mydriver/images/val nc: 3 names: [face, eye, phone]参数说明nc是类别总数必须和标注文件里的最大类别ID1相等names的顺序决定了推理时显示的目标名称和标注txt里的类别ID一一对应搞反了会出现模型检测到的“face”实际是“phone”的情况。4.3 训练命令与参数解读python train.py --data mydata.yaml --weights yolov5s.pt --epochs 100 --batch-size 16 --img 640 --device 0参数说明--weights yolov5s.pt表示用COCO预训练权重做迁移学习训练速度比从零开始快很多--epochs 100对毕设场景够用再多容易过拟合体现在推理时对训练集之外的角度频繁漏检--batch-size 16在8GB显存上勉强能跑显存不够就降到8--img 640和推理时的输入尺寸保持一致。训练过程中可以看到每个epoch输出box_loss、obj_loss、cls_loss还有mAP0.5等指标。第一次训练建议把--epochs降到50跑通流程确认数据加载和标注没问题再拉满时长不然训到第80个epoch才发现数据格式错了血亏。4.4 autoanchor要不要关YOLOv5训练前会自动分析数据集的标注框尺寸分布重新计算anchor尺寸这个机制叫autoanchor。如果你的目标框和COCO默认尺寸差异较大比如人脸框偏大、手机框偏小自动计算是好事。但某些版本里anchor变化会导致前几个epoch的mAP抖动第一次训练时如果看到mAP跳得厉害可以在命令里加--noautoanchor关掉自动计算用默认anchor再训一次对比。4.5 训练结果怎么判断训练完成后runs/train/exp/weights/下会有best.pt和last.pt其中best.pt是验证集上表现最好的一版。替换掉原工程里的weights/best.pt就完成了模型交接。替换之前要看一个避坑点验证集mAP高不等于实际视频里表现好。模型指标好但真实视频里司机低头不报警多半是训练集里这类遮挡或暗光场景太少需要补充数据而不是加训练轮数。5. 避坑指南五个真实翻车现场和对应解法整套工程跑下来我替大家把最容易卡住的五个环节列出来每一条都是实际见过的问题。5.1 现象dllib导入直接报错现象import dlib报DLL load failed程序在关键点检测那一步直接退出。原因dlib 19.22在Windows上编译需要Visual Studio C环境直接pip install dlib装的版本往往和Python 3.8不匹配。解决下载预编译的whl文件安装或者用conda install -c conda-forge dlib。装完之后用python -c import dlib验证能不能导入成功再做下一步。5.2 现象模型加载路径报错现象运行报FileNotFoundError: weights/best.pt或提示找不到shape_predictor_68_face_landmarks.dat。原因在IDE或终端里执行的当前目录和脚本所在目录不一致相对路径失效。解决用__file__拼出脚本所在的绝对路径。import os BASE_DIR os.path.dirname(os.path.abspath(__file__)) WEIGHTS os.path.join(BASE_DIR, weights, best.pt) DAT_FILE os.path.join(BASE_DIR, shape_predictor_68_face_landmarks.dat)逻辑说明os.path.abspath(__file__)取当前脚本的绝对路径dirname取所在目录这样无论你在哪个目录启动python都不会找不到模型文件。这是多机多人协作时最常见的埋雷点。5.3 现象GUI点了开始检测直接卡死现象界面能启动但点击“开始检测”后窗口立即无响应出现转圈或白屏。原因检测循环写在了Qt主线程里视频推理加上绘制把界面事件循环阻塞了。解决把检测逻辑放进QThread子线程帧和检测结果通过信号传回主线程刷新。关键点检测模型初始化很慢一定要放到线程启动时只做一次不能每帧初始化。5.4 现象跟踪ID乱跳一个人变成两个人现象视频里驾驶员头部转动时检测框的ID从1跳到2疲劳累计被断掉。原因置信度阈值太低Deepsort把很多低质量检测框也拿去关联了导致轨迹频繁分裂。解决把conf_thres从0.5提高到0.6同时检查iou_thres不要设得过大。Deepsort的max_age参数控制目标消失多少帧后删除轨迹设太大会留着错误轨迹设太小跟踪容易断一般从30起步调。5.5 现象训练时报CUDA out of memory现象训练刚开始就报错GPU显存直接被占满。原因batch-size、输入分辨率和模型结构三者叠加超出了显存容量。解决先把--batch-size降到8甚至4再把--img从640降到512。如果还不行就换更小的yolov5s.yaml模型结构不要硬扛。提示训练前用nvidia-smi看一眼显存占用如果已经被其他进程占了大半先把别人蹭显存的任务清掉再训。6. 答辩演示前最后一步用三个维度验证整套系统跑通以后别急着录演示视频先花十分钟做一次系统的验证把三件事确认明白。第一单帧检测维度。挑一段包含正常驾驶、接电话、点头瞌睡三个片段的视频逐帧检查检测框和类别是否正确特别是黑暗场景和戴眼镜场景下的漏检。这个维度验证的是YOLOv5的模型质量。第二跟踪维度。看视频时打印出track_id确认头部左右转动时ID不跳变。跟踪不稳定疲劳累计就会清零整个系统逻辑就塌了。这个维度验证的是Deepsort的参数合理性。第三疲劳判定维度。闭眼2秒和眨眼0.3秒系统必须能区分开。方法是在myfatigue.py里把EAR值实时打印出来观察闭眼时的最低值和正常睁眼值的差距然后据此微调阈值。演示节奏上不要拿一整段长视频从头放到尾评委注意力会涣散。我习惯准备一段10到15秒的视频前半段正常驾驶系统无报警中间段驾驶员低头或者闭眼系统弹出报警后半段恢复正常报警解除。再配合界面上的EAR曲线变化整个系统逻辑在30秒内就能讲完。从那以后我每次拿到一套检测项目都会先花10分钟把输入源、权重、关键点模型三条路径全部理清楚再开始跑。这套资源我也按这个习惯检查了一遍演示视频、权重、界面脚本都在包内建议你下载后先跑mydetect.py验证链路再进main.py看GUI效果。希望帮到你。本文还有配套的精品资源点击获取