
简介本资源面向从事机器视觉与目标检测的开发者及学生聚焦非机动车违规停放场景下的电动车识别任务提供YOLOv5可直接训练使用的已标注数据。包内为电动车数据集中的第七类——雅迪电动车共864张实拍图片配套858个XML标注文件压缩包约100MB合计1722个文件图片与标注一一对应省去自行采集与标注的成本。该分类属于更大规模非机动车数据集的一部分同类还涵盖山地、公路、通勤、共享单车绿源、台铃、小刀、共享电动车以及淮海、金彭、宗申等三轮车每类约500至1000张整体规模达两万余张便于后续扩展多类别检测。目前已有2330人学习下载适合用于违规停放识别、电动车检测模型训练与算法验证可直接接入YOLOv5流程完成数据加载、训练与评估快速验证检测效果。1. 从 864 张雅迪电动车说起这套 E_bicycle7 标注数据到底能干什么如果你正在做园区、社区或者校园场景的非机动车违规停放识别大概率绕不开一个现实问题公开数据集里电动车样本太少自己拍又凑不齐角度和光照。我手上这份 E_bicycle7 资源就是专门解决这个卡点的——它是整个非机动车数据集里电动车分类的第七类全部是雅迪电动车864 张图片每张都配了 XML 标注直接对应 YOLOv5 的训练格式。说白了这份资源不是让你从零标注而是把「数据准备」这一步替你走完了。你拿到手就能直接进 YOLOv5 的训练流程把精力放在模型调参和部署上。适合两类人一是刚接触机器视觉识别、想跑通一个完整非机动车违规停放检测流程的新手二是手头有场景但缺电动车样本、需要快速补充某一类数据的老手。下面我按「数据长什么样 → 怎么转成 YOLO 格式 → 怎么训 → 坑在哪」的顺序拆一遍。2. 拆开 E_bicycle7 数据包864 张图与 XML 标注的结构2.1 图片与标注的对应关系这份资源的核心是「图片 XML 标注」成对出现。864 张雅迪电动车图片命名规则是「雅迪电动车_编号.jpg」编号从个位数到四位数都有比如雅迪电动车_41.jpg、雅迪电动车_1011.jpg。对应的标注文件是同名 XML放在同一目录或者平行的 annotations 目录下具体看你拿到的压缩包结构。XML 的格式是 PASCAL VOC 风格里面记录了图片尺寸、目标类别和边界框坐标。类别名统一是 E_bicycle7这个命名很关键——它决定了你后面训练时模型输出的类别标签。如果你直接把这份数据混进自己的数据集类别名冲突或者重复定义会直接导致训练报错。我一般拿到这种数据包第一件事不是急着转格式而是先抽查三到五张图确认 XML 里的 bndbox 坐标和图片里的电动车位置对得上。这一步花两分钟能省掉后面几小时的排查。2.2 数据规模在整体数据集里的位置摘要里写得很清楚这份 E_bicycle7 只是电动车大类下的一个子类。整个电动车部分有 8000 张左右分绿源、台铃、小刀、雅迪、共享电动车等每类 800 到 1000 张。雅迪这一类给了 864 张属于正常量级。再往上自行车 8000 张、三轮车 6000 张整个非机动车数据集接近 22000 张。这个规模意味着什么如果你只做电动车违规停放识别864 张够你训一个单类检测器但泛化能力有限。更合理的做法是把这份数据当作「补充样本」和你自己场景里的电动车图片混在一起训。雅迪这个品牌在现实中保有量高样本多样性角度、光照、遮挡比你自己拍的要好。提示不要指望 864 张就能覆盖所有电动车外观。雅迪不同车型差异不小如果场景里还有其他品牌建议按比例混入。2.3 标注质量与重复样本的处理摘要里提到「极个别重复」这是真实数据集的常态。重复样本分两种一种是完全相同的图片被复制了两份另一种是同一辆车不同角度但高度相似。前者必须去重后者可以保留但要控制比例。去重我一般用感知哈希pHash快速筛一遍阈值设 5 到 8 之间。完全重复的直接删高度相似的保留但打散到不同 fold 里避免训练集和验证集出现同一辆车的不同角度导致验证指标虚高。这一步不做你看到的 mAP 可能是假的。XML 标注本身也可能有框偏大、框偏小、漏标的情况。864 张里我抽查下来大部分框是紧贴车身的少数几张把旁边的柱子或者地面标线也框进去了。这种脏标注在训练时会引入噪声建议用脚本把宽高比异常比如宽高比大于 5 或小于 0.2的框筛出来人工过一遍。3. 从 XML 到 YOLO 格式转换脚本与四个边界坑3.1 为什么必须转成 YOLO 格式YOLOv5 不认 PASCAL VOC 的 XML它要的是每张图对应一个 txt 文件每行格式是「类别索引 中心x 中心y 宽 高」坐标全部归一化到 0 到 1 之间。这个转换看着简单但边界情况不少。我见过太多人转完格式直接开训结果 loss 不降回头查才发现坐标没归一化或者类别索引从 1 开始。下面这个脚本是我常用的版本处理 E_bicycle7 这种单类别数据刚好够用。import os import xml.etree.ElementTree as ET from PIL import Image # 类别映射E_bicycle7 对应索引 0 CLASS_MAP {E_bicycle7: 0} def convert_annotation(xml_path, img_path, out_dir): tree ET.parse(xml_path) root tree.getroot() # 用 PIL 读图片真实尺寸不信任 XML 里的 size with Image.open(img_path) as im: w, h im.size lines [] for obj in root.iter(object): cls_name obj.find(name).text.strip() if cls_name not in CLASS_MAP: continue cls_id CLASS_MAP[cls_name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 边界裁剪防止坐标越界 xmin max(0, min(xmin, w)) xmax max(0, min(xmax, w)) ymin max(0, min(ymin, h)) ymax max(0, min(ymax, h)) # 归一化并转中心点格式 cx (xmin xmax) / 2.0 / w cy (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) if lines: base os.path.splitext(os.path.basename(xml_path))[0] with open(os.path.join(out_dir, base .txt), w) as f: f.write(\n.join(lines))逻辑说明脚本先读图片真实宽高而不是用 XML 里写的 size因为有些标注工具的 size 字段是错的。然后对每个 object 做边界裁剪防止 xmin 小于 0 或者 xmax 超过图片宽度。最后归一化并转成中心点加宽高的格式。参数说明CLASS_MAP 里 E_bicycle7 映射到 0如果你后面要混入其他类别在这里加映射就行但索引必须从 0 开始连续。归一化保留 6 位小数够用且不会引入精度损失。3.2 四个容易翻车的边界情况第一个坑是坐标越界。XML 里偶尔出现 xmax 大于图片宽度的情况直接归一化会得到大于 1 的值YOLOv5 训练时不会报错但那个框实际是错的。脚本里的 max/min 裁剪就是防这个。第二个坑是空标注文件。有些图片可能没有目标XML 里 object 数量为 0。这种图如果生成空 txtYOLOv5 会把它当负样本但比例不能太高。我一般统计一下空标注比例超过 5% 就考虑剔除部分。第三个坑是类别名大小写和空格。E_bicycle7 如果写成 e_bicycle7 或者带前后空格CLASS_MAP 匹配不上转换后 txt 是空的。脚本里用了 strip()但映射表的 key 必须和 XML 里完全一致。第四个坑是图片格式。jpg 和 JPG 在 Linux 下是两个不同的文件名遍历时如果只匹配小写后缀会漏文件。建议用 os.path.splitext 取后缀后统一转小写再判断。3.3 转换后的目录结构YOLOv5 要求的数据集结构是 images 和 labels 平行train 和 val 分开。转换完我一般整理成下面这样dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/划分比例按 8:2 或者 9:1864 张的话验证集留 80 到 100 张就够。注意 images 和 labels 下的文件名必须一一对应只是后缀不同。划分时用随机种子固定保证每次跑的结果可复现。4. 用这份数据训 YOLOv5环境、配置与训练参数4.1 环境配置的最小闭环YOLOv5 的环境不算复杂但版本对不上会出各种玄学问题。我一般用 conda 建一个干净环境Python 3.8 到 3.10 都行PyTorch 选 1.12 以上。CUDA 版本跟着显卡驱动走不用追最新。conda create -n yolo5 python3.9 -y conda activate yolo5 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt逻辑说明先建环境再装 PyTorch最后装 YOLOv5 的依赖。requirements.txt 里包含了 numpy、opencv、matplotlib 这些版本已经锁好不要手动升级。参数说明cu118 对应 CUDA 11.8如果你的驱动只支持到 11.6换成 cu116。装完用python -c import torch; print(torch.cuda.is_available())验证返回 True 才算通。4.2 数据配置文件怎么写YOLOv5 用 yaml 文件描述数据集路径和类别。针对 E_bicycle7 单类数据新建一个data/e_bicycle7.yamlpath: ../dataset train: images/train val: images/val nc: 1 names: [E_bicycle7]逻辑说明path 是数据集根目录train 和 val 是相对路径。nc 是类别数单类就是 1。names 列表里的顺序必须和转换脚本里的 CLASS_MAP 索引一致否则模型学到的类别会错位。参数说明如果你后面要混入自行车或三轮车数据nc 改成对应数量names 按索引顺序排列。改完记得检查转换脚本里的映射表同步更新。4.3 训练命令与关键超参数单类数据用 YOLOv5s 就够模型小、训练快。命令如下python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data data/e_bicycle7.yaml \ --weights yolov5s.pt \ --project runs/train \ --name e_bicycle7_exp逻辑说明img 640 是输入分辨率864 张图用 640 够用想提精度可以上 1280 但显存翻倍。batch 16 是 8G 显存下的稳妥值显存大可以加到 32。epochs 100 对单类数据通常够收敛看 loss 曲线如果还在降可以加到 150。参数说明weights 用预训练的 yolov5s.pt不要从零训小数据集从零训基本学不出东西。project 和 name 控制输出目录跑完在 runs/train/e_bicycle7_exp 下看结果。训练过程中重点看三个指标box_loss 是否稳定下降、mAP0.5 是否在 30 个 epoch 后开始爬升、验证集的 precision 和 recall 是否差距过大。如果 recall 明显低于 precision说明漏检多可能是标注框偏小或者数据里小目标太多。4.4 训练完怎么验证模型真的能用训练结束不代表模型能用。我一般做两步验证先用val.py跑一遍验证集看 mAP 和混淆矩阵再找几张训练集里没有的电动车图片做推理肉眼确认框的位置和置信度。python val.py --data data/e_bicycle7.yaml --weights runs/train/e_bicycle7_exp/weights/best.pt --img 640逻辑说明val.py 会输出每类的 AP 和整体 mAP同时生成混淆矩阵和 PR 曲线。重点看 E_bicycle7 这一类的 AP如果低于 0.5说明数据或训练有问题。参数说明--img 必须和训练时一致否则推理尺度不匹配会导致精度下降。--weights 指向 best.pt不要用 last.ptlast 可能过拟合。5. 避坑与排查这份数据用起来最容易踩的五个问题5.1 训练 loss 不降mAP 一直是 0现象开训后 box_loss 在 0.5 附近震荡mAP 始终为 0模型不收敛。原因最常见的是类别索引不匹配。转换脚本里 E_bicycle7 映射到 0但 yaml 里 names 写成了别的顺序或者 nc 写成了 2。另一个可能是 txt 文件里坐标没归一化值大于 1。解决随便打开一个生成的 txt确认每行第一个数字是 0后面四个数都在 0 到 1 之间。再检查 yaml 的 nc 和 names 是否和转换脚本一致。改完重新生成 labels 再训。5.2 验证集 mAP 很高实际推理全是误检现象val.py 跑出来 mAP0.5 有 0.8但拿真实场景图片推理背景里的广告牌、垃圾桶都被框成电动车。原因训练集和验证集划分时没有打散同一辆车的不同角度同时出现在 train 和 val 里导致验证指标虚高。另外 864 张里如果背景单一模型学到的是背景特征而不是电动车特征。解决重新划分数据集用图片的感知哈希做分组同一组只进 train 或 val。训练时加数据增强YOLOv5 默认开了 mosaic 和 HSV 增强确认没被关掉。如果背景太单一混入一些负样本图片。5.3 XML 解析报错提示 not well-formed现象转换脚本跑到某张图时抛异常提示 XML 格式错误。原因标注文件在保存时被截断或者里面有非法字符。这种情况在批量标注的数据里不罕见。解决用 try/except 包住 ET.parse遇到解析失败的记录文件名跳过并记录。跑完统计跳过了多少张如果超过 10 张建议找标注方重新导出。5.4 显存不够batch 降到 4 还是 OOM现象训练启动后报 CUDA out of memory降 batch 也没用。原因YOLOv5 默认会开多尺度训练和 mosaic显存占用比预期高。另外如果 img 设了 1280显存需求是 640 的四倍左右。解决先把 img 降到 640batch 设 8。如果还不够在 train.py 里加--nosave减少中间权重保存或者用--workers 2降低数据加载进程数。实在不行换 yolov5n模型更小。5.5 推理时框的位置偏移明显偏左或偏上现象模型能检出电动车但框整体往左上偏移和车身对不齐。原因转换时用了 XML 里的 size 字段而不是图片真实尺寸两者不一致导致归一化基准错了。或者推理时的预处理 resize 和训练时不一致。解决确认转换脚本用的是 PIL 读出的真实宽高。推理时用 YOLOv5 自带的 detect.py不要自己写预处理它的 letterbox 逻辑和训练时是对齐的。6. 把 E_bicycle7 用出更高价值混类训练与部署前验证单类数据训出来的模型放到真实场景里往往不够用。我的习惯是把 E_bicycle7 当作电动车类的种子数据和自行车、三轮车数据按比例混合训一个多类检测器。这样模型学到的特征空间更大对电动车本身的泛化反而更好。混合时注意类别平衡。假设你手头有自行车 8000 张、三轮车 6000 张、电动车只有这 864 张直接混进去电动车会被淹没。我一般对多的类别做下采样每个类别控制在 2000 到 3000 张电动车不够就用这 864 张加上自己补拍的。类别索引重新排E_bicycle7 可以映射到电动车大类下的一个子索引也可以直接归到「电动车」这个大类里。部署前我强制走一遍的验证流程是这样的从验证集里挑 20 张再从真实场景拍 20 张混在一起跑推理统计误检和漏检。真实场景那 20 张是关键验证集指标再高真实场景翻车就是翻车。这一步我吃过亏有一次验证集 mAP 0.85实际部署到园区门口晚上光线暗的时候漏检率超过一半。后来补了夜间样本重新训才解决。还有一个技巧是导出 ONNX 之后用 onnxruntime 跑一遍对比 PyTorch 和 ONNX 的输出差异。如果差异大说明有算子不被支持或者导出时的 opset 不对。YOLOv5 导出命令是python export.py --weights best.pt --include onnx --opset 12opset 12 兼容性最好。从那以后我每次拿到新数据集都强制先跑一遍「转换 → 抽查 → 小规模训 10 个 epoch → 真实场景验证」这个闭环确认没问题再上全量训练。这套流程帮我省下了不少返工时间。希望帮到你。本文还有配套的精品资源点击获取