ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

YOLOv8课堂学生行为检测实战:从数据标注到部署

YOLOv8课堂学生行为检测实战:从数据标注到部署 简介基于YOLOv8的课堂学生行为检测系统是一份面向课程设计、毕业设计与深度学习入门实践的高完整性项目包适合计算机相关专业学生、高校教师及开发者开展课堂场景下学生姿态、抬头/低头、玩手机等行为识别实验。项目难度适中源码、配置与说明文档齐全按文档调整环境后即可运行无需从零搭建模型。压缩包共207个文件约74.21MB核心内容以Python源码、YOLOv8训练与推理yaml配置、可视化结果png、标注xml为主同时包含Docker部署文件、ipynb交互示例、bin/pb/caffemodel模型权重及设计报告docx覆盖数据准备、模型训练、效果评估、服务部署和论文撰写等多个环节。已有186人学习下载既可满足日常实训与作业要求也适合作为课设、毕设的高分参考尤其适合首次接触YOLO系列项目的学习者快速入手。1. 这是给课设和毕设准备的YOLOv8实战开局把基于YOLOv8的课堂学生行为检测系统跑通不是从网上下个模型权重、对着教室视频预测一遍就完事。一套能拿去答辩的项目至少得有三样东西能解释清楚的行为类别定义、完整的数据标注和训练闭环、以及一份把你每一步取舍写明白的设计报告。这个方向适合两类人——准备交毕业设计或课程设计需要一份既能跑又讲得清的项目以及想给课堂考勤做自动化统计的工程师先拿最小系统验证效果。这个方向真正的成本不在模型训练而在数据准备和类别边界下面按一条能直接复制的路径讲。2. 先想清楚检测谁行为类别划定和报告逻辑2.1 六类行为还是八类行为类别边界直接影响标注和收敛很多拿到源码包的同学第一反应是直接训训完发现准确率上不去。问题通常不在YOLOv8而在类别定义太随意。课堂行为检测最常见的设计是6类我一般按“正面行为、中性行为、负面行为”三组去做分组类别典型姿态标注要点训练难度正面举手手臂抬起手掌高于肩部框住“手臂手掌”区域不要只框拳头中正面阅读低头看书书本在桌面框“头部书本”书本很小要标准确中正面书写握笔手臂贴桌面框“上半身桌面”别框半截低中性听讲目视前方面部朝讲台框头部可放宽到肩部以上低负面睡觉头部趴下或后仰框头部注意与低头的区分高负面玩手机手持手机视线朝下框“手手机区域”手机目标极小高这个表的目的是让类别边界可操作。比如“睡觉”和“低头看手机”在画面里都是头部下沉姿态如果标注时只看头不看手模型就会把两手空空的低头误判成玩手机。所以我在标注规范里加了一条硬性约束玩手机必须能看到手部有握持动作否则标为听讲或低头——这样才逼着模型去学手部特征而不是用头部角度一刀切。类别数量上我不建议超过8类。课堂场景单张图里的目标太多、彼此遮挡严重类别越多标注歧义越大。6类已经能把“课堂参与度”这个核心指标讲清楚参与度 举手 阅读 书写 听讲/ 总人数。这套口径写在报告里老师一看就知道你做过需求分析而不是拍脑袋选类别。还有一个经常被忽略的设计点目标尺度。教室全景摄像头下一个坐着的学生可能只有40×80像素。这种小目标对YOLOv8不算友好但可以通过两类手段弥补——训练时把imgsz从640提到768推理时用切片或放大画面。更推荐的做法是训练数据里混合“全景画面”和“半场特写”让模型同时见过大目标和小目标而不是只在特写视频里训练然后拿全景画面推理。2.2 紧扣毕设评分点的设计报告结构与答辩追问预案设计报告是源码包的另一半价值。一份能拿高分的报告结构上应该直接对应“需求 → 设计 → 实现 → 验证”这条链。我看到很多同学的报告把YOLOv8原理抄了十几页系统设计只有两三页分数往往不理想。我建议把报告重心放在数据层面。报告里我一般建议六个章节绪论与背景、目标检测技术选型为什么选YOLOv8而不是Faster R-CNN或SSD、行为类别定义与数据采集标注规范、模型训练与参数调优、系统实现界面 实时推理流程 行为统计、实验结果与误差分析。答辩时老师最常追问三个问题报告里要提前埋伏好答案。第一个“行为类别边界是怎么定义出来的”——直接引用上表的可操作判定规则解释同类遮挡和类间相似怎么处理。第二个“为什么不用时序模型”——这个问题要诚实回答单帧YOLOv8能覆盖大部分静态行为睡觉、玩手机这类持续性行为可以用帧间统计平滑成本低效果好如果做举手这类瞬时动作再引入时序模型如LSTM或SlowFast才划算。第三个“模型在真实课堂环境的光照、遮挡下表现如何”——报告里放一张误差分析表列出各类别在正常光照、逆光、遮挡场景下的mAP对比答完这三个问题基本就稳了。3. 搭建YOLOv8训练环境与跑通最小训练闭环3.1 Ubuntu 20.04 CPU与GPU两条环境路线怎么选环境配置是第一个劝退点但它的难度被高估了。YOLOv8基于Ultralytics框架安装方式很统一创建Python 3.83.10的环境pip install ultralytics即可。关键分歧在算力——CPU还是GPU。如果是Ubuntu 20.04的CPU机器训练yolov8n小模型、只跑几十个epoch做验证是可行的但速度慢到你想放弃。不要指望CPU跑完整训练更合理的定位是CPU机单独做数据预处理、格式转换、模型导出的推理验证真正训练交给有GPU的机器或云平台。CPU环境的安装要点有两个一个是pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu避开CUDA版torch另一个是ultralytics会自动检测设备跑model.train(devicecpu)就能强制指定CPU。GPU环境下踩得最多的是版本不匹配。我的固定操作是先nvidia-smi看驱动支持的CUDA版本再装对应CUDA版torch。GTX 1660 Ti这种6GB显存的卡跑yolov8s、imgsz640、batch8到16是没问题的如果只有4GB显存就把imgsz降到480batch降到8。# 创建独立的Python虚拟环境避免搞崩系统环境 conda create -n yolo python3.10 -y conda activate yolo # 安装Ultralytics框架会自动带上依赖的cv2/numpy等 pip install ultralytics # 验证安装成功能正常打印模型结构说明环境没问题 yolo predict modelyolov8n.pt sourcehttps://ultralytics.com/images/bus.jpg这段命令里yolo是Ultralytics提供的命令行入口predict子命令的model参数指定权重文件首次运行会自动下载。如果最后一条命令能输出检测结果说明框架、依赖、权重下载链路都通了可以进训练环节。3.2 用自己的课堂视频做数据集标注、转换与YOLO格式训练自己的数据集绕不开标注。课堂行为数据常用的标注工具是Labelme或LabelImg。LabelImg生成的是YOLO原生格式省一步转换但Labelme在复杂多边形场景更顺手。我习惯用Labelme标注课堂行为因为“睡觉趴桌”这类目标边界不规则矩形框容易框进桌面杂物Labelme可以先画矩形再微调。无论用哪个工具最终都要落到YOLO格式每张图对应一个同名txt文件每行是类别ID x_center y_center width height四个坐标值都归一化到01。Labelme输出的是JSON格式必须转一次。下面这段转换脚本是我每次做课设数据集都会用的import json import os from pathlib import Path # 类别顺序必须与训练yaml里的names定义完全一致 CLASSES [hand_up, read, write, listen, sleep, phone] def convert_labelme_json(json_path: str, out_dir: str, img_w: int, img_h: int): with open(json_path, r, encodingutf-8) as f: data json.load(f) txt_name Path(json_path).stem .txt lines [] for shape in data[shapes]: label shape[label] if label not in CLASSES: continue # 未定义类别直接跳过避免脏数据进训练集 points shape[points] xs [p[0] for p in points] ys [p[1] for p in points] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) # Labelme坐标是绝对像素YOLO格式需要归一化 x_center (x_min x_max) / 2 / img_w y_center (y_min y_max) / 2 / img_h width (x_max - x_min) / img_w height (y_max - y_min) / img_h line f{CLASSES.index(label)} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f} lines.append(line) with open(os.path.join(out_dir, txt_name), w, encodingutf-8) as f: f.write(\n.join(lines)) # 使用示例对data/labels_json下的每个json按图宽高转换这段脚本的核心是把Labelme的绝对坐标归一化同时过滤掉没在类别清单里的标签。使用时的两个关键参数是img_w和img_h它们必须取原始图片尺寸而不是标注时预览窗口的尺寸否则框的位置整体偏移。数据量上每类至少准备300500个实例整个数据集2000张图上下比较稳。图片来源可以是自己录的课堂视频抽帧也可以混入公开数据集做预训练迁移。3.3 训练自己的课堂数据集从迁移学习到评估的完整命令数据准备好了训练就变成一条命令的事。Ultralytics把数据组织约定固化成了标准数据集目录下要有images/train、images/val、labels/train、labels/val四个子目录再配一个dataset的yaml文件。# classroom.yaml path: ./dataset # 数据集根目录相对路径更容易迁移 train: images/train # 训练集图片目录框架会自动匹配同名txt标签 val: images/val # 验证集图片目录 names: 0: hand_up 1: read 2: write 3: listen 4: sleep 5: phone训练命令我建议写成shell脚本而不是一行行手动敲方便后面反复调参# 训练脚本 train.sh yolo detect train \ dataclassroom.yaml \ modelyolov8s.pt \ epochs120 \ imgsz640 \ batch16 \ device0 \ patience20 \ projectruns/train \ nameclassroom_v1命令里modelyolov8s.pt不是随机初始化而是用COCO预训练权重做迁移学习这是小数据集能收敛的关键。epochs120对两千张图的数据集够用再多容易过拟合。batch16在6GB显存上是安全值越大的batch梯度越稳但显存不够就降到8。patience20表示验证集指标连续20个epoch不提升就早停这是防止周末人不在、训练白跑浪费电量的后悔药。训练完成后输出在runs/train/classroom_v1/下weights/best.pt和last.pt分别是验证集最优和最后一个epoch的权重。评估和推理直接复用这两个文件# 用best.pt在验证集上输出mAP等指标 yolo detect val modelruns/train/classroom_v1/weights/best.pt dataclassroom.yaml # 对一段课堂录像做批量预测并保存结果视频 yolo detect predict modelruns/train/classroom_v1/weights/best.pt \ sourcetest_video.mp4 saveTrue conf0.35conf0.35是置信度阈值课堂场景我习惯设0.30.4。设太低会出现大量误报设太高小目标玩手机全漏。数据不均衡的类别可以单独调低该类的置信度但YOLOv8命令行不支持类级置信度要写几行Python调用model.predict(conf0.35)之后按类别过滤。4. YOLOv8训练参数含义与loss曲线的调参方法4.1 关键训练参数速查与课堂场景推荐值YOLOv8的默认参数在多数通用场景表现不错但课堂行为数据有自己的脾气——类别不均衡、小目标多、单人遮挡频繁。直接把默认参数套上去能跑但精度未必理想。下面这几个参数我每次必调参数默认值课堂场景推荐值具体作用epochs100120150训练轮数早停开启时可按此设置上限imgsz640640768全景教室建议768特写镜头640够用batch16816受显存限制1660Ti可用16optimizerautoSGD或AdamW小数据集AdamW收敛更稳但mAP上限略低lr00.01SGD用0.01AdamW用0.001初始学习率太高会震荡不收敛lrf0.010.01最终学习率 lr0 × lrfmosaic1.00.81.0拼接增强但会切碎小目标后期建议调低label_smoothing0.00.1缓解类别过拟合睡觉类尤其有效close_mosaic1010最后10个epoch关闭mosaic让小目标回归真实分布mosaic是YOLOv8里影响最大也最容易被忽略的参数。它在训练时把4张图拼成1张等效扩大了batch和场景多样性但对课堂行为这种小目标数据是个双刃剑——拼接后单个目标被缩小到原来的四分之一模型学到的多是“模糊的小色块”。所以我在第4章开头就建议把mosaic设成0.8后期靠close_mosaic10在最后10个epoch恢复正常分布。这个参数组合是我对比过几轮实验后固定的能让睡觉类和玩手机类的召回率各提升三到五个点。optimizer参数在Ultralytics里默认是auto会自动按模型规模选SGD。实际上对小数据集、类别不平衡的场景AdamW前几十个epoch收敛更快适合快速验证数据有没有标错等到正式跑最终版本再切回SGD冲mAP。我自己的迭代节奏是先用AdamW 80个epoch验证流程通不通再切SGD 120150个epoch出最终权重。4.2 画损失函数曲线判断过拟合、欠拟合和数据问题很多同学不看曲线只看最后一个epoch的mAP这样调参基本靠玄学。YOLOv8每次训练都会在runs/train/classroom_v1/下生成results.csv里面记录了每个epoch的box loss、cls loss、dfl loss以及验证集对应指标。画曲线不需要额外装框架一个Python脚本搞定import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/train/classroom_v1/results.csv) # 注意Ultralytics的csv列名首尾有空格需要strip df.columns [c.strip() for c in df.columns] epochs df[epoch] plt.figure(figsize(10, 6)) plt.plot(epochs, df[train/box_loss], labeltrain/box_loss) plt.plot(epochs, df[val/box_loss], labelval/box_loss) plt.xlabel(epoch) plt.ylabel(loss) plt.legend() plt.title(Box Loss: train vs val) plt.savefig(loss_curve.png, dpi200)判断逻辑就三条。第一条train/box_loss持续下降但val/box_loss在第40个epoch左右开始回升这是标准的过拟合信号处理方式是加大label_smoothing、减小模型yolov8n换yolov8s、或者把数据增强的hsv_h和fliplr打开让模型见过更多变化。第二条两个loss下降都很慢每10个epoch只降0.01这种多半是学习率太低把lr0提高3倍看曲线斜率是否明显变化。第三条train/box_loss正常下降但val/cls_loss始终在高位抖动这说明分类那段大概率是标签错误——某个类别的标注框和类别对不上丢进dataset/labels/train看一眼最可疑几个json的坐标有没有错位。第4章里画的曲线在答辩时也很有用可以放在实验部分配合“发现过拟合后怎么调参”的叙述比空口说“准确率99%”可信得多。5. 训练课堂行为数据最容易翻车的五个坑及排查记录5.1 安装后import报错torch版本与框架不匹配现象是pip install ultralytics之后代码里from ultralytics import YOLO要么报AssertionError要么提示某个算子不存在。原因是Ultralytics新版对torch版本有下限要求而CUDA版torch安装时没指定版本装了旧版。我现在的处理步骤是先pip list | grep torch看版本低于1.8的直接升级同时用python -c import torch; print(torch.cuda.is_available())确认CUDA是否真正可用。还有一个常见变体是conda环境下pip装的torch和系统CUDA驱动不一致表现为训练能开始但速度极慢且不报错——nvidia-smi确认驱动CUDA版本后再重装对应torch。5.2 标签类别ID错位训练不收敛但图表看着正常这个坑非常隐蔽。现象是训练曲线正常下降、mAP也有0.7以上但抽样看预测结果发现“睡觉”被标成“玩手机”、“阅读”和“书写”完全颠倒。原因是标注工具里类别列表的顺序和classroom.yaml的names定义不一致导致JSON里的label转换时ID错位。排查方法很简单随机抽20个训练样本把txt和图片叠着看一遍重点检查第一个数字对应的类别名。我踩过一次后在转换脚本里加了一行断言——如果JSON中出现不在CLASSES里的标签就终止转换并打印标签名宁可停也不要带病训练。5.3 类别不平衡让mAP虚高睡觉类实际识别率骤降课堂行为数据的分布天然不均衡“听讲”占了一半样本“睡觉”只有几十个样本。结果就是mAP被大类撑住小类实际一测就露馅。判断方法不是看总mAP单独看per-class的召回率。解决办法从三个方向同时做一是给少数类增加样本用视频抽帧变体——同一段睡觉视频每5帧抽一帧让模型见过不同姿态角度的睡觉二是用mosaic增强把少数类目标拼进不同背景三是数据层面实在凑不够时调低该类的检测置信度阈值用后处理方式兜底召回率。5.4 CPU训练慢到怀疑人生还没跑到一半就放弃了如果只有CPU机器我建议不要试图完整训完yolov8s。实测yolov8n在纯CPU上跑一个epoch需要十几分钟120个epoch要一天多完全不适合迭代调参。替代方案有三个yolov8n imgsz480 batch8先跑通流程把数据量减到每类200张验证代码链路正确性后再扩数据用Colab这类免费GPU平台把数据集传上去训练下载best.pt回到本地做推理。注意Colab的GPU训练时要把device0改成device0或者干脆删掉让Ultralytics自动选设备。5.5 全景教室小目标误检漏检检测框乱跳还连号教室全景图里一个学生几十个像素YOLOv8很容易漏检或框体抖动。现象是视频里检测框一帧有、一帧没或者同一个学生一会儿标成阅读一会儿标成睡觉。原因有两层训练数据里全景图占比太少模型没见过小目标分布推理时没有做时序平滑。解决方式一个落在训练端一个落在推理端。训练端在数据集里混入30%的全景教室画面并且把imgsz提到768推理端引入结果平滑器取过去10帧的检测结果做多数投票当前帧的检测类别以投票结果为准而不是只看单帧。这个平滑逻辑在后面的系统实现里是一个约20行代码的函数。6. 让系统从“能检测”到“能用”行为统计、界面优化与轻量化部署6.1 行为统计别只靠单帧跟踪与滑动窗口才是正解很多demo项目停留在“画框标类别”但课设系统要求的是“统计课堂参与度”。最朴素的实现是每帧统计各类别人数然后画折线图但这么做的结果就是第5章讲过的检测框抖动被直接放大到统计曲线上。我会加一层基于跟踪的行为归属对每个检测目标维护一个状态只有当连续N帧都是同一类别时才更新该目标的行为状态。用Ultralytics的model.track接口可以直接拿到目标ID配合persistTrue做跨帧关联。跟踪能顺带解决重复计数——同一学生在不同帧不应该累计多次行为次数。行为统计最终输出两个指标整节课的学生参与度曲线以及睡觉、玩手机行为的人次数。6.2 从ONNX到RK3588边缘部署课堂行为检测的现实路线如果想把系统从PC端挪到教室边缘设备我走的是best.pt → ONNX → RKNN这条链。先在PC上导出通用格式yolo export modelruns/train/classroom_v1/weights/best.pt formatonnx opset12导出后建议用onnxruntime跑一遍验证精度损失再按设备要求转换。RK3588上部署YOLOv8的常见做法是用rknn-toolkit2把ONNX转成rknn格式重点调quantized_dtype参数做int8量化——量化后模型体积缩到四分之一精度大概掉一到两个点但这个损失在课堂行为这种粗粒度分类任务上完全可接受。边缘部署优先选yolov8n或yolov8s不要一上来就上yolov8x算力吃不住且帧率不达标。我个人的教训是先在本地用ONNX跑通推理再碰RKNN的板端环境否则板子上的报错信息晦涩到让你误以为是模型写错了。最后把整个项目当成产品看一遍数据标注规范、损失曲线、误差分析、跟部署可行性这四份产出比模型本身更有分量。课设答辩时能拿出“我调过标注规范、对比过mosaic开关、量化后精度损失多少”这些细节就是区分度所在。希望这些踩过的坑能帮你少走几轮弯路。本文还有配套的精品资源点击获取
返回列表