简介婴儿车检测数据集以VOCYOLO双格式发布内含1073张真实场景图片及一一对应的标注文件面向计算机视觉目标检测方向的开发者与算法工程师可支撑婴儿车、行人、行李箱、轮椅等多类别检测模型的训练与精度评估。资源包共2000个文件核心为1073个xml标注文件和927个txt标注文件xml遵循Pascal VOC规范txt为YOLO格式坐标两者与jpg图片同名对应无需格式转换即可接入主流训练框架类别覆盖bicycle、human、stroller、suitcase、wheelchair五个目标总标注框数1606其中stroller框数1169、human框数433样本分布清晰便于针对性地做数据增强或类别均衡。所有标注均由labelImg工具绘制矩形框完成不含分割路径压缩包体积58.43MB下载后直接解压即可使用。已有263人学习下载适合需要快速获取高质量婴儿车检测训练集的开发者尤其适用于模型调优与算法对比实验。1. 婴儿车检测数据集VOCYOLO 双格式1073 张图能做什么做行人检测项目时最容易被忽略、又真实存在的需求是检测婴儿车stroller和轮椅这类“非标准行人目标”。医院、商场、交通路口做人流统计或安全巡检时光把人框出来不够还得区分步行的人、推婴儿车的人、坐轮椅的人这直接关系到无障碍通道占用判断和客流结构分析。这份婴儿车检测数据集共 1073 张 JPG 图片同时给出 Pascal VOC 格式 XML 和 YOLO 格式 TXT 两套标注标注类别 5 个总框数 1606其中 stroller 框数多达 1169 个明显是一个以婴儿车为主体、行人作为上下文的小型专用数据集。适合两类人一是想用 YOLOv5/YOLOv8 训练自己的检测模型、但缺标注数据的开发者二是正在做人流统计、商场或医院场景目标检测需要快速跑通 baseline 验证思路的从业者。它解决的核心问题是省去从零标注的时间拿到手就能开始训练。2. 数据集结构与标注格式双格式标注的目录组织和数据分布2.1 解压后的目录组织JPG、XML、TXT 一一对应拿到压缩包后7-Zip 解压出来会看到 JPG 图片、VOC 格式 XML 文件和 YOLO 格式 TXT 文件三类资源数量各 1073 个三者通过文件名一一对应。比如项目中出现的firc_babycar_128.txt、firc_babycar_318.txt、firc_babycar_621.txt这类命名编号表示来源图片的序号同名的.jpg、.xml、.txt就是同一个样本的三份表达。用tree命令看一下典型结构babycar_dataset/ ├── images/ │ ├── firc_babycar_128.jpg │ ├── firc_babycar_318.jpg │ └── ... ├── annotations/ │ ├── firc_babycar_128.xml │ ├── firc_babycar_318.xml │ └── ... └── labels/ ├── firc_babycar_128.txt ├── firc_babycar_318.txt └── ...提示实际解压后的顶层目录名可能不带images/、annotations/、labels/这三层更常见的是所有文件平铺放在同一目录里。使用前先ls看一眼再决定训练脚本里路径怎么指。文件名前缀firc_babycar是固定的图片和标注共享同一前缀这是对齐的关键。YOLO 训练时要求images和labels目录平行放置且图片路径里的images换成labels就是标注路径。如果文件是平铺的我的习惯是先建好这套目录结构再移动文件而不是在 YAML 里写一堆自定义路径后面排错会省很多事。2.2 类别分布与长尾问题1169 个 stroller 框意味着什么这份数据集的标注类别是 5 个bicycle自行车、human行人、stroller婴儿车、suitcase行李箱、wheelchair轮椅。整体框数分布如下类别框数占比按总框数 1606stroller116972.8%human43327.0%suitcase20.12%bicycle10.06%wheelchair10.06%这个分布非常典型stroller和human是主体两者合计占总框数的 99.8% 以上而bicycle、suitcase、wheelchair各自只有 1 到 2 个框属于极端长尾。这意味着直接拿去训练模型大概率只在 stroller 和 human 两类上有可用精度其余三类基本学不到有效特征——不是标注质量差而是样本数量根本不够。这点在拿到数据集时就要有心理预期后面第 5 章会专门讲怎么处理。另外每张图平均框数约 1.5 个1606 / 1073说明大多数图片是单个目标为主少量图片同时出现行人和婴儿车。这类样本结构对检测器的上下文语义学习是有帮助的——模型能学到“推婴儿车的人”这种组合特征而不是把 stroller 当作孤立的物体。2.3 YOLO 格式 TXT 的存储方式每行一个目标YOLO 的 TXT 标注不是给人看的是给训练器吃的。每行对应一个目标格式固定为class_id x_center y_center width height其中坐标全部归一化到 0 到 1 之间。以firc_babycar_128.txt为例打开后类似这样1 0.487500 0.361111 0.275000 0.583333 2 0.765625 0.547222 0.168750 0.450000这里第一列的 1 和 2 是类别 ID对应关系取决于命名时的classes.txt顺序。按字母序排列的话0bicycle, 1human, 2stroller, 3suitcase, 4wheelchair那上面的第一行就是 human第二行是 stroller。但我必须强调这个 ID 顺序不是数据集官方写死的训练前要打开项目自带的类别文件确认一遍。注意YOLO 的归一化坐标是相对整张图宽高的比例值不是像素值。x_center和width是除以图片宽度后的结果y_center和height是除以图片高度后的结果。手工检查时如果发现某个值大于 1说明标注框超出图像边界需要定位原始 XML 排查。3. VOC 格式 XML 与 YOLO 格式转换字段解析和坐标换算脚本3.1 XML 标注里的关键字段从 filename 到 bndboxVOC 格式的 XML 是 labelImg 的默认输出格式信息完整但冗余。每个文件包含图片名、来源、尺寸、目标列表等信息。打开firc_babycar_318.xml核心结构是这样annotation folderimages/folder filenamefirc_babycar_318.jpg/filename source databaseUnknown/database /source size width640/width height480/height depth3/depth /size object namestroller/name bndbox xmin102/xmin ymin85/ymin xmax301/xmax ymax365/ymax /bndbox /object object namehuman/name bndbox xmin320/xmin ymin90/ymin xmax412/xmax ymax368/ymax /bndbox /object /annotationsize里的width和height是图片的真实尺寸YOLO 坐标转换时必须要用object可以出现多个每个代表一个被标注目标name是类别名bndbox里是矩形框的左上角(xmin, ymin)和右下角(xmax, ymax)像素坐标。labelImg 自动生成的 XML 里 name 都是小写这个数据集的类别名也全部是小写训练时注意别因为大小写不一致导致类别对不上。用 Python 解析 XML 并提取目标信息常见做法是直接用xml.etree.ElementTreeimport xml.etree.ElementTree as ET def parse_voc_xml(xml_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) objects [] for obj in root.iter(object): name obj.find(name).text bndbox obj.find(bndbox) xmin int(bndbox.find(xmin).text) ymin int(bndbox.find(ymin).text) xmax int(bndbox.find(xmax).text) ymax int(bndbox.find(ymax).text) objects.append({name: name, bbox: (xmin, ymin, xmax, ymax)}) return img_w, img_h, objects这段代码的目的是把 XML 中的图片尺寸和所有目标的类别、边框信息读出来。img_w和img_h是后续归一化的分母bndbox是训练时真正用到的像素坐标。如果你只是用这份数据集做训练而不改标注其实不用自己解析 XML但如果你要清洗数据、筛选特定类别的图片或者把标注迁移到别的框架这段代码就是基础工具。3.2 VOC 坐标转 YOLO 格式归一化计算和 ID 映射VOC 的(xmin, ymin, xmax, ymax)是绝对值YOLO 需要的是归一化后的中心点和宽高换算关系很简单x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h转换成代码就是def voc_to_yolo(xml_path, class_names, out_txt_path): img_w, img_h, objects parse_voc_xml(xml_path) lines [] for obj in objects: if obj[name] not in class_names: continue # 跳过不在类别列表里的目标 class_id class_names.index(obj[name]) xmin, ymin, xmax, ymax obj[bbox] x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines))关键参数就两个class_names列表的顺序直接决定输出的类别 ID顺序一变整个训练语义就乱了x_center等四个值输出 6 位小数精度足够模型训练使用。转换完之后建议把 TXT 里的坐标再转回像素坐标画框验证一遍确认没有把xmax和ymax写成宽高——这是我自己踩过最多的坑VOC 的bndbox是“两个点”YOLO 是“中心点和宽高”概念转换出错时画出来的框全是斜的或反向的。3.3 类别对照表训练前必须核对的一步这份数据集既然同时提供了 XML 和 TXT就说明两者可以互相对照检查。类别 ID 的映射规则取决于标注时classes.txt的顺序拿到数据集后第一件事就是确认这个文件里写了什么。常见做法是手工建一个classes.txtbicycle human stroller suitcase wheelchair如果按这个顺序那么 YOLO 标注中0对应 bicycle、1对应 human、2对应 stroller、3对应 suitcase、4对应 wheelchair。用脚本把 XML 里的类别名批量读出来和 TXT 里的 ID 对照一遍能快速发现是不是有顺序错位import glob xml_files sorted(glob.glob(annotations/*.xml)) class_names [bicycle, human, stroller, suitcase, wheelchair] name_to_id {name: i for i, name in enumerate(class_names)} for xml_file in xml_files: _, _, objects parse_voc_xml(xml_file) txt_file xml_file.replace(annotations, labels).replace(.xml, .txt) with open(txt_file) as f: yolo_lines f.read().strip().split(\n) if f.read() else [] # 对比逻辑XML 里每个 object 的类别 ID 应能在 TXT 中找到对应行 print(xml_file, len(objects), len(yolo_lines))这类脚本的价值在于把“人眼检查”变成“程序检查”。如果某个 XML 有 2 个目标但对应 TXT 只有 1 行或者 XML 里的类别在class_names中找不到都会在这一步暴露出来。数据集本身标注质量是可信的但解压、移动、改名过程中出现的文件缺失和错位靠的就是这种批处理脚本去兜底。4. 把数据集跑进 YOLOv8 训练数据划分、YAML 配置和启动命令4.1 训练集验证集划分随机抽样时注意类别均衡YOLOv8 不像老版本 YOLO 那样要求 train.txt / val.txt 文件列表它只需要目录结构规范训练时按图片路径自动找对应标注。划分数据的核心诉求是验证集里必须覆盖到 stroller 和 human 两类目标否则验证指标会失真。用一个简单的随机划分脚本import os import random import shutil random.seed(42) images sorted(os.listdir(images)) random.shuffle(images) val_ratio 0.2 val_count int(len(images) * val_ratio) val_images images[:val_count] train_images images[val_count:] os.makedirs(yolo_dataset/images/train, exist_okTrue) os.makedirs(yolo_dataset/images/val, exist_okTrue) os.makedirs(yolo_dataset/labels/train, exist_okTrue) os.makedirs(yolo_dataset/labels/val, exist_okTrue) for img in train_images: shutil.copy(fimages/{img}, yolo_dataset/images/train/) label img.replace(.jpg, .txt) shutil.copy(flabels/{label}, yolo_dataset/labels/train/) for img in val_images: shutil.copy(fimages/{img}, yolo_dataset/images/val/) label img.replace(.jpg, .txt) shutil.copy(flabels/{label}, yolo_dataset/labels/val/) print(ftrain: {len(train_images)}, val: {len(val_images)})这里用的随机种子 42 是为了复现换别的种子结果会变。val_ratio 0.2意味着约 215 张图进验证集对 1073 张的规模来说比例合理。有一点需要提醒随机划分可能把某个仅有 1 个框的稀有类别全部划进训练集或验证集导致验证时该类别 AP 无法计算。如果你对三个稀有类别还有执念建议做分层抽样——先按“是否包含稀有类别”分组再在组内按比例划分。但这种小样本类别分层抽样的意义也不大更实际的做法是第 5 章要讲的处理策略。4.2 编写 data.yaml路径、训练验证目录和类别名YOLOv8 的数据配置是个 YAML 文件告诉训练器去哪里找图片、标注有哪些类别。针对这个数据集典型的配置如下path: /path/to/babycar_dataset # 数据集根目录改成你自己的绝对路径 train: images/train val: images/val names: 0: bicycle 1: human 2: stroller 3: suitcase 4: wheelchairpath字段是根路径train和val是相对path的图片目录训练器会把images/train中的路径替换为labels/train来找标注文件。如果你的目录结构是images/和labels/平级这就能直接用如果文件名前缀不是firc_babycar而是被改名了只要图片名和标注名一致就行。注意YAML 里的names顺序必须和标注 TXT 里的类别 ID 一致。如果标注时是按字母序生成的classes.txt那 YAML 里也要按字母序写。这是 YOLO 系列最容易翻车的地方——训练不报错但推理时类别标签全对不上。另外path建议用绝对路径。相对路径在命令行执行和脚本执行时的工作目录不一致训练器找不到数据集会报AssertionError: train: No labels found这个报错十有八九是路径写错了而不是数据真的没标注。4.3 启动训练模型规模、batch size、epoch 和训练轮数的选择配置写好就可以训练了。用 YOLOv8 的 CLI 命令启动yolo detect train \ modelyolov8n.pt \ datababycar.yaml \ epochs200 \ imgsz640 \ batch16 \ device0 \ patience50几个关键参数的选择逻辑modelyolov8n.pt用 nano 版本的原因是这个数据集只有 1073 张图参数量太大的模型如 yolov8x更容易过拟合nano 或 small 是更稳的起点。如果你想直接用这个预训练权重做迁移学习YOLO 会自动下载.pt文件到当前目录。imgsz640分辨率。如果原始图片本身是 1280 以上的高清图用 640 训练会丢失小目标细节但多数标注框里 stroller 占画面比例不小640 够用。显存不够可以降到 512 或 416。batch16显存 8GB 的卡跑 nano 模型用 16 没问题如果训练时 OOM降到 8 或 4。实际上 batch size 对最终精度的影响没有学习率大够用就行。epochs200数据集较小200 轮是为了让模型充分收敛。但patience50意味着连续 50 轮验证集指标没有提升就提前停止所以如果数据太简单实际可能 80 到 100 轮就自动停了。device0用第一块 GPU。没有 GPU 的机器改成devicecpu但要做好训练时间翻几十倍的心理准备1073 张图跑 200 轮 CPU 可能要十几个小时。训练结束后结果保存在runs/detect/train/目录下里面有weights/best.pt和weights/last.pt。best.pt是验证集上指标最好的权重推理和部署都用它。4.4 训练日志怎么看loss 曲线和 mAP 指标的变化规律训练过程中的输出会实时打印每个 epoch 的box_loss、cls_loss、dfl_loss和验证集的mAP50、mAP50-95。对这个数据集我的经验是关注三件事第一box_loss和cls_loss在前 20 到 30 轮应该快速下降之后趋于平缓。如果你的 loss 下降很慢可能是学习率太小默认的 lr 通常不用改但可以检查cos_lrTrue的余弦退火是否开启。第二mAP50大概率会比较高因为 stroller 和 human 占了绝大多数样本模型很容易在这两类上达到 0.9 以上。但mAP50-95会明显低于mAP50因为婴儿车有各种角度、遮挡和姿态定位精度要求更高。第三如果训练日志里出现albumentations相关输出说明 YOLOv8 默认开启了随机增强包括 HSV 变换、平移、缩放等这对小数据集是好事。不需要额外配置默认参数即可。5. 避坑指南这五类问题最容易被忽略5.1 稀有类别只有 1 到 2 个框训练后 AP 恒为 0现象训练正常完成验证集上 stroller 和 human 的 mAP 都很高但 bicycle、suitcase、wheelchair 的 AP 始终是 0或者根本不出现在验证结果里。原因这三个类别总共只有 1 到 2 个框且大概率只在训练集或只在验证集里出现。目标检测是数据驱动的方法个位数的样本量连一个 batch 都凑不齐模型无法学习到类别区分特征。这是数据集自身分布决定的不是训练参数的问题。解决最务实的方法是只保留 stroller 和 human 两类做训练把稀有类别从names里去掉对应 TXT 文件里将其过滤掉。如果业务上必须检测轮椅或行李箱那就需要用这三类的更多数据来扩充或者从别的数据集迁移。不要指望靠调参把 1 个框的类别训练出来这是玄学不是技术。5.2 7z 压缩包解压报错“密码正确但一直失败”现象解压.7z文件时提示密码错误但密码明明是对的或者解压到一半提示数据错误文件不完整。原因常见原因有两种——一是用的解压软件是老版本的 WinRAR 或好压对 7z 格式的新压缩算法头支持不完整二是压缩包本身是分卷压缩或使用了-mheon加密文件头普通解压工具读取不了。解决一律换用 7-Zip 官方版解压Linux 下用7za x babycar.7z不要用unzip命令——unzip根本不支持 7z 格式。解压后第一时间用ls | wc -l核对文件数量确保 1073 张 JPG 和对应标注全部到位确认没有解压中断产生的截断文件。5.3 XML 和 TXT 文件数量一致但内容对不上现象JPG、XML、TXT 三种文件的数量都是 1073但训练时提示No labels found或者某张图检测时类别明显标错。原因文件名匹配依赖前缀相同的规则但实际场景中经常出现同一图片有多份 XML比如标注中途保存了多次或者某张图的 XML 被别人手工编辑过导致filename和实际文件名不一致。数量对得上不代表内容对得上。解决写一个脚本遍历所有 JPG检查同名 XML 和 TXT 是否存在再对比 XML 里的filename字段是否和实际文件名一致。重点检查有没有多余空格、大小写差异、中文路径等隐性问题。5.4 图片路径含中文或空格导致训练报错现象yolo detect train命令执行后秒退报错信息指向数据加载失败或者训练中途读取图片时崩掉。原因数据集放在中文目录比如D:\数据集\babycar\或者路径里有空格时YOLOv8 的 data loader 在解析路径时可能出错。Windows 下路径分隔符是反斜杠Linux 下是正斜杠跨平台混用也会出问题。解决把整个数据集目录迁移到纯英文、无空格的路径下比如C:\work\babycar_dataset或/home/user/babycar_dataset。同时检查 XML 里path字段labelImg 会自动写入绝对路径是否指向了旧位置这个字段不影响训练但会影响可视化工具加载。5.5 标注框超出图像边界导致训练警告现象训练日志出现WARNING ⚠️ Invalid labels或坐标值大于 1 的提示某些图片在增强后被自动过滤实际参与训练的图片数量少于预期。原因少量标注框的xmax或ymax接近图片边缘归一化时由于浮点误差出现 1.000001 这类超界值。YOLOv8 对这类坐标会做 clamp 处理但如果超出太多会直接丢弃该标签。解决写个批量检查脚本解析所有 TXT找出坐标值小于 0 或大于 1 的行对应回 XML 修正。这类问题不多但一旦出现会导致某些图片白标了模型在该图上永远学不到东西。import glob for txt_file in glob.glob(labels/*.txt): with open(txt_file) as f: lines f.read().strip().split(\n) for idx, line in enumerate(lines, 1): parts line.split() if len(parts) ! 5: print(f{txt_file} 第{idx}行格式错误: {line}) continue vals [float(v) for v in parts[1:]] if any(v 0 or v 1 for v in vals): print(f{txt_file} 第{idx}行坐标越界: {line})这段脚本把每个标注文件的每一行拆成 5 个字段校验后 4 个坐标是否都在 [0,1] 区间。发现问题后回到对应 XML看看bndbox的四个值是否和图片width、height匹配。通常修正一两个文件就能解决。6. 训练后必须做的一组验证用标注可视化确认数据没有被白标训练不是终点验证标注与预测的一致性才是让模型真正可用的最后一步。我的习惯是拿到best.pt之后先不看验证集指标而是随机抽 20 张训练集图片做标注可视化再抽 20 张没见过的图片做推理可视化对比两者来确认“模型学到的”和“数据标注的”是同一套语义。标注可视化直接用 OpenCV 画框import cv2 img cv2.imread(images/firc_babycar_128.jpg) h, w img.shape[:2] with open(labels/firc_babycar_128.txt) as f: for line in f: parts line.split() cls_id int(parts[0]) x_c, y_c, bw, bh map(float, parts[1:]) x1 int((x_c - bw / 2) * w) y1 int((y_c - bh / 2) * h) x2 int((x_c bw / 2) * w) y2 int((y_c bh / 2) * h) color (0, 255, 0) if cls_id 2 else (0, 0, 255) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, str(cls_id), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1) cv2.imwrite(check_128.jpg, img)其中cls_id 2是 stroller按字母序画绿色框其他类别画红色框可以直接看到类别 ID 是否标反、框是否贴合目标轮廓。如果发现 stroller 的框把半个行人都包进去了说明标注框偏大可以考虑用cacheTrue开启缓存并以iter100的短训练做一次快速调试。推理验证则用训练的模型跑一遍验证集yolo predict modelruns/detect/train/weights/best.pt \ sourceimages/val \ conf0.25 \ saveTrue重点关注两个细节一是conf0.25的阈值是否过滤掉了太多真目标如果预测结果里 stroller 大量缺失把阈值降到 0.1 再跑一次二是保存的预测图里类别标签是否和实际物体吻合比如轮椅被标成了 stroller——这是类别混淆的典型症状说明数据增强时把相似外观的类别搞混了。最后想说的是我最初拿到这份数据集时跳过可视化直接训练跑出来的模型在真实场景里把行李箱识别成婴儿车折腾了很久才发现是标注可视化这步没做。从那以后每拿一套新数据集我都强制走一遍“解析 XML → 画框 → 人眼确认类别顺序”这个流程半小时的功夫能省下后面几天的排错时间。这份数据集的结构算是干净的但干净的数据集也值得你用同样的流程去验证一遍希望帮到你。本文还有配套的精品资源点击获取
