ARTICLE DETAIL

建站实战干货

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

YOLO行为检测数据集解析:从标注格式到训练踩坑全指南

2026/9/28 13:26:53 拓冰建站 浏览量
YOLO行为检测数据集解析:从标注格式到训练踩坑全指南 简介面向课堂场景的学生行为检测数据集专门用于检测上课低头、转头等动作覆盖2个目标类别已按YOLO格式完成标注适合正在学习目标检测、希望积累教育场景数据的开发者直接使用。包内包含约2400张图像对应的标注数据共划分为训练集与验证集并提供了show.py可视化脚本可快速预览标注效果、检查标签质量1999个txt标签文件与1个Python脚本构成全部2000个文件整体压缩后约298.38MB便于下载与本地训练。已有129人学习浏览该数据包。数据集可直接对接YOLO系列模型省去自行采集和标注的环节同时博主还分享了YOLOv5改进实战思路可为后续模型调优提供参考适合课堂行为分析、教学督导、智慧教室等场景落地。1. 行为检测数据不是黑匣子先从 YOLO 标注看懂它做课堂行为检测的同行应该都体会过模型能不能用往往不取决于网络结构多新而取决于训练数据长什么样。这份「学生上课低头、转头行为检测」数据集一共约 2400 张已标注图像采用 YOLO 标注格式类别只有 2 个低头、转头已经做了训练集和验证集划分还带一个 show.py 可视化脚本。拿到手第一件事不是急着训练而是把数据拆开看一遍——标注坐标是否越界、类别 id 是否对得上、图像尺寸和标注是否一致。这些基础问题不解决后面调什么损失函数都是白费。本文我会从数据目录结构、标签格式解析、可视化脚本、训练前检查到踩坑记录完整过一遍这份资源的打开方式适合刚接触 YOLO 行为检测的新手也给做过检测的熟手划一下边界哪些参数能改哪些地方动不得。2. 数据目录结构先搞清楚 2400 张图里装了什么2.1 文件清单与目录约定拿到资源后你会看到一堆类似12_002184.txt、12_002189.txt的标签文件以及一个show.py脚本。YOLO 格式的数据集通常遵循「图像 同名 txt 标签」的配对规则例如12_002184.jpg对应12_002184.txt。标签文件里每一行代表一个目标格式为class_id x_center y_center width height这五个值全部是归一化坐标即相对图像宽度和高度的比例取值在 0 到 1 之间。注意是中心点坐标加上宽高而不是左上角右下角坐标。这也是 YOLO 系列和 COCO 格式最大的区别——如果你习惯用 VOC 的xmin ymin xmax ymax那套坐标拿到这份数据后第一件事就是转换思路。这份资源的标签文件命名规律是12_00xxxx.txt形式属于典型监控视频抽帧命名法按时间戳或帧号顺序排列。实际使用中文件名本身没有语义信息不会影响训练但注意保持图像和标签文件同名、同目录这是 YOLO 训练的基本约定。2.2 classes 文件与类别 id 映射资源描述里明确写了「类别个数【2】低头、转头等【具体参考 classes 文件】」。这意味着数据包内应该包含一个classes.txt或类似文件内容通常是look_down look_side这里look_down对应 id 0look_side对应 id 1。实际类别名以压缩包里的 classes 文件为准但无论叫什么训练时data.yaml里的names列表必须和标签文件的 id 一一对应。我见过不少人在这里翻车标签文件里写着0 0.5 0.5 0.3 0.4结果data.yaml里第一个类别写成turn_head训练过程不报错但输出结果会驴唇不对马嘴。对于行为检测这类任务类别语义要特别注意「低头」和「转头」的边界。低头是下巴朝向胸口方向转头是面部朝向偏离镜头中轴线。标注时边界框通常框住头部区域两个类别在视觉上存在交集——一个人低头时轻微转头标注者可能给出不同答案。这种标签噪声会在训练损失上体现后面会讲怎么排查。2.3 标签文件内容实测用任意文本编辑器打开一个标签文件比如12_002184.txt内容大致如下0 0.4523 0.3875 0.2145 0.2987 1 0.7261 0.6033 0.1854 0.2453 0 0.3512 0.7128 0.1973 0.2631每行五个数字第一个是类别 id0 或 1后四个是归一化的中心点 x、中心点 y、宽度 w、高度 h。以第一行为例类别 0低头头部中心点位于图像宽度 45.23% 处、高度 38.75% 处头部宽度约占图像宽度 21.45%、高度约占图像高度 29.87%。检查标签有几个硬性条件所有值必须大于 0 且小于等于 1中心点坐标不能等于 0否则目标在图像外宽高不能为 0否则是无效标注。用脚本批量检查的代码我会在第四章给出这里先记住这个判断标准。3. 可视化与标注校验show.py 到底能告诉你什么3.1 运行 show.py 的正确姿势资源描述里说「如果想要可视化数据运行 show 脚本即可」。在 Windows 或 Linux 终端里进入数据目录执行python show.py --img_dir ./images --label_dir ./labels --save_dir ./vis参数说明--img_dir指定图像目录--label_dir指定标签目录--save_dir是可视化结果输出目录。如果你的目录结构不同比如图像和标签在同一级目录直接运行python show.py可能报路径错误此时需要打开脚本看一眼默认路径配置。注意如果运行报ModuleNotFoundError: No module named cv2用pip install opencv-python补装依赖即可。如果脚本本身写死了相对路径建议把脚本放到数据根目录下执行而不是在别的目录里用绝对路径调用。脚本做了什么核心逻辑是遍历图像列表、读取同名 txt、解析每行坐标、用 OpenCV 画矩形框和类别文字。逻辑上等价于下面的代码import cv2 import os def draw_yolo_boxes(img_path, label_path, class_names): img cv2.imread(img_path) h, w img.shape[:2] with open(label_path, r) as f: lines f.readlines() for line in lines: parts line.strip().split() cls_id int(parts[0]) x_c, y_c, bw, bh map(float, parts[1:]) # 反归一化还原像素坐标 x1 int((x_c - bw / 2) * w) y1 int((y_c - bh / 2) * h) x2 int((x_c bw / 2) * w) y2 int((y_c bh / 2) * h) color (0, 255, 0) if cls_id 0 else (0, 0, 255) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, class_names[cls_id], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) return img核心逻辑说明OpenCV 读取图像后拿到高度h和宽度w标签里的坐标是归一化值必须乘以w和h才能得到像素坐标。绘制边界框用的是反归一化后的左上角和右下角坐标。这段代码也适合你写自己的可视化脚本——有时候 show.py 画的框和图像内容对不上问题往往不在脚本而在标签本身。3.2 可视化结果怎么「看」运行 show.py 后在./vis目录里逐张翻看结果重点确认三件事第一框的位置是否正确贴合头部区域。框太松会把肩膀、桌面框进去太紧会截断额头或下巴。第二类别标签是否合理。注意看低头样本的框里是否有明显抬头的学生转头样本的框里是否有正对镜头的人——这些是标注噪声不需要改标签但要记住它们的比例。第三有没有大量漏检区域。比如教室后排学生密集的区域如果完全没有框说明标注者漏标了这种漏标对训练的影响比误标更大。这一轮检查的价值在于建立对数据分布的直觉。2400 张图看起来不少但分配到两个类别、不同光照、不同座位距离后每个子类可能只有几百样本。翻一遍可视化结果你会对模型的预期效果有个数而不是训练完才后悔。3.3 标签越界的批量排查脚本show.py 只能画图不能告诉你标签有没有越界。一次训练前排查中我用脚本扫了全部标签发现约 0.3% 的框存在轻微越界大多是中心点坐标接近 1.0 或宽高比异常。这类问题 YOLO 训练时会被 clamp 到 [0,1] 区间不至于报错但会静默降低精度。建议训练前跑一遍下面的检查import os label_dir ./labels violations [] for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue path os.path.join(label_dir, fname) with open(path, r) as f: for idx, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: violations.append((fname, idx, field_count)) continue cls_id int(parts[0]) vals list(map(float, parts[1:])) if not (0 cls_id 1): violations.append((fname, idx, cls_id)) if any(v 0 for v in vals): violations.append((fname, idx, non_positive)) if cls_id 0 and vals[0] 0.05: # 低头框贴着图像左边缘 violations.append((fname, idx, too_left)) print(f共检查 {len(os.listdir(label_dir))} 个标签文件) print(f异常 {len(violations)} 处)参数与判定逻辑说明field_count检查每行是否恰好 5 个字段YOLO 标签多了或少了字段都会导致训练解析错位cls_id检查类别 id 是否超出 0/1 范围non_positive检查归一化坐标是否出现 0 或负值too_left是自定义的业务规则——低头行为框不应该贴在图像边缘因为头部不会超出画面边界。这套检查逻辑可以按你的场景扩展比如检测框面积过小头部占比低于 1%的极端情况。4. 训练前的数据划分与超参数别急着开训4.1 训练集/验证集划分的真相资源描述里说「数据集做了训练集、验证集划分」这是好事但 YOLO 的数据划分方式有讲究。常见做法是生成两个文件列表train.txt和val.txt内容分别是训练集和验证集图像路径的逐行列表。训练时 YOLO 通过这两个文件找到图像再根据同名规则找到标签文件。这里要提醒的是不管原资源怎么划分的拿到手后第一件事是验证划分是否合理。最怕的是同一个人、同一时间段、背景几乎一样的图像同时出现在训练集和验证集——这会人为抬高验证 mAP让你误以为模型效果很好。合理划分的逻辑是按视频片段划分而不是按单帧随机划分。同一个视频的相邻帧应该全部进训练集或全部进验证集。如果你不清楚原资源的划分方式最稳妥的做法是自己重新划分。把图像按文件名前缀分组——12_002184和12_002185属于同一个视频片段应该放在同一个集合里。按比例 8:2 合并到训练和验证然后重新生成train.txt和val.txt。这一步重新做一次用不了十分钟但能保证后面的评估数字可信。4.2 data.yaml 的配置细节YOLOv5/v8 系列训练前都要写data.yaml内容如下path: ./student_behavior_dataset train: train.txt val: val.txt nc: 2 names: 0: look_down 1: look_side字段说明path是数据集根目录train和val是训练/验证集列表文件的路径相对于pathnc是类别数names是类别名称列表。注意names的顺序必须和标签文件中的 id 一致否则验证时混淆矩阵里每一行代表的含义就错了。注意如果你的图像路径包含中文请把path改成英文路径否则 OpenCV 读取中文路径可能在部分系统上失败。这是 Windows 上非常常见的坑代码层面没有问题但操作系统文件系统编码导致读图失败。4.3 超参数选择的边界与依据行为检测任务和通用目标检测在超参数上最大的区别在图像尺寸和 anchor 设置。2400 张图的规模不算大输入尺寸建议用 640×640 起步不要直接上 1280——样本量不够时大分辨率只会放大标注噪声。批次大小按显存调整常见做法是 16 起步如果出现CUDA out of memory就降到 8。学习率方面YOLOv5 的默认lr00.01、lrf0.2在这个数据规模下够用不需要改。真正值得调的是epochs2400 张图建议先跑到 100 轮看收敛曲线如果 val loss 在 60 轮左右就平台期了后面 40 轮完全是浪费算力。数据增强建议关闭 Mosaic 或降低概率因为低头/转头这类细粒度行为检测Mosaic 拼接后的图像上下文会被破坏模型学到的是「纹理块」而不是「头部姿态」。我一般把mosaic设为 0.5mixup设为 0.2保留平移缩放增强关掉旋转增强——课堂场景里头部不会倒过来。5. 避坑行为检测数据常见的五个坑5.1 现象训练 loss 正常下降但 mAP 一直很低原因最可能的是标注框严重不贴合目标。可视化检查时看到框偏移较大但训练的时候模型强行拟合了偏移的框学到的特征中心偏离头部实际位置。行为检测的目标是头部框中心和头部中心偏差超过 10 个像素就会明显影响 mAP。解决把训练集里损失最大的前 100 张图像可视化重新标注或删除异常样本。别指望模型自动「忽略」错误标注它会尽力拟合。5.2 现象验证集上「低头」识别很好「转头」几乎全漏原因类别不平衡。虽然总共 2400 张但「转头」的标注数量可能只有「低头」的三分之一尤其后排学生转头时面部特征小更难检测。看一眼两个类别的样本计数如果比例超过 3:1问题基本可以确定。解决对「转头」类别做过采样重复复制这部分样本进训练集或者给损失函数加类别权重。我一般先把 val 集里漏检的转头样本拿出来看确认是标注太少还是特征太弱再决定是补数据还是调权重。5.3 现象训练时某个类别的 loss 突变为 NaN原因标签里有坐标或宽高为 0 的异常行。YOLO 训练时解析到这样的标签会导致损失计算除零或对数溢出。前面章节给过标签检查脚本这类问题跑一遍就能发现。解决用脚本扫描所有标签把异常行所在的文件单独挑出来删除异常行或修正坐标。注意不要直接删整个文件——一个文件里可能还有其他正常的框。5.4 现象可视化正常但训练时提示某些图像找不到标签原因图像文件和标签文件数量不匹配。有的图像没有对应标签或者标签文件名比图像多了一个空格或后缀。目录里如果有系统生成的Thumbs.db或隐藏文件也会被误当成标签文件。解决写个计数器比对两个目录的文件名集合把差集列出来。常见做法是写两行 Python 代码求差集比肉眼翻目录快得多。5.5 现象验证精度很高但实际课堂视频里检测结果频繁闪烁原因数据划分泄漏。训练集和验证集包含同一视频的相邻帧模型相当于记住了帧内容而不是学会了行为特征。课堂监控视频帧间差异小这种泄漏非常隐蔽。解决重新按视频片段划分数据集并拿一段全新的课堂视频做端到端测试。如果测试视频上的表现远低于验证集基本可以确定是数据泄漏问题。6. 训练后的数据反馈用混淆矩阵反向检查标签质量训练完成后YOLO 会在runs/val目录下生成混淆矩阵、PR 曲线和验证集预测结果。混淆矩阵不只是给你看模型效果的它更能暴露数据问题。矩阵中如果「低头」预测为「转头」的比例明显偏高说明这两类标注边界在数据里就互相渗透——有些图像标注为低头但视觉上头部已经右转了。我的检查方法是取混淆矩阵里误分类概率最高的 50 张验证图像把真实标签和预测框同时画出来。重点看两件事一是真实框区域里到底是不是真的低下了头如果角度介于低头和正常之间说明标注时采用了比较松的标准二是预测框是否偏左或偏右偏右往往意味着图像里后脑勺的特征比面部特征更显著学生背对镜头时模型只能靠轮廓推断。这个反馈回路比单纯调参有用得多。有次我发现「低头」类别的 recall 只有 0.82翻图才发现大量标注框框住了伏桌休息的学生——头部完全被手臂遮挡模型根本无法从视觉上判断低头状态。这类样本应该从训练集剔除因为它对模型传递的是「手臂遮挡的桌子也属于低头」的错误信号。从那以后我每次拿到新的行为检测数据都会强制走一遍流程先跑 show.py 可视化抽看 50 张图判断标注风格再用脚本检查标签数值边界然后验证 train/val 划分是否按片段隔离最后训练完用混淆矩阵反查标签质量。这套流程下来2400 张的数据量虽然不大但训练出来的模型在真实课堂场景里表现足够稳定——因为数据里每一张图都是有效的、可信的。这份资源最大的价值不是「2400 张」这个数字而是它给了你一个完整的数据闭环起点。希望帮到你。本文还有配套的精品资源点击获取