铁路人员危险行为检测数据集:VOC+YOLO双格式3766张,含YOLO训练避坑指南
简介这份数据集面向智慧交通与铁路安全场景下的行为识别研究主要解决铁路上人员危险行为躺卧、坐卧、站立与轨道区域的自动检测问题适合计算机视觉方向的学生、算法工程师及铁路安防项目开发者使用。资源包共2000个文件以1999个xml标注文件和1个说明txt为主压缩包约920.36MB标注采用labelImg工具以矩形框方式完成可直接用于VOC与YOLO两种格式的训练流程。数据集包含3766张jpg图片及对应标注共4个类别sitting 1406框、sleeping 689框、standing 1782框、track 1819框总框数5696覆盖铁路上人员行为与轨道区域动物等目标未作标注。需注意包内含有较多增强图片建议下载前仔细查看图片质量再斟酌使用。目前已有703人学习下载可为铁路人员危险行为检测模型的训练、验证与对比实验提供现成标注基础帮助读者快速搭建检测流程并评估不同算法在该场景下的表现。1. 铁路场景下的人员危险行为检测这份 3766 张 VOCYOLO 数据集能解决什么铁路站台和沿线的人员安全监控长期依赖人工盯屏一个班次下来眼睛发酸还容易漏判。真正落到算法侧第一个卡住你的往往不是模型结构而是「没有标注好的行为数据」。这份智慧交通铁路人员危险行为数据集给了 3766 张实拍图覆盖 sitting、sleeping、standing、track 四个类别同时提供 Pascal VOC 的 XML 和 YOLO 的 TXT 两套标注总框数 5696。它解决的就是「从零标注成本高、类别定义不统一」这个前置问题适合做铁路安防算法验证、行为识别课程设计或者想快速跑通 YOLO 训练流程的从业者。需要提前说清楚数据里混了不少增强图动物没有标注下载前得先掂量自己的场景匹配度。2. 拆开压缩包VOC 与 YOLO 双格式的目录结构和字段含义拿到.7z之后别急着解压完就丢进训练脚本先花十分钟把目录和标注格式对一遍后面能省掉大量排查时间。这份数据的组织方式比较典型图片和标注同名不同后缀VOC 走 XMLYOLO 走 TXT两边一一对应。2.1 文件清单与命名规律解压后你会看到三类文件混在同一层或者分目录存放.jpg原图、.xml的 VOC 标注、.txt的 YOLO 标注外加一个使用前必读.txt。从项目正文给出的样本看命名是firc_railway_数字这种形式比如firc_railway_671.xml、firc_railway_25.xml。这个前缀firc大概率是数据集来源的缩写后面的数字是全局唯一编号图片、XML、TXT 三者的编号必须一致这是配对的关键。文件类型数量作用jpg 图片3766训练/验证输入xml 标注3766VOC 格式含 bbox 与类别txt 标注3766YOLO 格式归一化坐标使用前必读.txt1作者的使用说明数量三者对齐说明没有出现「有图无标」或「有标无图」的情况这点比很多野生数据集规范。但要注意3766 是图片总数不是独立场景数增强图会重复出现相似画面。2.2 VOC XML 的字段怎么读VOC 格式是 Pascal VOC 那套老规矩一个 XML 对应一张图核心节点是filename、size、object。object里又有name类别、bndboxxmin/ymin/xmax/ymax 像素坐标。用 Python 快速验证一个文件import xml.etree.ElementTree as ET tree ET.parse(firc_railway_671.xml) root tree.getroot() # 图片尺寸YOLO 归一化要用到 size root.find(size) w int(size.find(width).text) h int(size.find(height).text) for obj in root.findall(object): name obj.find(name).text box obj.find(bndbox) xmin int(box.find(xmin).text) ymin int(box.find(ymin).text) xmax int(box.find(xmax).text) ymax int(box.find(ymax).text) print(name, xmin, ymin, xmax, ymax, img:, w, h)这段代码做两件事读出图片宽高再逐个打印目标的类别和像素框。size节点必须存在否则后面转 YOLO 时没法归一化。如果你发现某个 XML 里size的宽高和实际 jpg 对不上那这张图大概率被裁剪或缩放过了得单独处理。2.3 YOLO TXT 的归一化坐标YOLO 的 TXT 每行一个目标格式是class_id x_center y_center width height全部是相对图片宽高的 0~1 浮点数。类别用整数索引顺序通常按类别名排序或按作者定义。这份数据四个类别索引大概率是 0sitting、1sleeping、2standing、3track但不要假设一定要用 XML 反推验证因为索引错位是训练不收敛的经典原因。# 验证 TXT 与 XML 是否一致 with open(firc_railway_671.txt) as f: for line in f: cid, xc, yc, bw, bh line.split() # 反归一化回像素和 XML 对比 print(int(cid), float(xc)*w, float(yc)*h, float(bw)*w, float(bh)*h)把反归一化的结果和 XML 的框对一下误差在 1~2 像素内算正常差太多说明标注被改过。这一步做完你才对这份数据的「干净程度」有底。3. 用这份数据跑通 YOLO 训练从 data.yaml 到第一个 epoch格式确认没问题接下来就是把它喂给 YOLO。不管你是用 Ultralytics 的 YOLOv8/v11还是老版 darknet核心都是「图片路径 标签路径 类别名」三件事对齐。这里以当前主流的 Ultralytics 流程为例因为它在 PyCharm 里装完就能跑对新手最友好。3.1 目录重组与 data.yaml 编写原始数据是平铺的YOLO 训练一般要求images/train、labels/train这种结构。写个脚本按 8:2 切分注意同一张图的增强版本要分到同一侧否则验证集里出现训练集的近似副本指标会虚高。import os, shutil, random src_img raw/images src_lbl raw/labels random.seed(42) files [f for f in os.listdir(src_img) if f.endswith(.jpg)] random.shuffle(files) split int(len(files) * 0.8) for i, f in enumerate(files): subset train if i split else val stem os.path.splitext(f)[0] shutil.copy(os.path.join(src_img, f), fdataset/images/{subset}/{f}) shutil.copy(os.path.join(src_lbl, stem .txt), fdataset/labels/{subset}/{stem}.txt)random.seed(42)保证切分可复现换机器结果一致。切完检查一下train和val的类别分布如果sleeping在验证集里只有个位数指标波动会很大可以手动调几张过去。data.yaml 是训练的入口配置path: ./dataset train: images/train val: images/val nc: 4 names: [sitting, sleeping, standing, track]nc必须等于 4names的顺序必须和 TXT 里的 class_id 严格对应。这里再强调一次顺序错了模型学出来的类别就是乱的loss 看着降但预测全错。3.2 启动训练与关键参数装好环境后一条命令开跑yolo detect train datadata.yaml modelyolov8n.pt epochs100 imgsz640 batch16modelyolov8n.pt用 nano 版先验证流程别一上来就上大模型数据本身有增强图小模型足够看出问题。imgsz640是通用值如果你的原图分辨率远高于此小目标比如远处躺着的人会被压没可以试 960。batch16看显存调爆显存就降到 8。训练时重点盯三个数box_loss是否稳定下降、mAP50是否在 20 个 epoch 后有起色、cls_loss是否异常高。如果cls_loss居高不下八成是类别索引或 names 顺序错了回去查 3.1。3.3 推理验证与结果解读训完拿验证集跑一遍yolo detect predict modelruns/detect/train/weights/best.pt sourcedataset/images/val saveTrue看输出图重点检查两类错误把standing误判成track人站在轨道上框重叠导致以及sleeping漏检躺姿目标扁长anchor 不匹配。这两种是铁路行为检测的高频问题不是数据错是场景本身难分。可以针对性加几张困难样本重训。4. 避坑与排查这份数据集最容易翻车的五个地方数据拿到手到跑出可用模型中间踩的坑比想象中多。下面五条是我处理同类行为数据集时反复遇到的按「现象 → 原因 → 解决」列清楚。现象一训练 loss 正常下降但预测框全是一个类别。原因TXT 里的 class_id 和 data.yaml 的 names 顺序不一致模型把所有目标都学成了索引 0。 解决用 2.3 的脚本反查一个 TXT 的类别分布和 XML 的name统计对比确认映射关系后再改 yaml。现象二验证集 mAP 高得离谱实际测试一塌糊涂。原因增强图被随机切分训练集和验证集出现近似副本等于变相泄漏。 解决切分前先按图片内容聚类或按原始编号分组保证同一场景的增强版本只进一侧。现象三track类别框数 1819但模型几乎不预测它。原因track是轨道这种大面积、长条形目标和standing的人框大量重叠标注时边界模糊。 解决训练时适当提高track的损失权重或者后处理阶段对重叠框做 NMS 阈值调整别用默认 0.7。现象四解压后图片能打开但 XML 解析报错。原因部分 XML 编码不是 UTF-8或者使用前必读.txt里提到的增强图带了非标准字符。 解决读取时显式指定encodingutf-8失败就errorsignore再检查size节点是否完整。现象五直接拿全部 3766 张训练显存不够或速度极慢。原因增强图占比不低实际有效样本远少于 3766全量训练性价比低。 解决先抽样 1500 张跑通流程确认类别平衡后再逐步加量别一上来就全量。提示使用前必读.txt里作者明确说了「有很多增强图片」这句话的分量比看起来重它直接决定你的验证集是否可信务必在切分阶段就处理掉。5. 进阶技巧用类别权重和困难样本挖掘把 sleeping 检出率提上来四个类别里sleeping只有 689 个框是standing的零头典型的类别不平衡。默认训练下模型会偏向多数类躺着的人漏检严重。我一般会走两步先给损失函数加类别权重再做一轮困难样本回捞。Ultralytics 本身不直接暴露类别权重参数但可以在 data.yaml 同级写一个hyp.yaml覆盖默认超参或者更直接的办法——对sleeping样本做定向过采样。下面这个脚本把含sleeping的图复制一份进训练集简单粗暴但有效import os, shutil lbl_dir dataset/labels/train img_dir dataset/images/train for f in os.listdir(lbl_dir): with open(os.path.join(lbl_dir, f)) as fp: lines fp.readlines() # class_id 1 对应 sleeping按你的实际映射改 if any(line.startswith(1 ) for line in lines): stem os.path.splitext(f)[0] shutil.copy(os.path.join(img_dir, stem .jpg), os.path.join(img_dir, dup_ stem .jpg)) shutil.copy(os.path.join(lbl_dir, f), os.path.join(lbl_dir, dup_ f))复制出来的dup_文件参与训练但不进验证集这样既提升sleeping的梯度贡献又不污染评估。跑完一轮后对比sleeping的 recall通常能从 0.5 左右提到 0.7 以上。第二步是困难样本挖掘。用训好的模型在验证集上推理把sleeping漏检或置信度低于 0.3 的图挑出来人工复核标注是否有误确认无误后加进训练集再训一轮。这个循环做两到三次模型对躺姿的敏感度会明显改善。策略操作预期效果过采样复制含 sleeping 的图recall 0.15 左右困难样本回捞低置信度图复核后加训边界样本更稳提高 imgsz640 提到 960远处小目标改善最后说个习惯每次动数据之前我都会先跑一遍类别统计脚本把四个类别的框数和图片数打出来存档。因为增强图的存在这份数据的「表面数量」和「有效数量」是两回事只有每次训练前都确认一遍分布才能保证指标可比。从那以后我每次换数据集或改切分都强制走一遍统计再开训省了太多返工。希望帮到你。本文还有配套的精品资源点击获取