☰
地铁警戒线检测数据集:1125张VOC/YOLO双格式标注与YOLO训练实战
2026/10/13 20:28:31 网站建设 项目流程

简介:本资源为地铁警戒线检测数据集,面向从事目标检测算法训练与验证的开发者、学生及研究人员,可用于地铁站台安全监控场景下的警戒线识别模型开发。数据集同时提供VOC与YOLO两种标注格式,压缩包内包含图片、xml与txt三类文件,共2000个文件,其中1125个xml标注文件、875个txt标签文件,整体约116.34MB,图片清晰且未做数据增强,标签为矩形框,仅含warning_line一类,总框数达1635个,标注准确合理。已有159人学习下载。读者可直接获得1125张jpg原图及对应双格式标注,省去格式转换与清洗成本,快速投入YOLO或VOC流程训练,适合作为地铁警戒线检测的基线数据,也可用于验证模型在单一类别小目标场景下的表现。

1. 地铁警戒线检测数据集:1125 张双格式标注,能不能直接开练?

做轨道交通场景的视觉算法,最头疼的往往不是模型选型,而是找不到一份标注干净、格式齐全、拿来就能进训练管线的数据集。这份「地铁警戒线检测数据集」就是冲着这个痛点来的:1125 张站台实拍图,同时提供 VOC 的 xml 和 YOLO 的 txt 两套标注,标签只有一类warning_line,总框数 1635。换句话说,平均每张图 1.45 个警戒线目标,场景聚焦、类别单一,非常适合做站台安全监控、越线告警这类单类检测任务的起步训练集。它适合谁?刚接手轨道交通视觉项目、需要快速跑通 baseline 的算法工程师,以及想拿真实场景练手目标检测的学生和自学者。不适合谁?想要多类别、复杂遮挡、密集小目标挑战的人——这份数据集的定位就是「干净、聚焦、可复现」,不是刷 SOTA 的竞技场。

2. 拆包先看结构:VOC 与 YOLO 双格式到底怎么对应

拿到压缩包别急着解压进训练脚本,先把目录结构和标注逻辑摸清楚。这份数据集的核心价值在于「一份图、两套标注」,理解它们之间的映射关系,后面转换、校验、训练才不会翻车。

2.1 三个文件夹的职责划分

解压后你会看到三个平级文件夹,这是 VOC 数据集最经典的布局:

文件夹内容数量作用
JPEGImagesjpg 图片1125原始图像,训练与验证的输入
Annotationsxml 文件1125VOC 格式标注,含 bbox 坐标与类别
labelstxt 文件1125YOLO 格式标注,归一化后的类别与坐标

三个文件夹的文件名主干是一一对应的,比如sl_images157.jpg对应sl_images157.xml和sl_images157.txt。项目正文里列出的sl_images157.txt、sl_images139.txt、sl_images490.txt这些,就是 labels 文件夹里的部分样本名。命名规则统一,没有花哨的前缀后缀,这对批量脚本非常友好。

提示:解压后先做一次文件名对齐检查,确认三个文件夹的主干名集合完全一致。任何一边多一个或少一个,都会在训练时变成静默丢样本的坑。

2.2 VOC 的 xml 里有什么

VOC 格式的 xml 是「人类可读、机器可解析」的典型代表。打开任意一个 xml,你会看到<size>记录图像宽高,<object>下记录类别名和<bndbox>的 xmin/ymin/xmax/ymax。这份数据集的类别名固定为warning_line,坐标是绝对像素值。

<annotation> <folder>JPEGImages</folder> <filename>sl_images157.jpg</filename> <size> <width>1920</width> <height>1080</height> <depth>3</depth> </size> <object> <name>warning_line</name> <bndbox> <xmin>412</xmin> <ymin>806</ymin> <xmax>1503</xmax> <ymax>874</ymax> </bndbox> </object> </annotation>

