简介一份面向目标检测与YOLO系列模型训练的三轮车专用图像数据集适合入门级与进阶开发者用于行人/车辆识别、物流场景感知等方向的数据准备与模型验证。资源共1679个文件主要包括559张JPG图片、559个Pascal VOC格式的XML标注文件以及配套的YOLO格式TXT标注文件压缩包整体约25.22MB。数据集由labelImg工具手工画框标注标注类别仅“tricycle”一类总计659个真实框定位准确、类别清晰可直接用于YOLOv5、YOLOv8等框架的训练与评估。已有642人学习下载对于需要快速获取规范标注数据、省去自行采集与标注环节的CV学习者来说是一份省时且便于上手的实战资源。1. 三轮车数据集为什么值得手工做559张VOCYOLO能解决什么做目标检测的同行应该都有体会公开数据集里汽车、行人、自行车一抓一大把但三轮车这种“非标目标”反而很难找。共享电单车、快递车、农用三轮车姿态和外形差异极大公开的车辆检测模型拿到真实场景里经常漏检。于是自己攒数据就成了绕不开的路而标题里的这套三轮车数据集走的是最扎实也最费时间的一条路人工用 labellmg 逐张框选同时保留 VOC 和 YOLO 两种格式。559 张听起来不多但手工标注的 559 张往往比自动扒下来的 5000 张噪声数据更可用。VOC 格式方便你随时改标注、看边界YOLO 格式则直接喂给训练脚本。这套组合拳特别适合刚上手 YOLO 训练自己数据集的人先拿它跑通“标注 → 转换 → 训练 → 验证”全流程再决定要不要在这个基础上扩充数据。下面从格式差异讲起把从 labellmg 到模型训练这条链路上的关键步骤和坑一次性说清楚。2. 先搞清楚格式VOC 与 YOLO 标注的差异和手工转换脚本2.1 两种格式在存储和解析上的本质差异VOC 格式源于 PASCAL VOC 竞赛一个图片对应一个 XML 文件里面记录了文件名、图片尺寸width、height、depth以及每个目标的类别和边界框坐标。边界框用 xmin、ymin、xmax、ymax 四个绝对像素值表示坐标原点是图片左上角。这种格式的优点是可读性强修改一个框的位置或类别直接编辑 XML 就行也方便人在标注阶段排查错误。YOLO 格式走的是另一条路每个图片对应一个同名 TXT 文件每一行代表一个目标格式是“类别ID 中心点x 中心点y 宽度 高度”。这里的五个数值全部被归一化到 0~1 区间用的不是像素绝对值而是相对图片宽度和高度的比例。类别 ID 从 0 开始计数具体哪个数字对应哪个类别完全由训练时的 data.yaml 文件决定。这种设计让 YOLO 训练时读取标注特别快不用解析嵌套的 XML每行五个浮点数直接进张量。但代价是肉眼几乎无法直接判断标注对不对一个只有 0.4812 0.5322 0.2154 0.1876 的 TXT 文件不还原成像素你根本不知道框在哪。所以我的习惯是标注阶段全部用 VOC 格式存训练前再做格式转换这样保留了后悔药。正式训练前我会写一个可视化脚本把 YOLO 格式的标注画回图片上确认转换没出错再开工。2.2 用 Python 脚本把 VOC 转成 YOLO坐标系换算与边界检查转换的核心是把“左上角右下角”的绝对坐标换算成“中心点宽高”的归一化坐标。公式不复杂但有几个坑图片尺寸必须从 XML 的 size 节点读取不能自己猜转换后的宽高除以图片宽高后结果必须落在 0 到 1 之间类别名必须手动映射成整数 ID。import os import xml.etree.ElementTree as ET def convert_voc_to_yolo(xml_path, output_dir, class_names): tree ET.parse(xml_path) root tree.getroot() # 图片尺寸必须从 xml 里读不能假设固定值 size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) txt_path os.path.join(output_dir, os.path.splitext( os.path.basename(xml_path))[0] .txt) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_names: continue # 遇到没在类别表里的目标跳过并打印警告 class_id class_names.index(name) 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) # 坐标换算绝对像素 - 归一化中心点 宽高 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h # 裁剪越界值防止训练时报 label out of bounds x_center max(0.0, min(x_center, 1.0)) y_center max(0.0, min(y_center, 1.0)) w max(0.0, min(w, 1.0)) h max(0.0, min(h, 1.0)) lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(txt_path, w) as f: f.write(\n.join(lines))这段脚本的逻辑很直白解析 XML 里的 size 节点拿到真实宽高遍历所有 object 节点提取类别和边框做坐标换算后写入 TXT。参数里 class_names 的列表顺序就是训练时的类别 ID 顺序必须和 data.yaml 保持一致比如 [tricycle] 表示 ID 0 对应三轮车。转换后我会再跑一段检查代码统计有没有 TXT 文件为空、有没有类别 ID 超出范围、有没有文件数量对不上。因为 labellmg 可能漏存、误删这类低级错误往往比模型本身更折磨人。3. 用 labellmg 打 559 张三轮车图工作流与关键设置3.1 labellmg 安装与环境配置labellmg 是目标检测标注里最常用的图形工具PyQt5 界面支持同时输出 VOC 和 YOLO 格式。安装有两种常见做法我推荐在 Anaconda 环境里装因为后面训练 YOLO 大概率也用同一个环境省得来回切换环境配置。首先创建一个干净的 conda 环境然后装依赖和 labellmg 本体conda create -n label python3.8 -y conda activate label pip install pyqt55.15.7 lxml pip install labelImg如果 pip 直接装失败常见原因是 PyQt5 版本和系统图形库不兼容这时候改用系统包管理器装 PyQt5 再跑源码方式。labellmg 的启动命令很简单在终端里输入labelImg回车就会弹窗。打开后的默认界面是英文在 View 菜单里可以切换 Chinese不切换也不影响使用核心快捷键就那么几个。启动后的第一件事是设置自动保存模式。快捷键 CtrlShiftS 打开“自动保存”开关这样每切到下一张图时上一张的标注会自动落盘极大降低忘保存导致标注丢失的概率。另一个必改的设置是默认标注目录否则每次打开图片都要重新选一次输出目录。3.2 三轮车这类细长目标的标注策略三轮车和普通轿车不一样它在外观上存在“车头货斗”的明显分段侧面看尤其长。新手常见的错误是把车头和货斗拆成两个框或者反过来把后面跟着的拖挂也算进去。我的建议是一个目标一辆车整车的几何外接框作为一个标注框原因是你做检测的最终目的是判断“这里有一辆三轮车”而不是拆零件。然后是边界框的贴合度问题。labellmg 里用鼠标拖出的框经常比目标大一圈如果训练数据里所有框都偏大模型学到的就是“宽松的框”推理时定位精度会变差。手动调整时把框的四边贴住车身的最外侧像素轮子下沿要覆盖到车顶篷最高点也要包含进去宁可略紧不要过松。对于被遮挡的三轮车如果遮挡面积超过一半这个目标可以不标如果只被电线杆挡了一小块按可见部分正常标注这对模型学习遮挡鲁棒性有帮助。类别定义上559 张图如果全部只有一类“tricycle”训练会简单很多但如果你在真实场景里还要区分“载人三轮车”和“载货三轮车”那就必须在标注阶段就分开两个类否则后期重新标注的工作量是灾难级的。手工标注特别费时我一般建议第一版只做单类跑通流程后再考虑细分。3.3 标注质量的抽查与修正559 张图全部标注完你会发现人的注意力是会衰减的。标到 200 张以后鼠标框选的精度明显下降偶尔还会漏掉角落里的目标。所以每标完一批我会用随机抽样画框检查的方式做质量抽检把标注结果可视化出来人工过目。import cv2 def draw_yolo_boxes(image_path, label_path, class_names, output_path): img cv2.imread(image_path) h, w img.shape[:2] with open(label_path, r) as f: for line in f.readlines(): parts line.strip().split() cls_id, xc, yc, bw, bh int(parts[0]), float(parts[1]), \ float(parts[2]), float(parts[3]), float(parts[4]) # 反向从归一化坐标还原成像素坐标 x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) color (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, class_names[cls_id], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.imwrite(output_path, img)这个脚本做的事情是把 YOLO 标注画回图片上参数里 class_names 必须和转换脚本用同一份列表。跑完抽样后一张张看图重点看框有没有偏移、有没有漏掉小目标、类别有没有标错。抽样比例我一般取 15%~20%全部 559 张里抽查 80 到 100 张。抽查发现的问题如果是成片出现的比如某几十张图的框都整体偏左那就是标注时手抖了。这时候不要一张张手动改回到 labellmg 里按批次修正更高效因为 XML 格式下框的位置一目了然比对着 TXT 猜坐标靠谱得多。4. 训练自己的三轮车检测模型目录结构与超参数设置4.1 数据集目录结构和 data.yaml 配置把 VOC 转成 YOLO 并完成质量抽检后下一步是组织训练集目录。YOLO 官方仓库对目录结构有明确约定图片和标签分开存放并各自拆分 train 和 val 两个子目录标签文件和图片必须同名只是扩展名不同。这是一个最小可用的数据集目录结构tricycle_dataset/ ├── images/ │ ├── train/ │ │ ├── 0001.jpg │ │ └── ... │ └── val/ │ ├── 0500.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── 0001.txt │ │ └── ... │ └── val/ │ └── 0500.txt └── data.yaml划分比例方面559 张图我一般取 8:2也就是约 447 张训练、112 张验证。如果图片来源是同一段视频连续抽帧直接随机划分会导致训练集和验证集高度相似验证指标虚高。正确做法是先把图片按场景分组再按组划分。有了目录结构还要写 data.yaml这是告诉模型“去哪里找数据、有几个类别、类别叫什么”的配置文件。# data.yaml 内容 train: tricycle_dataset/images/train val: tricycle_dataset/images/val nc: 1 names: [tricycle]data.yaml 里的 path 如果填的是相对路径就要保证运行训练命令时的工作目录和这个相对路径对得上。4.2 训练命令与必调参数batch、epoch、imgsz目录和配置文件就绪后开始训练。YOLOv5 和 YOLOv8 是现在用得最多的两个版本命令略有差异但核心参数名基本一致。我以 YOLOv5 为例先做一次短训练验证流程通不通再跑完整训练。# 安装依赖第一次需要 pip install -r requirements.txt # 先跑 10 个 epoch 验证流程 python train.py --img 640 --batch 16 --epochs 10 \ --data tricycle_dataset/data.yaml \ --weights yolov5s.pt --name tricycle_test参数从功能上可以分成三类。第一类是输入控制--img 指定训练分辨率640 是基础值如果图片里三轮车只占很小一块建议先把它切块或改成分辨率更高一档但显存占用会随之上涨。第二类是训练强度--batch 是批大小16 是 8GB 显存下的稳妥值--epochs 是训练轮数三轮车这类单类别任务 100 轮基本够用。第三类是模型结构--weights 指定预训练权重yolov5s.pt 是参数量较小的版本559 张的数据量根本喂不饱大模型用 s 甚至 n 型号才是合理的直接上 xl 很容易过拟合。用 YOLOv8 的话命令改成如下形式yolo detect train datatricycle_dataset/data.yaml \ modelyolov8s.pt epochs100 imgsz640 batch16这里 model 参数既可以用官方预训练权重也可以直接指定模型架构配置文件训练中途停止后还能用resumeTrue接着跑。YOLOv8 的这套命令行风格我个人感觉比 v5 更清新但底层训练逻辑差别不大。4.3 训练日志怎么看loss 和 mAP 对应什么问题训练启动后终端会滚动输出每一轮的指标很多人盯着数字看半天不知道哪些该关心。我一般按优先级分成三块第一是 box_loss、cls_loss、dfl_loss 三个损失值它们只要在持续下降就是正常第二是验证集上的 precision、recall 和 mAP这三项才是模型真实水平的反映第三是训练速度它只提示系统性能不影响模型质量。关于 yolo 损失函数box_loss 负责回归边界框的坐标cls_loss 负责分类是否准确dfl_loss 是分布焦点损失主要优化框的边沿精度。三轮车数据量小常见的翻车现场是训练 loss 一直降但 mAP 上不去这多半是过拟合了。判断方法很简单看 box_loss 在训练集和验证集上的差距如果验证集 loss 在某个 epoch 后开始反弹而上训练集还在降说明模型开始死记硬背训练图片这时候早停就够了继续跑只会让结果更差。训练结束后会在 runs/detect/train 目录下生成 weights/best.pt 和 weights/last.pt测试和部署时用 best.pt。5. 三轮车数据集避坑清单从标注到训练阶段的常见问题与排查5.1 现象labellmg 标注完了但训练时报“Cant find label for image”训练启动后提示找不到某张图的标签文件打开 labels 目录一看确实缺了几个 TXT。原因通常是 labellmg 在标注过程中自动保存没有打开切换图片时部分图跳过了保存或者图片文件名里有空格和特殊字符转换脚本处理时同步失败。解决方法是转换前先把所有文件名统一成纯数字前缀比如 0001.jpg、0002.jpg 这种格式再重新执行转换脚本并在转换后对比图片和标签的文件数量。5.2 现象loss 训练正常但预测时所有框都偏向图片左上角这是坐标系换算翻车了。YOLO 格式要求的是中心点坐标加宽高如果转换脚本里算的是左上角坐标除以图片宽高模型学到的就是错误映射。遇到这种情况不要猜返回到 2.2 节的转换脚本找一个已知样本手算一遍坐标再对照 TXT 里的数值确认是 x_center 用的(xminxmax)/2而不是xminy 轴同理。坐标系这种错位代码 review 很难看出来跑一次反向可视化立刻暴露。5.3 现象验证集 mAP 很高但实际图片上三轮车就是检测不到这是最迷惑人的场景常见于数据划分不当。如果 559 张图里同一场景的连续帧被同时分进了训练集和验证集验证指标会“虚假繁荣”但换个角度、换个背景的真实图片模型立刻不行。解决方法是在划分数据前先按拍摄场景聚类让同一场景的图片全部进训练或全部进验证。另一个可能原因是标注框过紧或过松导致特征学习不充分检查第 3.2 节的标注策略遮挡严重的目标漏标也会让模型误以为“三轮车必须完整可见才算目标”。5.4 现象训练时报“image not found”或“label out of bounds”如果训练日志里出现这种报错十有八九是图片路径里带了中文或空格YOLO 的读取逻辑对这类路径支持不好。解决方法是把数据集整体挪到纯英文路径下图片文件名也改成纯数字。另一个常见诱因是第 2.2 节提到的边界框越界问题检查转换脚本里是否做了归一化后的裁剪如果某个框的左边界超出了图片宽度训练时就会抛异常。我在写转换函数时把越界值裁剪到 0~1 区间这个处理不要省。5.5 现象epoch 已经跑满但 mAP 还在缓慢爬升要加轮数吗559 张的小数据集上mAP 在 80 轮之后还缓慢上升是可能的但收益极低。这时候该做的是调数据而不是加算力检查是不是所有三轮车都在白天场景有没有夜间和雨天样本用 Mosaic 数据增强扩大有效数据量或者用已训练好的模型做半自动预标注人工修正后扩充到 1000 张以上。数据扩充的优先级永远高于堆 epoch这是我的核心经验。6. 用验证脚本和测试图片做最后把关置信度阈值与漏检权衡训练结束后不要急着部署先用 test 图片做一轮感知验证。用训练时预留的 112 张验证图跑val.py拿到指标再额外找一些训练集里绝对没出现过的三轮车图片做鲁棒性测试。小数据集的通病是“见过才认得”这个阶段你会发现白天场景 mAP 0.93但同一辆车换个黑暗背景就检测不到了这很正常559 张的底子决定了上限。一个很容易被忽略但影响极大的参数是置信度阈值。YOLO 默认的 conf 阈值在 0.25 左右如果调低到 0.1漏检会减少但误检增多调高到 0.5 则反过来。我的习惯是用验证集做一次阈值扫描把 precision 和 recall 的曲线画出来找两者交叉点的阈值作为部署默认值。三轮车检测通常偏重少漏检宁可多报一个不可放过一个所以阈值我会设在 0.15~0.2 之间。最后一公里的建议是保留完整的标注原始文件。559 张的 VOC XML 和 YOLO TXT 都别删后续要扩充类别、修正边界、做数据蒸馏都靠它们。我自己就吃过亏一次整理磁盘时清掉了 XML 只留了 TXT后来想细化“载货三轮车”类别只能重新打开 labellmg 一张张补标那种感觉确实不好受。这套数据集的方向是靠谱的关键是别把原始资产搞丢了。希望帮到你。本文还有配套的精品资源点击获取
