
简介本资源是一套面向计算机视觉初学者与教育信息化开发者的课堂行为分析实战项目聚焦学生睡觉、玩手机等典型违纪行为的实时检测需求。基于YOLOv5目标检测框架构建完整端到端系统涵盖数据标注规范、模型训练调优、视频流推理部署及可视化反馈模块适用于课程设计、毕业设计或AI教育应用原型开发。压缩包共220个文件含103个Python脚本含训练/推理/评估主程序、79个YAML配置文件定义模型结构、超参与数据路径、11个Markdown文档含技术原理说明与使用指南以及Dockerfile系列支持CPU/ARM64多平台部署整体仅1.19MB轻量易上手。目前已有1937人学习下载提供可直接运行的完整代码、结构清晰的工程目录、标准化数据组织方式及CITATION.cff学术引用支持助读者快速复现、调试并拓展应用场景。1. 项目缘起从课程设计到真实场景的跨越最近在整理硬盘时翻到了一个几年前带学生做的课程设计项目——“基于YOLOv5的学生课堂违纪检测系统”。当时这个项目主要是为了满足计算机视觉或人工智能相关课程的期末大作业需求目标是跑通一个从数据标注、模型训练到部署演示的完整流程。但有意思的是这个看似“学院派”的项目在后续与一些教育技术领域的朋友交流时发现其核心思路和踩过的坑对于想尝试将AI落地到具体垂直场景的开发者来说反而有不少值得深挖的地方。它不仅仅是一个调用现成API的玩具而是涉及了目标检测模型选型、小样本数据处理、业务逻辑定义、轻量化部署等一系列真实问题。今天我就把这个项目的完整思路、代码实现中的关键细节以及那些教科书上不会写的“坑点”重新梳理一遍希望能给正在做类似课程设计或对AI应用落地感兴趣的朋友一些实在的参考。这个系统的核心任务很简单通过教室监控视频流自动检测并识别学生可能出现的违纪行为比如趴桌睡觉、交头接耳、使用手机等。选择YOLOv5作为基础模型主要是看中它在精度、速度和易用性之间的平衡以及其活跃的社区和丰富的预训练模型非常适合课程设计这种需要快速出成果的场景。但“快速出成果”不等于“敷衍了事”整个项目链条上的每一个环节都藏着让模型从“能跑”到“好用”的关键。2. 核心问题定义什么才算“课堂违纪”在动手写第一行代码之前最重要也最容易被忽视的一步是明确你要检测的“违纪行为”到底是什么。这直接决定了数据如何标注、模型如何设计、后处理逻辑怎么写。2.1 行为拆解与目标定义我们不能让模型直接去理解“交头接耳”这个抽象概念。必须将其分解为模型可感知、可检测的视觉目标。基于常见的课堂场景我将其定义为三类可检测的目标Object再通过目标间的空间关系组合成行为Behavior趴桌睡觉 (Head-Desk)这是一个静态单人行为。我们不需要模型理解“睡觉”只需要它检测出“头部”这个目标并判断其与“桌面”区域的相对位置和姿态如头部与桌面的接触面积、头部姿态角。在初期简化版本中我们可以只检测“头部”并设定一个阈值当头部检测框的中心点持续N帧低于桌面预设线或与桌面检测框有大量重叠则判定为疑似趴桌。使用手机 (Using Phone)这是一个手持物品的检测问题。理想情况下我们需要同时检测“手部”和“手机”两个目标并判断它们的空间关系如交并比IoU。但在实际课堂的俯拍或侧拍视角下手部检测可能不稳定。一个更务实的做法是只检测“手机”这个目标。因为学生在课堂上合法使用手机的场景极少除非是特定教学环节所以一旦在学生座位区域检测到手机即可大概率判定为违纪使用。这大大简化了问题。交头接耳 (Whispering)这是一个动态的双人交互行为。我们需要检测多个“头部”目标并计算任意两个头部之间的距离和相对朝向。如果两个头部距离过近例如小于两个头部宽度平均值且它们的朝向夹角较小大致面对面并持续一段时间则可以判定为在交头接耳。基于以上分析我们的目标检测任务实际上变成了对头部head和手机phone两类目标的检测。“桌面”可以作为先验知识ROI区域输入而非检测目标。这样项目就从复杂的行为识别降维到了更成熟、更易实现的目标检测问题上。注意这里有一个重要的工程取舍。理论上更严谨的做法应该检测“人”person再通过关键点如鼻尖、耳朵来精确定位头部和朝向。但对于课程设计级别的项目以及可能面临的数据标注成本、计算资源限制直接检测“头部”是性价比更高的方案。YOLOv5完全有能力完成多类别的目标检测。2.2 数据标注规范制定明确了检测目标就需要制定对应的数据标注规范。我们使用LabelImg或更高效的CVAT进行标注。头部head标注框应紧密包围学生的整个头部包括头发。对于趴桌的情况可能只露出部分后脑勺标注框也应覆盖可见部分。手机phone标注框应包围整个手机无论其握持方向。对于只露出手机一角的困难样本也应尽量标注这有助于提升模型的鲁棒性。标注时务必注意以下几点一致性同一个目标在不同帧、不同角度下的标注框大小和位置要尽量一致。困难样本对于遮挡严重的头部如被前排同学挡住一半、光线暗淡下的手机不要跳过必须标注。这些是模型在实际场景中必须面对的挑战。负样本数据集中可以适当包含一些没有任何目标的“空”画面或者有类似物如计算器、文具盒但非手机的画面这有助于降低误报。我们的课程设计数据集最终包含了约2000张来自公开课堂视频截图及少量模拟拍摄的图片按照8:1:1的比例划分训练集、验证集和测试集。3. 模型训练实战YOLOv5的调优细节拿到标注好的数据接下来就是训练模型。YOLOv5的仓库ultralytics/yolov5提供了非常清晰的脚本但要想获得更好的效果有几个细节必须关注。3.1 环境搭建与数据准备首先克隆YOLOv5官方仓库并安装依赖。这里强烈建议使用Python虚拟环境。git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt数据准备需要遵循YOLOv5要求的目录结构。我们在yolov5目录下创建自己的数据文件夹datasets/ └── classroom/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/图片放在images对应的子文件夹标注文件.txt格式YOLO格式放在labels对应的子文件夹。然后创建一个数据配置文件classroom.yaml放在yolov5/data/目录下# classroom.yaml path: ../datasets/classroom train: images/train val: images/val nc: 2 # 类别数head, phone names: [head, phone]3.2 关键超参数解析与调整直接运行python train.py --img 640 --batch 16 --epochs 100 --data data/classroom.yaml --weights yolov5s.pt可以开始训练但理解几个关键参数对结果影响巨大。--img 640输入图像尺寸。YOLOv5训练时会自动将图片缩放到此尺寸。更大的尺寸如1280能保留更多细节提升小目标如远处的手机检测能力但会显著增加显存消耗和训练时间。对于课堂场景学生头部通常是中大型目标640是一个兼顾速度和精度的起点。如果数据集里有很多坐在后排的小目标可以尝试增大到960。--batch 16批次大小。在显存允许的前提下较大的batch size能使训练更稳定梯度估计更准确。如果出现CUDA out of memory错误首先尝试减小batch或者减小--img。--epochs 100训练轮数。不是越多越好需要观察验证集损失val/loss和指标mAP0.5的变化。通常会在损失曲线平稳且mAP不再上升时提前停止。可以使用--patience参数设置早停。--weights yolov5s.pt使用预训练权重。这是提升小数据集性能最关键的一步。yolov5s.pt是在COCO大型数据集上预训练的其学到的通用特征边缘、纹理、形状极大地帮助了我们的模型快速收敛。永远不要从零开始训练--weights 除非你有海量数据。--data指定我们刚才创建的数据配置文件。除了命令行参数模型结构相关的超参数在models/yolov5s.yaml中定义。对于课程设计我们通常不需要修改网络结构但可以关注一下anchors锚框。YOLOv5会使用k-means算法在你的数据集上重新聚类生成更合适的anchors这个过程是自动的但了解其原理有助于调试如果你的目标大小分布很特别比如我们的“头部”目标宽高比接近1:1“手机”是细长型自动聚类的结果会比默认的COCO anchors更好。3.3 训练过程监控与问题排查启动训练后TensorBoard或日志会输出大量信息。重点看以下几个损失曲线Loss Curves关注train/loss和val/loss。理想情况是两者同步平稳下降。如果训练损失下降但验证损失上升这是典型的过拟合。解决方案增加数据增强YOLOv5默认已启用Mosaic、MixUp等强增强、使用更小的模型如从yolov5s换到yolov5n、增加正则化如--dropout或直接收集更多数据。性能指标Metrics重点是mAP0.5IoU阈值为0.5时的平均精度。这是衡量检测精度最核心的指标。我们会看到mAP0.5随着训练逐渐上升。类别精度YOLOv5还会输出每个类别的精度Precision、召回率Recall和mAP。如果发现phone的召回率远低于head很可能是因为手机样本太少、太难检测。需要针对性补充手机数据或调整正负样本权重通过修改损失函数但较复杂。在我的训练中曾遇到“手机”类别精度始终上不去的问题。排查后发现原始数据集中“手机”样本大多为正面或侧面清晰拍摄但实际违纪场景中学生常常用手遮挡或手机平放桌上只露一角。于是我们专门补拍了一批这类“困难样本”加入训练集并略微增加了针对小目标的数据增强如随机缩放phone的AP值最终提升了约15%。训练完成后最佳模型会保存在runs/train/exp/weights/best.pt。4. 从检测到行为判定的后处理逻辑模型输出了一个个边界框BBox包括坐标、置信度和类别。我们需要将这些原始的检测结果转化为“趴桌睡觉”、“使用手机”和“交头接耳”的行为判定。这部分逻辑需要自己编写是体现系统业务价值的关键。4.1 单帧行为判定算法假设我们从模型得到了一帧图片的检测结果列表detections每个元素包含[x1, y1, x2, y2, conf, cls]左上、右下坐标置信度类别索引。1. 使用手机判定最简单。遍历detections如果cls对应phone且其置信度conf高于阈值如0.6并且该检测框的中心点落在预设的学生座位区域内可以通过标定教室视频视角定义多个多边形ROI区域则判定为该座位学生使用手机。立即记录时间戳、座位号和截图。def detect_phone_use(detections, seat_rois, phone_cls_id1, conf_thresh0.6): phone_events [] for det in detections: x1, y1, x2, y2, conf, cls det if cls phone_cls_id and conf conf_thresh: center_x, center_y (x1 x2) / 2, (y1 y2) / 2 for seat_id, roi_polygon in seat_rois.items(): if point_in_polygon(center_x, center_y, roi_polygon): phone_events.append({ seat_id: seat_id, timestamp: current_time, bbox: [x1, y1, x2, y2] }) break return phone_events2. 趴桌睡觉判定判定逻辑需要结合“头部”位置和“桌面”区域。我们为每个座位预设一个“桌面区域”一个矩形框。判定条件可以是头部检测框的底部y2坐标低于桌面区域的上边界desk_top即头部下沉到了桌面以下。或者头部检测框与桌面区域的重叠面积IoU超过一定阈值如0.3。 同样需要持续多帧如2秒约60帧30fps满足条件才判定为一次有效的趴桌事件以避免学生短暂低头捡笔的误判。3. 交头接耳判定这是最复杂的涉及多目标间关系。算法步骤如下提取所有head检测框。计算每两个头部框之间的欧氏距离以框中心点计算。如果距离小于阈值D_thresh例如设定为两个头部框平均宽度的1.5倍则认为他们“距离过近”。可选计算朝向这需要更复杂的姿态估计。简化版可以跳过或者用两个头部框的水平位置差和高度差来近似判断是否面对面。同样需要持续多帧满足“距离过近”条件才判定为交头接耳。4.2 多帧追踪与事件滤波上述单帧判定会带来大量抖动和误报。例如学生可能只是瞬间转头对同学说一句话。因此必须引入时间维度的滤波。基于IOU的简单追踪对于同一类目标如head在连续帧间如果检测框的IoU大于某个阈值如0.3则认为它们是同一个目标并分配一个唯一的ID。这样我们就得到了每个目标的轨迹。状态机滤波为每个待检测的行为如“趴桌”设计一个状态机。例如状态0正常当条件首次满足如头部进入桌面区域进入状态1疑似并开始计时。状态1疑似在接下来的N帧内如果条件持续满足计时累加。如果计时超过阈值T如60帧则进入状态2确认触发一次违纪记录。如果在状态1期间条件不满足了则退回状态0。状态2确认记录事件后可以设置一个“冷却时间”在此期间不再对同一目标进行判定防止连续重复报告。通过这种“检测追踪滤波”的流水线系统的稳定性和准确性会大大提高。在课程设计中即使只实现一个简单的基于帧数的计数器例如连续5帧检测到手机才报警也能显著提升演示效果。5. 系统集成与可视化实现我们将整个系统构建成一个简单的Web应用使用Flask作为后端前端实时显示检测画面和违纪警报。这部分的代码结构清晰非常适合课程设计展示。5.1 后端服务Flask核心结构# app.py from flask import Flask, render_template, Response, jsonify import cv2 from inference import BehaviorDetector # 这是我们封装了模型加载、推理和后处理的类 app Flask(__name__) detector BehaviorDetector(weightsruns/train/exp/weights/best.pt) # 模拟或真实视频流 video_source test_video.mp4 app.route(/) def index(): return render_template(index.html) app.route(/video_feed) def video_feed(): def generate(): cap cv2.VideoCapture(video_source) while True: ret, frame cap.read() if not ret: break # 执行检测 annotated_frame, events detector.detect(frame) # 将违纪事件events存入临时列表或数据库供前端查询 # ... # 编码帧为JPEG _, jpeg cv2.imencode(.jpg, annotated_frame) yield (b--frame\r\n bContent-Type: image/jpeg\r\n\r\n jpeg.tobytes() b\r\n) cap.release() return Response(generate(), mimetypemultipart/x-mixed-replace; boundaryframe) app.route(/get_events) def get_events(): # 返回最新的违纪事件列表 events detector.get_recent_events() return jsonify(events) if __name__ __main__: app.run(host0.0.0.0, port5000, debugTrue)BehaviorDetector类是核心它内部会加载YOLOv5模型使用torch.hub或直接加载best.pt。对输入的每一帧进行预处理、推理、非极大值抑制NMS。调用第4部分所述的后处理逻辑进行行为判定和事件滤波。在帧上绘制检测框、行为标签和警报信息。管理事件记录。5.2 前端可视化HTML/JS前端页面主要做两件事通过img标签的src属性指向/video_feed路由来显示实时视频流通过AJAX轮询/get_events路由来更新侧边栏的违纪事件列表。!-- templates/index.html -- !DOCTYPE html html head title课堂违纪行为检测系统/title style .container { display: flex; } .video-panel { flex: 3; } .event-panel { flex: 1; border-left: 1px solid #ccc; padding: 10px; } #event-list { list-style: none; padding: 0; } #event-list li { padding: 5px; border-bottom: 1px solid #eee; } /style /head body div classcontainer div classvideo-panel h2实时检测画面/h2 img src{{ url_for(video_feed) }} width100% /div div classevent-panel h2违纪事件记录/h2 ul idevent-list !-- 事件将通过JS动态插入 -- /ul /div /div script function fetchEvents() { fetch(/get_events) .then(response response.json()) .then(events { const list document.getElementById(event-list); list.innerHTML ; events.forEach(event { const li document.createElement(li); li.textContent [${event.time}] 座位${event.seat}: ${event.type}; list.appendChild(li); }); }); } // 每2秒更新一次事件列表 setInterval(fetchEvents, 2000); /script /body /html这样一个具备实时视频流、动态检测和事件记录的系统就搭建完成了完全满足课程设计的演示要求。6. 课程设计之外的思考局限性与优化方向完成基本功能后我们有必要审视这个系统的局限性这也是从“课程设计”迈向“可用系统”必须思考的。6.1 当前方案的局限性视角依赖性强系统性能严重依赖摄像头角度。俯拍视角最适合检测趴桌和手机但对判断“交头接耳”的面对面朝向不利。侧拍视角则相反。固定角度的摄像头难以覆盖所有座位和所有行为。行为定义过于简化我们将复杂行为简化为目标检测和空间关系会丢失大量上下文信息。例如“低头看桌子”可能是睡觉也可能是看书。“两人靠近”可能是讨论问题不一定是交头接耳。这会导致误报和漏报。光照与遮挡挑战教室光照变化如阴天、灯光开关、严重遮挡前排高大同学挡住后排都会极大影响检测稳定性。计算资源与实时性在边缘设备如普通工控机上实时运行YOLOv5即使是s版并处理多路视频流对算力要求不低。需要模型量化、剪枝等优化。6.2 可能的优化方向模型层面更换骨干网络如果需要更快的速度可以尝试YOLOv5n纳米级或使用MobileNetV3作为backbone的变体。注意力机制在Neck或Head部分引入SE、CBAM等注意力模块让模型更关注“头部”、“手机”这类关键区域提升在复杂背景下的鲁棒性。知识蒸馏用训练好的大模型如yolov5l去指导一个小模型如yolov5n训练让小模型在精度损失不大的情况下获得更快的速度。数据与训练层面自动化数据增强策略如AutoAugment、RandAugment让模型见到更多样的数据变体。针对困难样本的重采样在训练过程中对“手机”这类难例样本给予更高的采样权重或损失权重。使用更丰富的预训练权重除了COCO还可以在包含更多“人”和“室内场景”的数据集如CrowdHuman, Objects365上进行预训练或微调。系统架构层面多视角融合部署多个摄像头从不同角度捕捉同一区域综合多个视角的检测结果进行判定可以缓解遮挡问题。引入时序模型在后处理阶段不使用简单的多帧滤波而是使用LSTM或Transformer对目标轨迹序列进行建模真正从时间维度上理解行为模式区分“短暂动作”和“持续行为”。边缘-云协同在教室端边缘运行轻量级模型进行初步检测和过滤将可疑片段或元数据上传到云端进行更复杂的分析如精细行为识别平衡实时性与准确性。回过头看这个课程设计项目就像是一个微缩的AI产品原型。它完整地走过了需求分析、数据准备、模型训练、应用开发、部署演示的闭环。最大的收获不是调出了一个多高的mAP而是在这个过程中你不得不去思考如何将模糊的业务需求“检测违纪”拆解成具体的算法问题“检测头和手机”如何为算法准备和标注数据如何根据实际场景设计后处理逻辑以及如何将模型包装成一个可演示的系统。这些经验远比单纯跑通一个MNIST分类demo要宝贵得多。如果你正在做类似的课程设计我的建议是不要只满足于“跑通代码”多花点时间在“定义问题”和“思考局限”上这会让你的项目报告更有深度也让你自己更有收获。本文还有配套的精品资源点击获取