这里的关键参数是<size>里的宽高——YOLO 格式的归一化就靠它。如果 xml 里的宽高和实际图片不一致,转换出来的 txt 坐标会整体偏移,这是最常见的翻车点之一。

2.3 YOLO 的 txt 里有什么

YOLO 格式的 txt 每行一个目标,格式是类别索引 中心x 中心y 宽 高,全部归一化到 0~1。这份数据集只有一个类别,所以类别索引恒为 0。

0 0.498437 0.777778 0.568229 0.062963

换算逻辑是:中心 x = (xmin + xmax) / 2 / 图像宽,宽 = (xmax - xmin) / 图像宽,y 方向同理。你可以用下面这段脚本快速验证 xml 和 txt 是否自洽:

import os import xml.etree.ElementTree as ET def parse_voc(xml_path): tree = ET.parse(xml_path) root = tree.getroot() size = root.find('size') w = int(size.find('width').text) h = int(size.find('height').text) boxes = [] for obj in root.iter('object'): name = obj.find('name').text bnd = obj.find('bndbox') xmin = float(bnd.find('xmin').text) ymin = float(bnd.find('ymin').text) xmax = float(bnd.find('xmax').text) ymax = float(bnd.find('ymax').text) # 转成 YOLO 归一化格式 cx = (xmin + xmax) / 2.0 / w cy = (ymin + ymax) / 2.0 / h bw = (xmax - xmin) / w bh = (ymax - ymin) / h boxes.append((name, cx, cy, bw, bh)) return w, h, boxes # 抽查一个样本,和 labels 里的 txt 对比 w, h, boxes = parse_voc('Annotations/sl_images157.xml') print(f'图像尺寸: {w}x{h}') for b in boxes: print(f'{b[0]} {b[1]:.6f} {b[2]:.6f} {b[3]:.6f} {b[4]:.6f}')

这段脚本的作用是把 xml 重新算一遍 YOLO 坐标,输出结果应该和 labels 文件夹里对应的 txt 行几乎一致(浮点精度范围内)。如果差得离谱,说明 xml 的 size 和真实图片对不上,或者标注本身有问题。参数上唯一需要注意的是float()转换——有些标注工具会写出带空格的文本,稳妥做法是加.strip()。

3. 从零跑通训练:YOLO 格式的目录组织与配置

格式看懂了,接下来就是把它喂给训练框架。这份数据集已经自带 YOLO txt,省掉了转换步骤,但目录组织仍然要自己动手。下面以常见的 YOLO 系列训练管线为例,把路径、配置文件、划分脚本一次讲清。

3.1 组织成 YOLO 训练目录

YOLO 训练要求 images 和 labels 分开放,且路径结构镜像对应。推荐这样组织:

dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml

把 JPEGImages 里的 jpg 按比例复制到 images/train 和 images/val,labels 里的 txt 同名复制到对应 labels 子目录。注意:labels 目录下不能有 images 以外的文件,否则训练时会报「找不到标签」或直接跳过。

import os import shutil import random random.seed(42) # 固定随机种子,保证划分可复现 src_img = 'JPEGImages' src_lbl = 'labels' dst_root = 'dataset' names = [os.path.splitext(f)[0] for f in os.listdir(src_img) if f.endswith('.jpg')] random.shuffle(names) split = int(len(names) * 0.8) # 8:2 划分 train_names = names[:split] val_names = names[split:] for subset, subset_names in [('train', train_names), ('val', val_names)]: os.makedirs(f'{dst_root}/images/{subset}', exist_ok=True) os.makedirs(f'{dst_root}/labels/{subset}', exist_ok=True) for n in subset_names: shutil.copy(f'{src_img}/{n}.jpg', f'{dst_root}/images/{subset}/{n}.jpg') shutil.copy(f'{src_lbl}/{n}.txt', f'{dst_root}/labels/{subset}/{n}.txt') print(f'train: {len(train_names)}, val: {len(val_names)}')

