尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

楼梯检测数据集:1043张YOLO+VOC格式图像的目标检测训练实践

发布时间:2026/9/27 1:03:29

资讯中心
01
ARTICLE

楼梯检测数据集:1043张YOLO+VOC格式图像的目标检测训练实践

楼梯检测数据集:1043张YOLO+VOC格式图像的目标检测训练实践
简介目标检测楼梯场景的专用数据集内含1043张清晰楼梯图片及对应标注适合训练楼梯或台阶识别模型面向计算机视觉初学者、算法调参工程师以及需要特定场景数据的科研人员。压缩包同时提供VOC格式xml与YOLO格式txt两套标注可直接导入YOLOv5、YOLOv8、Faster R-CNN等常见检测框架省去自行转换格式的麻烦。资源共2000个文件以jpg图片、xml标注和txt标签文件为主压缩包约9.49MB内部划分为JPEGImages、Annotations、labels三个目录分别存放原始图像、VOC框标注和YOLO标签文件结构清晰方便按需取用。所有图片均为矩形框标注类别仅“staircase”总计1224个目标框未做数据增强图片清晰度较高适合作为基础训练集或迁移学习数据。每个标签文件与图片一一对应训练时无需额外清洗数据可直接用于模型精度对比、训练流程验证或教学示例。目前已有88人学习下载对刚接触目标检测的开发者是一份低门槛、可直接上手的实操数据便于快速开展楼梯识别相关实验。1. 楼梯数据集 1043 张 YOLOVOC 格式这个压缩包能解决什么做楼宇巡检机器人、服务机器人和视觉辅助导航的时候楼梯检测是最容易被忽视、却又最容易翻车的一个目标。通用目标检测模型里几乎没有专门针对楼梯的优质样本网上能找到的楼梯图片要么混在室内场景数据集里要么只有几个类别标得稀稀拉拉。这个“楼梯数据集1043张YOLOVOC格式.zip”解决的正是这个空档1043张实拍楼梯图像同时给了 YOLO 的 txt 标签和 VOC 的 xml 标签覆盖室内楼梯、室外台阶、扶梯入口、暗光楼道等常见形态拿来就能直接喂给 YOLOv5/YOLOv8 或 RT-DETR 做训练。它适合三类人做服务机器人导航避障的工程师想在模型里单独加一个“楼梯”类别而不是靠人工规则兜底做楼宇数字化和安监巡检的团队需要识别楼梯口、台阶区域以及刚接触目标检测、想用一个干净的小数据集跑通全流程的初学者。1043张的量级说大不大说小不小但配合预训练权重微调和合理的数据增强做单类别检测足够出效果。下面从数据格式、训练流程、踩坑点和验证部署一路讲完。2. 拆开这个压缩包VOC 与 YOLO 格式怎么对应标签怎么校验拿到任何一个目标检测数据集我的第一反应都不是急着开训而是先花半小时把标签结构摸清楚。尤其是这种双格式的压缩包VOC 和 YOLO 两份标签是同一批标注的两种表达搞清楚它们的对应关系后面训练和分析结果才不会被坑。2.1 压缩包目录长什么样文件命名与两份标签的对应关系这类数据集压缩包最常见的布局是下面这样如果你的包略有出入按文件名前缀对齐即可楼梯数据集1043张YOLOVOC格式.zip ├── images/ # 1043 张 JPG 原始图像 ├── labels/ # 1043 个 txtYOLO 格式标签 ├── Annotations/ # 1043 个 xmlVOC 格式标签 ├── classes.txt # 类别清单通常只有一列 ├── train.txt # 训练集图片路径列表 └── val.txt # 验证集图片路径列表文件命名一般遵循“同名前缀”规则images/stairs_0001.jpg对应labels/stairs_0001.txt和Annotations/stairs_0001.xml。后缀不同、前缀一致靠这个对齐图像和标签。VOC 格式的 xml 长这样annotation filenamestairs_0001.jpg/filename size width1280/width height720/height depth3/depth /size object namestair/name bndbox xmin120/xmin ymin340/ymin xmax980/xmax ymax680/ymax /bndbox /object /annotationYOLO 格式的 txt 每一行是五个数字0 0.429688 0.708333 0.671875 0.472222第一列是类别 ID从 0 开始后四列分别是归一化后的中心点 x、中心点 y、框宽、框高取值都在 0 到 1 之间。换算关系是cx (xmin xmax) / 2 / 图像宽w (xmax - xmin) / 图像宽y 方向同理除以图像高。VOC 里 xmin/xmax 用的是像素坐标YOLO 里用的是相对整张图的比值同一个框两种表达方式。2.2 写脚本解析 YOLO 标签并检查坐标越界很多看似正常的数据集里面藏着坐标越界、宽高为 0、类别 ID 超出范围这类脏数据。它们不会让训练立刻报错但会让 loss 曲线莫名其妙地抖动。我一般会在训练前用下面这个脚本全量扫一遍import os from pathlib import Path from PIL import Image label_dir Path(labels) img_dir Path(images) for txt in sorted(label_dir.glob(*.txt)): img_path img_dir / (txt.stem .jpg) if not img_path.exists(): print(f[缺失] {img_path.name} 没有对应图片) continue # 用 PIL 读真实宽高不要轻信文件名里的尺寸信息 w, h Image.open(img_path).size for i, line in enumerate(open(txt, encodingutf-8)): parts line.strip().split() if len(parts) ! 5: print(f[格式] {txt.name} 第 {i1} 行: 期望 5 列实际 {len(parts)} 列) continue cls_id, cx, cy, bw, bh parts cls_id int(cls_id) cx, cy, bw, bh map(float, (cx, cy, bw, bh)) # 归一化坐标的合法区间是 [0, 1] if not (0 cx 1 and 0 cy 1): print(f[越界] {txt.name} 第 {i1} 行: 中心点越界 - {line.strip()}) if bw 1 or bh 1 or bw 0 or bh 0: print(f[异常] {txt.name} 第 {i1} 行: 宽高异常 - {line.strip()}) if cls_id ! 0: # 单类别数据集通常是 0 print(f[类别] {txt.name} 第 {i1} 行: 未知类别 ID {cls_id})这个脚本的核心逻辑是逐行解析 txt把五个字段拆开做区间判断。cls_id越界这类问题训练时通常不爆错但推理时模型会输出莫名其妙的类别中心点、宽高越界则会直接污染 loss 计算。用PIL.Image.open(img_path).size拿真实尺寸比读文件名里的尺寸可靠——有些预处理脚本会顺手缩放图片但不更新标签这种错位只能靠这种方式抓出来。这个脚本跑完如果输出为空说明标签文件在格式上是干净的。注意这只是合法性校验不保证标注内容正确——标注框是否贴边、楼梯是否漏标脚本看不出来需要人工抽检。2.3 VOC XML 转 YOLO txt归一化换算与边界裁剪如果后面想换框架训练比如从 YOLO 转到 SSD 或 Faster R-CNN可能需要反向转成 VOC 格式如果你拿到的包只有 VOC 标签也需要能自己转成 YOLO。下面这个脚本把 xml 批量转成 txtimport xml.etree.ElementTree as ET from pathlib import Path xml_dir Path(Annotations) out_dir Path(labels_yolo) out_dir.mkdir(exist_okTrue) # 类别到 ID 的映射顺序必须和 data.yaml/classes.txt 一致 cls_to_id {stair: 0} for xml_path in sorted(xml_dir.glob(*.xml)): root ET.parse(xml_path).getroot() W int(root.find(size/width).text) H int(root.find(size/height).text) lines [] for obj in root.findall(object): name obj.find(name).text if name not in cls_to_id: print(f[跳过] {xml_path.name} 里的未知类别: {name}) continue b obj.find(bndbox) xmin float(b.find(xmin).text) ymin float(b.find(ymin).text) xmax float(b.find(xmax).text) ymax float(b.find(ymax).text) # 边界裁剪防止标注手误导致框超出图片范围 xmin max(0, min(xmin, W - 1)) xmax max(0, min(xmax, W - 1)) ymin max(0, min(ymin, H - 1)) ymax max(0, min(ymax, H - 1)) if xmax xmin or ymax ymin: print(f[剔除] {xml_path.name} 中的空框/负宽高框) continue cx (xmin xmax) / 2 / W cy (ymin ymax) / 2 / H bw (xmax - xmin) / W bh (ymax - ymin) / H lines.append(f{cls_to_id[name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) out_path out_dir / (xml_path.stem .txt) out_path.write_text(\n.join(lines), encodingutf-8) print(f转换完成输出目录: {out_dir})注意这里的几个关键点cls_to_id的映射顺序必须和模型训练的 names 顺序一致否则类别 ID 全错位边界裁剪用的是min(xmax, W-1)因为有些标注工具允许框稍微出界裁剪后可以避免归一化出现大于 1 的数值xmax xmin的空框直接跳过训练时这种框会让损失变成 NaN。先校验后转换再训练这套流程能筛掉绝大多数数据问题。3. 用 YOLOv8 训练楼梯检测从环境准备到出模型标签确认干净之后下一步就是配环境、写 yaml、开训。1043张的数据集规模不大训练不需要多豪华的显卡一块 8GB 显存的 GPU 就能跑得动。3.1 安装 ultralytics 并配置 data.yaml训练首选 YOLOv8 的官方实现也就是 ultralytics 这个包。安装很简单一行命令pip install ultralytics yolo version第二条命令能打印版本号顺便验证安装是否成功。如果yolo命令找不到多半是 Python 脚本目录没进 PATH用python -m ultralytics代替即可。官方包第一次跑训练时会自动下载对应的预训练权重比如 yolov8n.pt不需要手动去翻网页找下载链接它会缓存到本地目录后续重复使用。然后配置数据描述文件假设压缩包解压到了/home/user/stairs_dataset下path: /home/user/stairs_dataset train: train.txt val: val.txt nc: 1 names: 0: stairpath是数据集根目录的绝对路径train和val可以写成目录路径、具体图片列表或者文本文件路径。这里直接使用压缩包自带的train.txt和val.txt如果你的包里没有这两个文件可以用下面的 Python 脚本按 9:1 划分import random from pathlib import Path image_dir Path(images) imgs sorted(image_dir.glob(*.jpg)) random.seed(42) random.shuffle(imgs) val_num int(len(imgs) * 0.1) # 1043 张取 104 张做验证 val_imgs imgs[:val_num] train_imgs imgs[val_num:] def write_list(path, imgs): with open(path, w, encodingutf-8) as f: for img in imgs: f.write(str(img.resolve()) \n) write_list(train.txt, train_imgs) write_list(val.txt, val_imgs) print(f训练集 {len(train_imgs)} 张验证集 {len(val_imgs)} 张)这里固定random.seed(42)很重要它保证每次运行划分结果一致复现实验时不会因为数据分布变化导致指标对不上。3.2 训练命令与第一批参数建议环境和 yaml 都就绪后训练命令很简单yolo detect train \ datastairs.yaml \ modelyolov8n.pt \ epochs150 \ imgsz640 \ batch16 \ patience30 \ cacheTrue \ projectruns/stairs \ namebaseline \ seed42逐段说下参数含义。modelyolov8n.pt用的是 nano 版本预训练权重1043 张的小数据集不要一上来就用 yolov8x容量太大必过拟合nano 模型训练速度快、显存占用小精度在这个量级的数据集上够用。imgsz640是 YOLOv8 的默认输入尺寸楼梯这种中大型目标不用调大。batch16在 8GB 显存下比较稳妥如果爆显存就降到 8。patience30表示连续 30 轮验证集指标没有改善就自动早停小数据集有早停能省大量时间防止过拟合后白跑几十轮。cacheTrue会把图片提前加载进内存减少 IO 等待。关键参数汇总如下方便后面调参对照参数建议值说明modelyolov8n.pt小数据量首选 nano省显存且不易过拟合imgsz640YOLOv8 默认值楼梯属于中大型目标batch168GB 显存安全带OOM 就降到 8epochs150配合早停不必死等满轮patience30连续 30 轮无提升即停止cacheTrue1043 张全量载入内存几百 MB 级别seed42固定随机种子保证复现训练过程中终端会实时打印box_loss、cls_loss、mAP50等指标正常趋势是 loss 逐步下降、mAP 逐步上升到 100 轮左右曲线趋于平缓。如果 loss 从第一轮就开始震荡且不收敛多半是数据有问题回到第 2 章的校验脚本再扫一遍。3.3 训练日志里该盯哪三个文件训练结束后runs/stairs/baseline/目录下会生成一堆文件新手容易看花眼其实只需要盯三个。第一个是results.png它把训练损失、验证损失、精确率、召回率、mAP 曲线画在一张图上。重点关注验证集那几条曲线训练集 loss 往零走是正常的验证集 loss 如果中途拐头向上说明开始过拟合了此时 best.pt 停在拐点附近早停机制也会在这里触发。第二个是confusion_matrix.png这个小图直接反映了模型把楼梯错认成什么。对单类别检测来说最理想的情况是主对角线颜色最深、其他格子接近黑色。如果背景那一行有亮色块说明存在漏检或误检。第三个是weights/目录下的best.pt和last.pt。best.pt是验证集指标最优的那一版权重部署用这个last.pt是最后一轮的权重一般只在你想继续训练的时候用。后续推理、导出和验证都以best.pt为准。从数据校验到模型训练到这里已经能拿到一个像样的权重文件。但训练过程很少一帆风顺下一步讲讲我在楼梯数据集上真实踩过的坑。4. 楼梯数据集训练避坑5 条真实踩坑记录这部分写的每一条都是我在类似数据集上真实遇到过的按“现象 → 原因 → 解决”展开把血泪经验一次说清。4.1 类别 ID 错位模型学了一圈全预测成背景现象训练跑了 80 轮loss 降得很漂亮mAP50 却一直在 0.05 附近打转。拿训练集里的一张图片手动推理模型什么都框不出来偶尔框出来一个区域置信度也不到 0.3。原因data.yaml 里的names顺序和 txt 文件里的第一列对不上。比如 classes.txt 把stair排在第二行ID 应该是 1但 labels 里的 txt 第一列写的全是 0模型始终在用“类别 0 背景/其他”的语义在学习楼梯越学越乱。这种错位往往发生在数据集被二次打包、有人重新生成过 classes.txt 的时候。解决统一以标签 txt 的实际第一列为准反向修正 data.yaml 的 names 顺序或者批量重写 txt 第一列。最稳妥的办法是写脚本统计所有 txt 里出现过的类别 ID 集合再和 classes.txt 逐行比对。万一你用的是 labelImg 这类标注工具还需要注意它保存的类名顺序是首次创建项目的顺序后面删过类别会把 ID 弄乱重新导出时务必复查一次。4.2 坐标越界与零面积框loss 变成 NaN 的元凶现象训练到第 7 轮终端突然打出loss: nan进度条里的数据全部变成 NaNtrain 过程当场中断。重训一次在第 3 轮复现位置都不同但一定会出现。原因某些标签的 bbox 坐标出界比如xmax 图像宽度或者某个框的xmax xmin。归一化后出现大于 1 的宽高值IoU 计算时 log 函数拿到非法输入loss 直接 NaN。这种现象在自动标注生成的数据集里特别常见人工标注反而少见。解决用第 2 章的校验脚本全量扫描 labels 目录把所有越界、零面积的行先打印出来再决定是裁剪修正还是删掉该框。我的习惯是先跑检查脚本再训练而不是等训练报错再去排查。检查脚本输出为空才开训这是硬性纪律。顺带提醒cacheTrue时图像缓存读的是原图尺寸如果 train.txt 里混了几张非 RGB 或尺寸异常的图也可能诱发 NaN这类问题可以从 PIL 读图的报错信息里反查是哪张图。4.3 楼梯语义不统一同一类目标两种标注习惯现象模型 mAP50 能到 0.7但实际拍一段楼梯场景的视频检测框忽大忽小有时框住整段楼梯有时只框住其中三级台阶还有时把扶手也算进去了。原因数据集的标注人员在留意什么做“楼梯”这件事上没统一。一些人习惯框整个楼梯洞口的外接矩形另一些人只框台阶本体。目标是同一个 class框的语义却不同模型很难学到稳定的边界精确率被无效拉低。解决开训前先抽 20 张图人工过一遍标签如果发现标注语义漂移需要先定标注规范再修正数据。我常用的规范是“框住一段连续台阶的最小外接矩形包含台阶面和踢面不包扶手、不包楼梯洞口以外的墙面螺旋楼梯框整体轮廓扶梯只框梯级段不框水平通道”。定好规范后用脚本批量统计每个框的宽高比分布也能辅助发现离群标注——正常楼梯框宽度占比通常在某一个区间偏离太多的框值得人工复核。4.4 验证集划分不当mAP 波动大早停形同虚设现象同一份数据、同一个模型跑两次得到的 mAP50 分别是 0.72 和 0.58差距大得离谱。best.pt 的保存轮次也从第 50 轮变到第 90 轮实验结果没法复现。原因数据划分时没有固定随机种子或者验证集太小。楼梯数据集如果按 8:2 划分训练集 835 张、验证集 208 张这个比例本身没问题但如果只按 9:1 切验证集就只剩 104 张分布稍有偏斜指标就剧烈抖动。另一个隐蔽问题是连续帧很多楼梯数据集是从视频里抽帧的如果不按视频来源分组而是直接随机切分同一个楼梯的连续几帧可能既出现在训练集又出现在验证集导致验证指标虚高。解决固定seed42是底线更好的做法是按来源分组划分。压缩包里如果有视频 ID 或采集时间信息优先按片段分组没有的话先按文件名前缀聚类再划分保证同一个楼梯序列的图像不进两个集合。验证集大小控制在 100 张以上比较稳1043 张的 10% 正好是 104 张建议不要再少了。4.5 小显存机器开 cacheTrue训练还没开始就 OOM现象训练命令敲下去第一行日志还没完整打印程序直接退掉报 CUDA out of memory 或 Python MemoryError。检查nvidia-smi发现显存根本没被占用内存反倒吃满了。原因这个锅不在模型在cacheTrue。YOLOv8 的 cache 会把预处理后的图片批量缓存1043 张 640 分辨率的图片全量载入内存开销好几个 GB配上 16GB 内存的机器、再叠加载入 pre-trained 权重直接顶爆。解决显存小不代表内存一定大遇到 OOM把 cache 关掉或换成磁盘缓存。cacheFalse时每轮 epoch 都重新读盘1043 张图的体量训练速度损失不大如果还想快一点用cachedisk缓存写到本地临时目录速度和内存占用取中间值。这条经验也可以反过来用如果你的机器内存充裕直接开cacheTrue能明显缩短每轮迭代时间小数据集收益尤其明显。5. 验证与复用楼梯检测模型怎么才算真正能用训练完成不代表模型能用指标漂亮也不代表现场不漏检。最后一章说两条必须做的验证以及后续怎么把模型往实际项目里推。5.1 混淆矩阵与 PR 曲线怎么读打开confusion_matrix.png先看混淆矩阵的总和为什么不是 100%。YOLO 的混淆矩阵是按行归一化的每一行代表一个真实类别格子里是这个真实类别的样本被预测到各目标类别的比例所以每一行单独加起来是 100%。多个行之间不能横向相加凑 100这是很多新手看这张图时的困惑点。对单类别楼梯模型重点看两格真实类别stair这一行对stair的命中比例以及真实类别background这一行对stair的比例。前者低说明漏检严重后者高说明误检严重。检查完静态图再到真实视频上跑一段推理做冒烟测试这一步不能省yolo predict modelruns/stairs/baseline/weights/best.pt sourcestairs_test.mp4 conf0.25用一段没进过训练集的楼梯视频做端到端验证看看最终效果是不是你想要的框。conf 阈值默认是 0.25如果现场误检多把 conf 提到 0.4 到 0.5楼梯这类目标是静态大目标阈值调高不会伤召回。5.2 导出 ONNX 做边缘部署以及下一步可以怎么扩验证通过后把模型导出成 ONNX 格式yolo export modelruns/stairs/baseline/weights/best.pt formatonnx imgsz640导出后得到一个几十 MB 的.onnx文件可以用 ONNX Runtime 或 TensorRT 跑边缘设备搭机器人嵌入式部署时不需要在设备上装完整 PyTorch 环境。做楼宇导航时有一个实用技巧模型输出后别直接信单帧结果楼梯检测最常见的就是灯光反射或栏杆阴影造成的单帧误检加一个连续 5 帧投票去抖检测稳定性会明显提升这是纯视觉做楼梯可通行性判断的常见做法。如果后面想扩展可以把楼梯再按场景细分——室内楼梯、室外台阶、扶梯、螺旋楼梯各自作为一个类别重新标注模型能从单一“stair”学出更丰富的语义也可以用开放词汇检测的思路让模型配合语言描述做“可通行的楼梯口”判断而不只是输出一个框。数据量不够时我一般会优先买一两个相关的楼梯场景数据做融合而不是死磕数据增强。这些年我养成的一个习惯是拿到任何数据集第一件事不是开训而是先花半小时把标签合法性、类别 ID 映射、验证集划分来源这三件事过一遍。这个习惯帮我躲过了无数次半夜看 loss 跳到 NaN 的尴尬。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。