简介本资源为轮椅检测数据集面向计算机视觉方向的目标检测学习者、算法工程师及需要轮椅识别场景落地的开发者可用于训练与验证单类别检测模型。数据集同时提供Pascal VOC与YOLO两种标注格式包含jpg图片及一一对应的xml、txt标注文件标注工具为labelImg采用矩形框标注类别仅wheelchair一类共15816个标注框适合直接接入YOLO系列或VOC流程进行训练与评估。压缩包为7z格式共2000个文件以1999个xml标注文件和1个说明txt为主整体约925.42MB图片与标注数量均为13826规模较为充足。需要留意的是数据集中约四分之三的图片由增广方式扩充得到使用前建议结合示例图核对样本分布避免影响模型泛化评估。目前已有292人学习下载可作为轮椅检测任务的基础数据来源帮助读者快速搭建训练集、验证标注质量并开展模型对比实验。1. 轮椅检测数据集 VOCYOLO 格式 13826 张单类别这套数据到底能干什么如果你正在做无障碍通道占用告警、医院走廊轮椅识别或者智慧养老场景里的跌倒/轮椅联动检测大概率会卡在同一个地方找不到一份标注干净、格式齐全、量级够用的轮椅检测数据集。网上能搜到的要么是几百张的小样本要么只有 VOC 没有 YOLO要么类别混着「轮椅病床拐杖」一起标训出来的模型根本没法单独用。这份 13826 张、单类别、同时给 VOC 和 YOLO 两套格式的轮椅检测数据集解决的正是这个「拿来就能训」的问题。它的定位很明确单类别目标检测标签只有 wheelchair 一类VOC 格式给的是 XML 标注YOLO 格式给的是归一化后的 txt 标注13826 张图覆盖了室内走廊、病房、室外坡道、商场无障碍区等常见场景。适合两类人一类是想快速跑通 YOLO 训练流程、拿一个真实场景数据集练手的新手另一类是做无障碍相关产品、需要一个能直接微调 backbone 的检测基线的工程师。下面从格式转换、训练配置、参数调优到踩坑排查把这条路走一遍。2. VOC 与 YOLO 双格式拆解13826 张图怎么组织、怎么读2.1 两套标注格式的差异与各自适用场景VOC 格式的核心是每张图对应一个 XML 文件标注信息写在object节点里包含类别名name和边界框bndboxxmin、ymin、xmax、ymax 四个绝对像素坐标。这套格式的好处是可读性强、工具链成熟LabelImg、CVAT 都直接支持缺点是解析慢、文件体积大13826 张图就是 13826 个 XML光文件数量在训练时做数据加载就够呛。YOLO 格式则是每张图对应一个 txt每行一条标注格式是class_id x_center y_center width height后四个值都是相对图像宽高的归一化值0~1 之间。单类别的情况下 class_id 恒为 0。这套格式加载快、体积小是 YOLOv5/v8/v11 系列的标准输入。两套格式同时提供实际价值在于你可以用 VOC 做数据审核和可视化XML 肉眼可读用 YOLO 做训练输入。常见做法是先用 VOC 抽查几十张确认标注质量再切到 YOLO 跑训练。2.2 目录结构与文件命名约定拿到压缩包解压后典型结构是两套并列的目录。VOC 侧一般是Annotations/放 XML、JPEGImages/放原图、ImageSets/Main/放 train/val 的 txt 划分文件。YOLO 侧一般是images/放原图、labels/放 txt外加一个classes.txt或data.yaml描述类别。这里有个高频翻车点YOLO 的 images 和 labels 必须同名同层级。比如images/train/001.jpg对应的标签必须是labels/train/001.txt只差一个目录名。很多人解压后把 labels 全平铺在一个目录里训练时找不到标签模型 loss 直接不降还以为是学习率的问题。2.3 用脚本核对图像与标签的一一对应在正式训练前我一般会先跑一个一致性检查脚本把「有图无标签」「有标签无图」「标签为空文件」「坐标越界」这四类问题一次性揪出来。13826 张的量级人工核对不现实脚本几分钟就能跑完。import os from pathlib import Path IMG_DIR Path(dataset/images) LBL_DIR Path(dataset/labels) IMG_EXTS {.jpg, .jpeg, .png, .bmp} def check_pair(img_dir, lbl_dir): imgs {p.stem for p in img_dir.rglob(*) if p.suffix.lower() in IMG_EXTS} lbls {p.stem for p in lbl_dir.rglob(*.txt)} only_img imgs - lbls # 有图无标签 only_lbl lbls - imgs # 有标签无图 empty_lbl, bad_coord [], [] for p in lbl_dir.rglob(*.txt): lines [l.strip() for l in p.read_text().splitlines() if l.strip()] if not lines: empty_lbl.append(p.name) continue for line in lines: parts line.split() if len(parts) ! 5: bad_coord.append((p.name, 字段数不对)) break _, x, y, w, h map(float, parts) # 归一化坐标必须落在 0~1且宽高大于 0 if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): bad_coord.append((p.name, line)) break print(f图像总数: {len(imgs)} 标签总数: {len(lbls)}) print(f有图无标签: {len(only_img)} 有标签无图: {len(only_lbl)}) print(f空标签文件: {len(empty_lbl)} 坐标异常: {len(bad_coord)}) return only_img, only_lbl, empty_lbl, bad_coord check_pair(IMG_DIR, LBL_DIR)这段脚本的逻辑是用文件名主干stem做集合运算快速定位配对缺失再逐行解析 YOLO 标签检查字段数和归一化坐标范围。参数上IMG_EXTS按你实际拿到的图片后缀调整如果数据集里混了.webp或.tif记得加进去否则会被误判成「有标签无图」。跑完如果only_img或only_lbl不为零先别急着训把这几张挑出来看是命名不一致还是真的漏标。3. 从 VOC 转 YOLO转换脚本与四个边界坑3.1 转换的核心逻辑绝对坐标到归一化坐标VOC 的 bndbox 是绝对像素坐标YOLO 要的是归一化中心点加宽高。转换公式是x_center (xmin xmax) / 2 / img_wy_center (ymin ymax) / 2 / img_hwidth (xmax - xmin) / img_wheight (ymax - ymin) / img_h。看着简单但坑全在边界处理上。3.2 可直接复用的转换脚本import xml.etree.ElementTree as ET from pathlib import Path from PIL import Image CLASS_MAP {wheelchair: 0} # 单类别映射到 0 VOC_ANN Path(VOC/Annotations) VOC_IMG Path(VOC/JPEGImages) OUT_LBL Path(yolo/labels) OUT_LBL.mkdir(parentsTrue, exist_okTrue) def convert_one(xml_path): tree ET.parse(xml_path) root tree.getroot() img_name root.find(filename).text img_path VOC_IMG / img_name img_w, img_h Image.open(img_path).size # 用真实图像尺寸别信 XML 里的 size lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in CLASS_MAP: continue box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 边界裁剪防止标注超出图像范围 xmin, xmax max(0, xmin), min(img_w, xmax) ymin, ymax max(0, ymin), min(img_h, ymax) if xmax xmin or ymax ymin: continue # 裁剪后无效框直接丢弃 xc (xmin xmax) / 2 / img_w yc (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{CLASS_MAP[name]} {xc:.6f} {yc:.6f} {w:.6f} {h:.6f}) out_file OUT_LBL / (Path(img_name).stem .txt) out_file.write_text(\n.join(lines)) for xml in VOC_ANN.glob(*.xml): convert_one(xml) print(转换完成)逻辑说明脚本遍历每个 XML读取真实图像尺寸而不是 XML 里size节点写的那个经常和实际图不符对每个 wheelchair 框做边界裁剪后归一化。参数上CLASS_MAP是类别到 id 的映射单类别就写一个:.6f保留六位小数YOLO 官方推荐至少六位位数太少在密集小目标上会有精度损失。3.3 四个必须处理的边界坑第一个坑是坐标越界。VOC 标注里偶尔出现 xmax 大于图像宽度的情况直接归一化会得到大于 1 的值YOLO 训练时会被过滤掉导致某些目标「凭空消失」。脚本里的裁剪逻辑就是防这个。第二个坑是零宽高框。xmin 等于 xmax 的退化框归一化后 width 为 0训练时是无效样本必须丢弃。第三个坑是图像尺寸不一致。13826 张图如果来自多个来源宽高比可能五花八门转换时一定要逐张读真实尺寸不能用一个固定值套。第四个坑是文件名带空格或中文。VOC 的 filename 字段如果含空格Path(img_name).stem处理没问题但有些训练框架读路径时会截断建议转换后统一重命名成纯英文数字。4. 用 YOLOv8 训练单类别轮椅检测配置、参数与验证4.1 data.yaml 怎么写YOLO 训练的第一步是准备 data.yaml它告诉框架去哪找图、有几类、类名叫什么。path: /data/wheelchair # 数据集根目录 train: images/train # 相对 path 的训练图目录 val: images/val nc: 1 # 类别数单类别写 1 names: [wheelchair] # 类别名顺序对应 class_idnc和names必须严格对应单类别就写 1 和[wheelchair]。如果 names 里写了多个但标签里只有 0训练不报错但验证时 mAP 计算会乱。4.2 训练命令与关键参数yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/wheelchair \ nameexp1参数说明modelyolov8n.pt用 nano 版先跑通单类别任务 n 版通常够用显存紧张时优先选它imgsz640是检测任务的通用分辨率轮椅这种中等目标 640 足够如果图里轮椅占比很小可以提到 960batch16按显存调8G 显存跑 640 大概能到 16lr00.01是初始学习率微调预训练模型时这个值合适从头训可以降到 0.001patience20是早停20 轮验证指标不升就停省时间。4.3 训练过程该盯哪几个指标跑起来后重点看三个box_loss应该在前 10 轮快速下降然后趋缓如果一直不降八成是标签路径没对上mAP50是主指标单类别轮椅检测在干净数据上通常能到 0.9 以上如果卡在 0.5 左右检查是不是有大量小目标或遮挡样本cls_loss单类别任务里意义不大接近 0 是正常的。验证阶段用yolo detect val modelruns/wheelchair/exp1/weights/best.pt datadata.yaml重点看混淆矩阵和 PR 曲线。单类别没有类间混淆主要看漏检FN和误检FP的比例漏检多说明召回不够可以降 confidence 阈值或加数据增强。5. 训练轮椅检测模型最容易踩的五个坑坑一loss 不降训练几轮就停。现象是 box_loss 一直在 1.0 以上震荡。原因九成是标签路径不对YOLO 找不到 labels 目录把所有图当成负样本训。解决确认 images 和 labels 目录同级同名用第 2 章的检查脚本先跑一遍配对。坑二mAP 虚高但实际检测全是框。现象是验证 mAP50 到 0.95但拿新图测试满屏都是轮椅框。原因是验证集和训练集来自同一批连续帧高度相似模型过拟合了。解决划分数据集时按场景或视频来源切分别用随机切分保证验证集有独立场景。坑三小目标轮椅检测不到。现象是远处或监控俯拍的小轮椅全部漏检。原因是 640 分辨率下小目标特征太弱。解决把 imgsz 提到 960 或 1280或者用 YOLOv8 的 P2 检测头增加一个高分辨率特征层代价是显存和推理时间上升。坑四标注框偏移检测框总是偏一点。现象是检测框位置系统性偏移。原因是 VOC 转 YOLO 时用了 XML 里的 size 而不是真实图像尺寸两者不一致导致归一化基准错了。解决转换脚本里强制用 PIL 读真实尺寸别信 XML。坑五推理速度慢达不到实时。现象是单张推理几百毫秒。原因是用了大模型或没做导出优化。解决单类别任务用 yolov8n导出 ONNX 或 TensorRT 后推理能压到十几毫秒具体路数取决于你的部署硬件。6. 单类别数据集的进阶玩法从能跑到好用跑通训练只是起点真正决定这套数据集价值的是你能不能把它用出「产品级」的效果。单类别轮椅检测有个天然优势类别少可以把精力全砸在数据质量和后处理上。第一个进阶方向是难例挖掘。先用初版模型在全量数据上推理把 confidence 在 0.3~0.6 之间的样本挑出来人工复核这些就是模型的「模糊地带」。把其中标错的修正、漏标的补上再训一轮mAP 通常能涨 2~5 个点。这个循环做两三轮比盲目加数据有效得多。第二个方向是数据增强的针对性选择。轮椅检测的难点在遮挡和视角变化所以 mosaic、mixup 这类增强有用但要注意单类别下 mosaic 拼接四张图可能把轮椅拼得过于密集反而引入噪声。我一般会把 mosaic 的概率从默认 1.0 降到 0.5配合随机透视变换模拟俯拍和侧拍。第三个方向是导出与部署验证。训练完的 best.pt 直接用于生产太慢导出成 ONNX 或 TensorRT 引擎是常规操作。# 导出 ONNX动态 batch 方便服务端并发 yolo export modelbest.pt formatonnx dynamicTrue opset12 # 导出 TensorRT需要 NVIDIA 环境half 开启 FP16 加速 yolo export modelbest.pt formatengine halfTrue device0导出后一定要做数值对齐验证拿同一批图分别用 pt 和导出模型推理比对框的坐标差异IoU 低于 0.99 就说明导出有精度损失检查 opset 版本和是否开了 half。这一步很多人跳过上线后才发现检测框飘了。最后一个习惯每次训练都固定随机种子seed42把 data.yaml、训练命令、环境版本记在一个train_log.md里。轮椅检测这种单类别任务复现性比什么都重要不然调参调到最后自己都忘了哪版最好。这套数据集的价值不在于 13826 这个数字而在于它给了你一个干净的起点剩下的靠迭代。希望帮到你。本文还有配套的精品资源点击获取