逻辑说明:先收集所有图片主干名,用固定种子打乱后按 8:2 切分。random.seed(42)是血泪经验——不固定种子,每次划分不同,实验就没法对比。参数上split控制训练集比例,1125 张按 8:2 大约是 900 训练、225 验证,对小数据集来说验证集够用。如果你的场景对召回更敏感,可以调到 9:1,但验证集少于 100 张时指标波动会很大。

3.2 data.yaml 怎么写

YOLO 的 data.yaml 是训练入口配置,这份数据集只有一个类别,写起来很干净:

path: ./dataset train: images/train val: images/val nc: 1 names: 0: warning_line

nc是类别数,必须和 names 的条目数一致。names的键是类别索引,值要和 txt 里的索引对应——这份数据集 txt 里全是 0,所以 names 只写 0 即可。常见错误是把nc写成 2 或者 names 里塞了背景类,YOLO 不需要显式背景类,写了反而会导致索引错位。

3.3 启动训练与关键参数

配置就绪后,一条命令就能开跑:

yolo detect train \ data=dataset/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ patience=20 \ project=runs/warning_line \ name=baseline

参数逐个说:model选 nano 版是因为数据集只有 1125 张、单类别,大模型容易过拟合;imgsz=640是通用起点,如果你的警戒线在图中占比很小,可以提到 960 或 1280,但显存和速度要权衡;batch=16在 8G 显存上比较稳,爆显存就降到 8;patience=20表示 20 轮无提升就早停,小数据集上能省不少时间。训练过程中重点看mAP50和mAP50-95,单类别任务里 mAP50 上 0.9 通常不难,难的是 mAP50-95,它反映框的贴合精度。

注意:第一次训练前先用 10 个 epoch 跑个冒烟测试,确认 loss 在下降、验证集有预测输出。直接上 100 epoch 发现配置错了,浪费的是自己的时间。

4. 避坑与排查:标注、路径、指标里的五个真实翻车点

数据集再干净,落地时也有一堆细节能把人绊住。下面这五条是我在实际项目里反复遇到的,按「现象 → 原因 → 解决」整理,照着排查能省掉大量玄学调试。

4.1 训练 loss 正常但 mAP 恒为 0

现象:训练日志里 box_loss、cls_loss 都在降,但验证集 mAP 一直是 0,预测框一个都不输出。

原因:最常见的是 data.yaml 里names的索引和 txt 里的类别索引对不上。比如 txt 写的是 0,names 却从 1 开始编号,模型学到的类别和评估时对不上。其次是 val 路径写错,验证时加载的是空目录。

解决:先用os.listdir确认 val 目录下图片数量不为 0;再抽查一个 txt 的首列,确认全是 0;最后核对 data.yaml 的 names 键值。三步走完基本能定位。

4.2 图片和标签数量对不上

现象:训练日志提示N images, M labels,N 和 M 不相等,或者某些图片被跳过。

原因:labels 目录里混入了非 txt 文件(比如.DS_Store、Thumbs.db),或者图片和标签的主干名有细微差异(多了空格、大小写不一致)。

解决:跑一段校验脚本,把 images 和 labels 的主干名集合做差集:

import os img_names = {os.path.splitext(f)[0] for f in os.listdir('dataset/images/train')} lbl_names = {os.path.splitext(f)[0] for f in os.listdir('dataset/labels/train')} print('有图无标签:', img_names - lbl_names) print('有标签无图:', lbl_names - img_names)

差集为空才算干净。有图无标签的样本会被当成纯背景,有标签无图的直接报错。

4.3 警戒线框贴边导致坐标越界

现象:转换或训练时提示坐标超出 [0,1] 范围,或者框被裁掉一部分。

原因:警戒线常常横跨整个画面,标注时 xmin 可能为 0、xmax 等于图像宽,归一化后正好是 0 和 1。如果标注工具有 1 像素误差,就会算出 1.0003 这种越界值。

解决:在转换脚本里加一步 clamp:

