资讯详情

电梯内人车识别数据集详解:从YOLO标签到模型训练实战

📅 2026/9/24 23:42:20 | 华诺云谱 👁 阅读
电梯内人车识别数据集详解:从YOLO标签到模型训练实战
简介电梯内人车识别是智慧楼宇与安防场景中常见的细粒度目标检测任务。数据集围绕电梯监控视角采集标注person人、motorcycle摩托车、bicycle自行车三类目标覆盖97张图片并提供YOLO与VOC两种格式的标签txt文件以及包含类别信息的yaml配置可直接用于YOLOv5、YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10及Faster Rcnn、SSD等常见目标检测模型训练。压缩包内共2000个文件其中1999个为标签txt、1个为yaml配置文件整体大小约193.33MB目录结构简洁方便直接导入训练框架进行验证。目前已有200人学习适合正在做目标检测课程设计、算法对比或电梯场景落地项目的开发者与研究者。借助该数据集可省去自行采集与标注成本快速评估模型在电梯实际场景中的识别表现。1. 电梯内人车识别数据集小样本也能把检测模型跑起来做监控场景目标检测的同行应该都有体会公开数据集里车流、行人一大把但一进电梯这个封闭场景能用的数据立刻断档。这次拆的是一份电梯内人车识别数据集97张图片标注了person、motorcycle、bicycle三类目标同时给了YOLO格式的txt标签和适配YOLOv5到YOLOv10的yaml配置文件。数据量不大但场景垂直、标注格式干净适合用来做电梯监控、园区出入口、非机动车管理这类项目的模型验证和迁移学习起点。你不需要自己爬图、洗数据、重新标注下载后直接把目录结构理清楚就能开训。这篇文章会从文件格式、标签解读、训练配置到踩坑记录完整过一遍按步骤走完你应该能拿到一个可用的检测权重。2. 数据集文件拆解从txt文件名到标签内容都要看懂2.1 文件名的编码规律与来源判断这份数据集的图片和标签文件命名方式很有特点比如person_in_elevator_3_dat_07-22-2022_time_19-39-09_png.rf.64f6e22d966854811ff2d0273822e03c.txt拆开看能获取不少有效信息。person_in_elevator_3是场景语义标签说明这是电梯内的行人画面3是镜头或采集批次编号dat_07-22-2022_time_19-39-09是采集时间戳png.rf表示原始图片是PNG格式.rf是Roboflow平台导出时追加的后缀最后一段哈希值是样本的唯一ID。理解这个命名规律对后续数据管理有价值。比如你在做数据清洗时可以通过文件名中的_2_、_3_、_4_快速判断样本来自哪个采集批次如果训练时发现某个批次的图片泛化特别差可以直接按这个字段做分组排查。另外这类带.rf后缀的文件名在Roboflow导出的数据集里非常常见你拿到手第一步应该做的是去掉.rf段或整体重命名否则后续脚本处理文件名时容易出幺蛾子。# 批量重命名去掉 .rf 段 import os import re label_dir labels for f in os.listdir(label_dir): if f.endswith(.txt): # 把 .rf.xxxxxxxx 段替换为空 new_name re.sub(r\.rf\.[a-f0-9], , f) os.rename(os.path.join(label_dir, f), os.path.join(label_dir, new_name))这段脚本做的事很简单遍历标签目录用正则把.rf.加一串十六进制字符的段删掉。注意图片文件名也要做同样处理否则图片和标签对不上。正则里的[a-f0-9]是哈希段万一你的文件名有大小写混合把正则改成[a-f0-9A-F]就行。2.2 YOLO标签格式的归一化坐标解读标签文件里每行对应一个目标框格式是class x_center y_center width height五个值全部是相对于图片宽高的归一化坐标。拿电梯场景举例一行数据可能是0 0.482366 0.536238 0.166102 0.610467含义是类别0person的目标框中心点在图片水平48.24%、垂直53.62%的位置框宽度占图片宽16.61%高度占图片高61.05%。类别编号从0开始对应关系在yaml文件里定义。这份数据集的三类映射是0: person、1: motorcycle、2: bicycle。有个细节容易踩坑yaml文件里如果类别顺序是[person, motorcycle, bicycle]那编号0、1、2就按这个顺序走训练前务必确认txt标签里的类别编号和yaml顺序一致否则模型会把人识别成摩托车。# 快速统计标签分布确认类别编号合理 import os from collections import Counter label_dir labels class_counter Counter() for f in os.listdir(label_dir): with open(os.path.join(label_dir, f), r) as fp: for line in fp: cls_id int(line.strip().split()[0]) class_counter[cls_id] 1 print(类别编号分布:, dict(class_counter))跑完这段统计你会看到三类目标各自的数量。如果发现某个类别的编号乱跳比如出现3说明标签里有脏数据得回到标注工具里重新校验。做这一步的意义在于训练前发现类别错位比训练完发现mAP异常再去排查要省一天时间。2.3 VOC格式与YOLO格式的取舍摘要里提到这份数据集同时适配YOLO与VOC两种格式实际使用时你得理解两者的差异。VOC格式是XML文件每个文件里写object节点包含name、bndbox的绝对坐标xmin, ymin, xmax, ymaxYOLO格式是txt文件写归一化坐标。VOC的可读性好用LabelImg标注时默认就是VOC格式YOLO格式省空间、读取快训练时无需二次解析。对于YOLO系列算法我建议直接用txt格式训练不要转来转去。转格式的过程看似简单但坐标转换、边界裁剪、类别映射每个环节都可能引入误差。比如把VOC的绝对坐标转成YOLO归一化坐标时x_center (xmin xmax) / 2 / img_width这公式不复杂但如果你在脚本里把img_width和img_height写反了所有框的位置都会偏移训练出来的模型检测框会整体错位。这份数据集本身已经是YOLO格式省掉了转换这一步老老实实用就行。3. 训练前准备数据集划分与yaml配置3.1 目录结构规划与划分比例拿到数据集后第一件事不是直接开训而是把目录结构整理成YOLO系列算法期望的样子。常见做法是elevator_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml97张图片的总量不大划分比例建议用8:2或者7:3我习惯用train:val:test 70:20:10测试集留着最后验证。由于这份数据集本身是从Roboflow导出的通常已经带了划分好的train/val/test目录你拿到手先看结构如果已经划分好就别动直接操作如果没划分自己写脚本划分时注意一个原则同一个场景的连续帧不要同时出现在训练集和验证集里否则验证结果虚高。# 数据划分脚本按文件名哈希做分层采样 import os import random import shutil random.seed(42) img_dir images_all train_ratio, val_ratio 0.7, 0.2 imgs [f for f in os.listdir(img_dir) if f.endswith(.jpg) or f.endswith(.png)] random.shuffle(imgs) train_imgs imgs[:int(len(imgs) * train_ratio)] val_imgs imgs[int(len(imgs) * train_ratio):int(len(imgs) * (train_ratio val_ratio))] test_imgs imgs[int(len(imgs) * (train_ratio val_ratio)):] for split, split_imgs in zip([train, val, test], [train_imgs, val_imgs, test_imgs]): os.makedirs(fimages/{split}, exist_okTrue) os.makedirs(flabels/{split}, exist_okTrue) for img in split_imgs: shutil.copy(fimages_all/{img}, fimages/{split}/{img}) label_name img.rsplit(., 1)[0] .txt if os.path.exists(flabels_all/{label_name}): shutil.copy(flabels_all/{label_name}, flabels/{split}/{label_name})这段脚本的几个关键点random.seed(42)固定随机种子保证每次划分结果一致test_imgs是余量不指定比例也能保证三类划分之和等于全集。如果你发现某张图片没有对应的txt标签文件空标签脚本里if os.path.exists已经做了保护但这样的图片建议单独拎出来看是背景图还是漏标。3.2 data.yaml的写法与参数含义YOLOv5到YOLOv10的yaml配置文件结构基本一致# data.yaml path: /path/to/elevator_dataset # 数据集根目录绝对路径 train: images/train # 训练集图片目录相对path val: images/val # 验证集图片目录 test: images/test # 测试集图片目录可选 nc: 3 # 类别数量 names: [person, motorcycle, bicycle] # 类别名称顺序必须与标签编号对应几个容易出问题的参数path字段在YOLOv8里支持绝对路径和相对路径但如果你在别的机器上跑这个配置绝对路径会失效建议改成相对路径或者用dataset.yaml里不写path直接在命令行指定--data /full/path/data.yaml。nc的值必须和names列表长度一致否则训练直接报错。注意names的顺序不只是给人类看的训练时类别索引就是按这个顺序分配的前面已经强调过要和txt标签里的编号一致。一个低级的坑如果你的数据集里只有person和motorcycle两类有标注bicycle没有任何标注框nc: 3依然要保留只是bicycle类在训练中的loss贡献为零验证时它的AP会是0。这种情况下可以考虑去掉这个空类别减少模型输出维度让训练更稳定。3.3 用脚本做标注质量巡检训练前做个快速巡检能省掉大量排错时间。巡检内容至少包含三项标签坐标是否越界归一化值在0到1之外、框面积是否过小、是否有重叠框。import os label_dir labels/train for f in os.listdir(label_dir): with open(os.path.join(label_dir, f), r) as fp: for line in fp: parts line.strip().split() if len(parts) ! 5: print(f格式错误: {f} - {line.strip()}) continue cls, xc, yc, w, h int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) if not (0 xc 1 and 0 yc 1 and 0 w 1 and 0 h 1): print(f坐标越界: {f} - {line.strip()}) if w * h 0.0001: print(f框过小: {f} - {line.strip()})巡检脚本输出的每一条都值得认真看。坐标越界通常是因为标注时图片尺寸和训练时不一致或者标注工具导出bug框过小可能是标注失误也可能是目标真的特别小比如远处的人后者在训练时考虑是否保留。巡检通过后再进训练阶段翻车概率会小很多。4. 用YOLOv8训练这份数据集命令与参数调优4.1 环境准备与安装YOLOv8是目前使用门槛最低的YOLO版本pip安装就能用pip install ultralytics如果你要跑的是YOLOv5clone官方仓库然后pip install -r requirements.txt即可。YOLOv6、YOLOv7各有各的安装方式但ultralytics库已经统一支持了YOLOv5和YOLOv8的模型定义跑这份数据集建议直接用YOLOv8省去环境兼容的麻烦。一个细节ultralytics包会依赖torch如果你的机器是NVIDIA显卡先装对应CUDA版本的torch再装ultralytics否则pip默认装的torch可能是CPU版训练速度慢一个数量级。验证GPU可用性python -c import torch; print(torch.cuda.is_available())输出True说明GPU可用False就回去重装torch别硬着头皮用CPU跑97张图虽然不大但CPU迭代几百个epoch也够你等一天的。4.2 训练命令逐参数拆解yolo detect train \ --model yolov8n.pt \ --data data.yaml \ --epochs 200 \ --batch 16 \ --imgsz 640 \ --lr0 0.01 \ --patience 30 \ --device 0 \ --workers 4 \ --project runs/elevator \ --name yolo8n_baseline参数说明--model yolov8n.pt选择预训练权重n是nano版本模型最小、速度最快97张图的小数据集从nano起步最合适。如果你想追求精度可以试s或m版本但数据量不够时大模型容易过拟合。--epochs 200训练轮数。数据集小200轮够用了配合patience做早停。--batch 16批次大小显存不够就降到8。--imgsz 640输入分辨率。电梯监控画面通常是广角镜头目标偏小如果显存允许可以试--imgsz 960小目标检测效果会有明显提升。--lr0 0.01初始学习率YOLOv8默认是这个值小数据集不需要改。--patience 30连续30个epoch验证集指标不提升就早停防止无效训练。--device 0用第一张GPU卡CPU训练改成--device cpu。训练结束后runs/elevator/yolo8n_baseline/weights/best.pt就是验证集上表现最好的权重文件后续推理直接加载它。4.3 训练日志怎么看训练过程中终端会滚动输出每个epoch的loss、mAP50、mAP50-95等指标。重点看三个数值box_loss、cls_loss、dfl_loss三者都在持续下降说明训练正常收敛。mAP50是IoU阈值0.5下的平均精度mAP50-95是更严苛的综合指标后者才是模型真实能力的反映。小数据集训练经常出现的情况是mAP50很高比如0.9以上但mAP50-95很低0.5左右这说明模型对目标位置的预测不够精准常见原因是标注框不够紧或者输入分辨率偏低。遇到这种情况我的建议是检查标注质量而不是盲目加训练轮数。5. 避坑指南小目标漏检、类别错位与过拟合5.1 小目标漏检现象、原因与解决现象训练完成后跑测试集低楼层电梯画面里稍微远一点的人检测不到近处的摩托车能检测到但框偏大。原因电梯的广角摄像头拍出的画面里距离镜头远的人可能只有20×40像素而默认训练分辨率640×640下这些目标经过网络下采样后在特征图上只占几个像素点特征信息太少。另一个原因是标注时小目标的框本身就有偏差框大了一圈或歪了一点模型学到的是模糊的边界。解决把--imgsz提到960或1280小目标在特征图上占的像素变多检测率会明显上升。代价是显存占用增大、训练速度下降。如果显存不够改用YOLOv8的P2检测头版本yolov8n-p2.pt它在原有基础上增加了更浅层的特征图融合专门强化小目标检测。最后检查标注框是否贴合目标边缘框比目标大20%以上时建议重新标注。5.2 类别编号错位训练不报错但结果全错现象训练正常收敛loss下降、mAP看着正常但推理时把摩托车识别成自行车、把自行车识别成摩托车。原因yaml文件里names顺序和txt标签里的类别编号不一致。比如标签里1代表motorcycle但yaml里names: [person, bicycle, motorcycle]模型学到的是编号映射关系输出时按yaml顺序解释自然错位。解决训练前用前面第2章的统计脚本打印标签里的class_id分布再对照yaml的names逐一确认。没有捷径就是养成训练前检查类别映射的习惯。5.3 过拟合loss很低但验证集效果差现象训练集loss降到接近0mAP50有0.98但验证集mAP50只有0.6差距明显。原因97张图实在太少了模型把训练集的背景、光照、角度都背了下来。电梯场景尤其明显——同一个摄像头拍的连续帧背景几乎不变模型学到的是背景特征而不是目标本身的特征。解决第一优先做数据增强YOLOv8默认开了hsv_h、hsv_s、hsv_v、fliplr等增强项可以再打开mosaic和mixup增强方式在配置文件里设置mosaic: 1.0、mixup: 0.2。第二优先从大模型换小模型yolov8n换成yolov8n已经是最小了那就减少训练轮数配合更强的早停patience降到15。第三考虑补充数据哪怕收集几十张不同电梯的图片做增量训练对泛化能力的提升都远大于在97张图上硬调超参数。5.4 图片和标签文件数量不一致现象训练时报错找不到标签文件或者验证时大量图片没有预测框。原因有些图片没有对应标注纯背景帧或者导出时漏了标签文件。Roboflow导出的数据集一般不会漏但自己整理数据时很容易出现。解决写个脚本做一次双向校验把只有图片没有标签的文件列入黑名单训练时从train.txt和val.txt里剔除。5.5 类别不平衡bicycle样本极少现象训练结束后bicycle类的AP接近0模型完全学不会识别自行车。原因电梯场景里自行车出现的频率远低于行人和摩托车标签分布大概率是person占60%以上、motorcycle占30%、bicycle不到10%。样本太少模型把bicycle的特征当作噪声忽略。解决代码层面做类别权重YOLOv8里没有直接参数可以用--class_weights部分版本支持或者复制bicycle样本做重复采样。最直接的方案是把bicycle类别合并到motorcycle里当成一类两轮车来训练虽然评估维度变粗但比模型完全检测不到要实用。6. 验证与进阶从跑通到能用的小技巧训练结束不是终点验证模型能不能用才见真章。先说验证方法YOLOv8训练完成后会自动在测试集上跑一轮推理但你要做的是手动挑几张没参与训练的真实电梯画面做推理验证。重点关注三类场景光线变化的画面、拥挤场景、目标被部分遮挡的画面。推荐写个小脚本批量跑推理并把预测结果可视化输出from ultralytics import YOLO model YOLO(runs/elevator/yolo8n_baseline/weights/best.pt) results model.predict(sourcetest_imgs/, saveTrue, conf0.25, imgsz640)conf0.25是置信度阈值调低到0.15能看到更多漏检目标调高到0.5能看到更多误检。针对电梯场景我建议阈值在0.3到0.4之间太低容易把安全帽、背包误检成人。进阶一点的做法是统计模型的F1曲线在runs/elevator/yolo8n_baseline/目录下找到F1_curve.png取曲线峰值对应的置信度作为实际部署阈值。再提两个实战技巧。第一电梯场景的检测模型部署到端侧设备时imgsz不要用过大的分辨率端侧推理速度和帧率直接相关640和960的推理耗时差距不止一倍。如果一定要在小目标检测上提精度优先换硬件而不是堆分辨率。第二做迁移学习时不要从头训练务必用yolov8n.pt这类预训练权重做起点哪怕你的数据和COCO完全不沾边预训练权重里学到的底层特征边缘、纹理、颜色依然能加速收敛。用过这份数据集之后我的一个深刻教训是小数据集的模型训练最大的风险不是模型结构选得不对而是数据质量检查不到位。从那以后我每次拿到新数据集不管标注来源是平台还是外包一律先跑一遍标签巡检脚本确认格式、类别、坐标边界全部合规才允许进入训练流程。这个习惯帮我省掉了太多训练了一天结果全乱套的局面。做好数据质量管控配合合理的参数设置97张图一样能训出可用的电梯人车检测模型希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。