cx = min(max(cx, 0.0), 1.0) cy = min(max(cy, 0.0), 1.0) bw = min(max(bw, 0.0), 1.0) bh = min(max(bh, 0.0), 1.0)

同时检查 xml 里的 xmax 是否大于 width,大于就说明标注本身有问题,需要回看原图。

4.4 分辨率不一致导致归一化错乱

现象:部分样本的框位置整体偏移,像是被拉伸或压缩过。

原因:xml 里记录的 size 和实际 jpg 的尺寸不一致。有些标注流程会先缩放图片再标注,但 xml 里写的是缩放前的尺寸,或者反过来。

解决:用 PIL 读实际图片尺寸,和 xml 的 size 对比:

from PIL import Image import xml.etree.ElementTree as ET img = Image.open('JPEGImages/sl_images157.jpg') root = ET.parse('Annotations/sl_images157.xml').getroot() size = root.find('size') xml_w, xml_h = int(size.find('width').text), int(size.find('height').text) print(f'实际: {img.size}, xml: ({xml_w}, {xml_h})')

不一致的样本要么重新标注,要么以实际图片尺寸为准重算坐标。这份数据集摘要里标注了「图片清晰、未增强」,理论上尺寸应该一致,但抽查一遍不亏。

4.5 验证集指标虚高

现象:验证集 mAP 很高,但拿真实站台视频一测,漏检严重。

原因:1125 张图如果来自同一段视频的连续帧,相邻帧高度相似,随机划分会让训练集和验证集出现「近重复样本」,验证指标虚高。这是小数据集最隐蔽的坑。

解决:如果图片名带帧号,按帧号区间划分而不是随机划分;或者用感知哈希做去重后再划分。退一步,至少把验证集指标当作参考,真正验收要用独立采集的测试片段。

5. 进阶技巧:用 1635 个框反推标注质量与训练策略

数据集给了 1635 个框、1125 张图,这两个数字本身就藏着信息。平均每张 1.45 个框,说明大部分图只有一条警戒线,少数图有两条。这个分布决定了你的训练策略:不要用针对密集小目标的数据增强(比如 Mosaic 开到很高),否则会把单条长线切得七零八落,反而伤害学习。

我一般会先做一次框的宽高比统计,判断警戒线的形态分布:

import os ratios = [] for f in os.listdir('labels'): with open(f'labels/{f}') as fp: for line in fp: parts = line.strip().split() if len(parts) == 5: bw, bh = float(parts[3]), float(parts[4]) if bh > 0: ratios.append(bw / bh) ratios.sort() print(f'样本数: {len(ratios)}') print(f'宽高比中位数: {ratios[len(ratios)//2]:.2f}') print(f'宽高比 P10: {ratios[int(len(ratios)*0.1)]:.2f}') print(f'宽高比 P90: {ratios[int(len(ratios)*0.9)]:.2f}')

如果中位数远大于 1,说明警戒线普遍是横向长条,那么 anchor 或模型的正样本匹配策略要偏向宽扁框。YOLO 系列是 anchor-free 的,重点就落在数据增强上:可以关掉 Mosaic 的最后 10 个 epoch,让模型在真实长条分布上收敛。

另一个技巧是用框数分布做分层验证。把「单框图」和「多框图」分开统计指标,如果多框图的召回明显低,说明模型对同图多目标的分辨能力不足,可以考虑提高 imgsz 或增加多框样本的采样权重。

还有一个容易被忽略的点:警戒线是语义上高度依赖上下文的类别——它总是出现在站台边缘、黄线位置。如果你的部署场景和训练场景的拍摄角度差异大,光靠这份数据集可能不够,建议用少量目标场景图片做微调,哪怕只有几十张,也能显著提升实际表现。从那以后我每次拿到单类别数据集,都会先跑一遍框分布统计和分层验证,再决定增强策略和 imgsz,而不是上来就套默认配置。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询