ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

YOLO车辆数据集实战:从标签检查到高效训练全指南

YOLO车辆数据集实战:从标签检查到高效训练全指南 简介这是一套面向目标检测学习者和算法工程师的车辆检测数据集包含卡车、小型车、摩托车和公交车四类常见车辆目标可直接用于YOLO系列模型的训练、验证与测试。资源包共2000个文件压缩包大小62.4MB其中411个txt标签为YOLO格式1589个xml标签为VOC格式同时内置data.yaml配置文件和已划分好的数据集结构适配YOLOv5、YOLOv8、YOLOv9等算法。YOLO格式标签记录了归一化后的目标类别、中心点坐标和宽高比例VOC格式则便于在标注工具或其他检测框架中查看与复用免去了自行转换标注格式的麻烦。数据集规模适中覆盖城市交通常见的四类车辆适合用来练习车辆检测、交通场景识别也可作为算法对比实验的基准数据。目前已有111人学习下载是一份上手简单、实用性较强的目标检测数据集。1. 这份 2129 张车辆数据集能做什么以及为什么先别急着开训拿到一个「yolo算法-车辆数据集-2129张图像带标签--卡车-小型车-摩托车-公交车.zip」多数人的第一反应是解压、配好 data.yaml、跑一个通宵把模型训出来。我的建议是反过来先花二十分钟把标签和目录核对一遍。2129 张图对检测模型来说不算大真正决定成果的不是训练时长而是数据质量。这份车辆数据集覆盖卡车、小型车、摩托车、公交车四类路面目标适合停车场统计、路口车流监测、园区安防这类垂直场景做 yolo 入门或直接训练。特点是类别少、场景相对单一模型容易收敛但若直接用默认参数跑类别不均衡和标签错位会在验收时让你翻车后面每一章都在绕开这些。2. 拿到 zip 别先跑训练YOLO 标签格式与目录结构核对2.1 四类目标的 txt 标签到底存了什么从归一化坐标还原成像素框标题里带「yolo算法」前缀的车辆数据集标签最常见的是 YOLO 系 txt 格式每张 jpg 对应一个同名 txt里面若干行一行圈一个目标。每行五个数依次是类别编号、中心点 x、中心点 y、框宽、框高。后四个必须除以图片宽高做归一化取值在 0 到 1 之间而不是像素值。很多刚入门的人在这里栽跟头把 txt 里的数字当成像素坐标去画框画出来全挤在图片左上角附近。import cv2 img cv2.imread(images/0001.jpg) H, W img.shape[:2] # 0001.txt 中的一行1 0.500 0.371 0.422 0.310 class_id, cx, cy, w_n, h_n 1, 0.500, 0.371, 0.422, 0.310 # 归一化坐标换算成像素框 x1 int((cx - w_n / 2) * W) y1 int((cy - h_n / 2) * H) x2 int((cx w_n / 2) * W) y2 int((cy h_n / 2) * H) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite(check_0001.jpg, img)逻辑说明这段脚本把一行标签还原成可画的矩形用来抽查标注质量。目录结构是 images 目录放图labels 目录放同名 txtYOLO 系训练时按 basename 自动配对。参数说明w_n、h_n 是相对值乘以 W、H 才得到像素宽高x1、y1 是左上角x2、y2 是右下角。类别编号是整数从 0 开始0 对应第一个类名这一行里的 1 表示小型车。如果解压出来不是 txt而是 VOC 风格的 xml 或 COCO 的 json就要先转换。xml 里是绝对像素坐标把 xmin、ymin、xmax、ymax 分别除以宽高得到归一化框再写成 YOLO 行即可。需要特别注意类别编号映射COCO 里 bus 是 5 号、truck 是 7 号如果数据集发布者从 COCO 裁切出来又没重新编号直接按 0truck 配 names 就会错位。这也是「coco80 怎么读在 yolo 里」这类需求真正要解决的问题把 80 类的旧编号映射成你自己的四类新编号。2.2 目录怎么拆train/val 划分与 data.yaml 最小配置数据集到手后先看目录是不是已经分好 train/val。有些发布者只给一个平铺目录图片和 txt 混在一起这时候需要自己拆。我的拆分习惯是 80/202129 张图大约 1700 张训练、426 张验证不单独留测试集验证集就承担测试职责因为这类单一场景数据集验证和未来落地场景的分布差异不会太大。cd datasets/vehicle mkdir -p images/train images/val labels/train labels/val # 先把平铺的图片和标签分别收拢 mv images/*.jpg images/train/ mv labels/*.txt labels/train/ # 随机抽 20% 到验证集图片和标签必须一起搬 ls images/train/*.jpg | shuf -n 426 | while read -r f; do name$(basename $f .jpg) mv images/train/${name}.jpg images/val/ mv labels/train/${name}.txt labels/val/ done # 核对数量train 约 1703val 426 echo train: $(ls images/train | wc -l), val: $(ls images/val | wc -l)逻辑说明先移动全部到 train再按随机列表抽 426 张搬到 val保证图片和同名 txt 成对移动。参数说明shuf -n 426 指定抽取数量对应 20%如果你拿到的压缩包已经带 train.txt、val.txt 清单就不用这个脚本直接按清单复制文件。搬完一定要用最后一行核对总数对不上说明有图没标签或者有标签没图。接下来写 data.yaml这是训练时唯一必须的数据描述文件。yolo 换版本后字段基本兼容path 指到数据集根目录train/val 写相对路径names 按 0 到 3 列出四类目标。一个常见错误是 names 顺序和 txt 里的编号不一致模型训出来才发现车种全错。# datasets/vehicle/data.yaml path: /home/user/datasets/vehicle # 写绝对路径别用相对路径 train: images/train val: images/val names: 0: truck 1: car 2: motorcycle 3: bus参数说明path 建议绝对路径训练脚本的工作目录经常和你解压的目录不一致相对路径容易踩空。names 的索引就是 txt 第一列的编号0truck 意味着所有 txt 里编号 0 的目标都是卡车。这里我故意把小型车写成 car 而不是 small car类名只是显示用不影响训练但尽量和你后续要迁移的开源模型对齐能省不少事。2.3 一条脚本批量验证 2129 张图的标签空文件、越界、类别编号拆完目录不要立刻训练。先跑一遍标签体检把空标签、字段缺失、坐标越界、类别编号超范围这四类问题捞出来。2129 张图手工看不过来脚本几十毫秒就能扫完这个动作能避免浪费一晚上的训练时间。from pathlib import Path root Path(datasets/vehicle) bad [] for txt in (root / labels).rglob(*.txt): lines txt.read_text().strip().splitlines() if not lines: bad.append((txt, 空标签)) continue for ln in lines: parts ln.split() if len(parts) ! 5: bad.append((txt, f字段数{len(parts)}: {ln})) continue cid, cx, cy, w_n, h_n map(float, parts) if cid not in (0, 1, 2, 3): bad.append((txt, f类别编号越界: {cid})) if not (0 cx 1 and 0 cy 1 and 0 w_n 1 and 0 h_n 1): bad.append((txt, f坐标越界: {ln})) print(有问题的文件数:, len(bad)) for item in bad[:20]: print(item)逻辑说明脚本遍历 labels 目录下所有 txt逐行检查五个字段。空标签文件会让该图在训练时被当成纯背景字段数不是 5 说明行被拆坏或用错分隔符坐标越界说明归一化公式写错或标签本身脏。参数说明cid not in (0,1,2,3) 的检查依赖你的类别数量如果就只有四类这里就是硬性校验坐标检查里 w_n、h_n 允许等于 1但大于 1 一定有问题。扫描结果为空再随机挑几张图用 2.1 的脚本把框画出来肉眼抽查这一步叫可视化验证比看数字更可靠。3. 解压到训练一条龙最小命令与必调参数3.1 解压 zip 先做三件事完整性、密码、图片可读性数据集以 zip 形式分发第一步先做完整性测试。压缩包在网络传输后经常出现 CRC 校验错误跳过这一步直接解压大概率得到一张张无法读取的 jpg训练脚本碰到坏图要么直接停要么静默跳过让数据总量悄悄缩水。完整检查命令如下解压到固定目录后再用 2.3 节的脚本验证配对。unzip -t yolo_vehicle_dataset.zip # 只测试不实际解压 unzip -o yolo_vehicle_dataset.zip -d datasets/vehicle逻辑说明unzip -t 逐个校验文件 CRC输出 no error 才算健康-o 覆盖解压-d 指定目标目录。参数说明如果压缩包带密码unzip 会提示输入这是发布者防止批量转发的常见手段。正确做法是回到发布页面找密码说明不要用网上那些号称移除 zip 密码的小工具它们多半是捆绑推广还有可能把你机器搞出问题这是我见过最多人吃亏的地方。注意带密码的 zip 不要用第三方「移除密码」工具先回发布页面找密码说明。解压完成后检查图片本身能否被解码。OpenCV 的 imread 很宽容损坏的图它不报错而是返回 None所以要用 PIL 的 verify 硬校验。顺手把图片数量和标签数量做个 diff防止少文件。from PIL import Image from pathlib import Path img_root Path(datasets/vehicle/images) broken [] for p in img_root.rglob(*.jpg): try: with Image.open(p) as im: im.verify() except Exception: broken.append(p) print(坏图数量:, len(broken)) for p in broken[:10]: print(p) labels list(Path(datasets/vehicle/labels).rglob(*.txt)) print(标签文件数:, len(labels))逻辑说明Image.verify 只校验文件结构不加载像素速度快broken 收集所有打不开的图。参数说明目录深度不确定用 rglob 递归找如果你的数据是 png 或 bmp把后缀改成对应值。最后打印的标签文件数要和图片数一致差一个都说明配对有缺漏。3.2 用 YOLOv8 跑起来的训练命令与参数选择逻辑目录和标签确认没问题就可以训练了。现在社区最常用的是 ultralytics 的 YOLOv8 系一条命令加一个 data.yaml 就能启动。我一般不会追最新发布的结构和所谓一键部署脚本因为新结构在车辆小目标上的收益不明确踩坑代价却不小锁一个验证过的固定版本把精力留给数据是性价比最高的做法。yolo detect train \ datadatasets/vehicle/data.yaml \ modelyolov8s.pt \ imgsz640 \ batch16 \ epochs100 \ projectruns/vehicle \ namebase逻辑说明model 传预训练权重yolov8s 是速度和精度的平衡点对 2129 张这种小数据集很合适。参数说明imgsz 设 640数据里的目标大多是路面车辆尺寸中等640 足够如果后续发现摩托车这种小目标召回差再调 768 或 960不要一开始就开高分辨率显存和时间都吃不消。batch 受显存约束8G 卡上 640 分辨率用 s 模型batch 16 通常能跑内存不够就降到 8这不是玄学是显存不够就报 CUDA out of memory 的硬约束。epochs 100 是起步值四类目标一共两千张图一般 60 到 100 轮就收敛训练时开启早停更省时间。训练过程中盯两个曲线train/box_loss 和 val/box_loss。前者下降说明模型在拟合后者也下降说明没过拟合如果 val 的 box_loss 在某个 epoch 开始回升而 train 还在降就是过拟合信号应该提前停而不是硬跑满。日志里每个 epoch 末尾的 mAP50 也会一起打出来可以直接观察验证集表现的变化。3.3 类别不均衡怎么办从 yolo 损失函数说起训练跑起来之前先想清楚这份数据的隐患四类目标数量大概率不均衡摩托车在小路场景里出现频次低样本数可能只有卡车的零头。yolo 损失函数由三块组成框回归损失、置信度损失、分类损失。分类损失按每个检测框的真实类别计算样本少的类贡献的梯度也少最后模型会偏向把不确定的目标预测成高频类别这就是摩托车漏检和误检的来源。处理不均衡我不建议第一轮就上花活。先按默认损失训一版看训练结束后的每类 AP如果只有摩托车低、其他三类都正常再针对性处理。常见手段有两个一是按类别给分类损失加权重让少数类的错误罚得更重二是做类别层面的复制粘贴增强把摩托车小图抠出来粘贴到别的图上增加它的出现次数。我一般选后者因为增强还顺带提升了模型对遮挡和重叠的鲁棒性。还有人会直接换改进版检测头比如 efficient head 结构的变体或者针对小目标用 NWD 距离替代 IoU 做回归。这类改进确实能提升小目标召回但改动训练代码调试成本高适合放在基线模型跑通之后作为第二步实验不要一开始就和数据问题混在一起。4. 车辆数据集训推避坑五个高频翻车点4.1 「No labels found」或指标全 0现象训练刚启动就提示找不到标签或者每个 epoch 结束后 maps 全为 0没有任何检测结果。原因分两种一是 data.yaml 里 path 和 train/val 的相对路径拼起来不存在常见于项目目录移动过二是 labels 目录里的 txt 是空文件训练脚本认为这张图没有目标整个数据集没有正样本。解决先确认 data.yaml 的 path 是绝对路径再跑 2.3 节的体检脚本。如果空标签文件很多回到发布方确认这批文件本来就是没目标还是导出时丢了确实没目标的图可以保留但得保证有目标的比例足够。路径问题则用ls datasets/vehicle/images/train | head肉眼核对目录是否存在。4.2 EXIF 旋转让标签集体错位现象用看图软件预览图片是正的模型训练出来的框却整体偏移通常是横竖颠倒。原因手机或部分相机拍照时会把旋转信息写进 EXIF预览软件主动读 EXIF 把图转正但 YOLO 训练管线用 cv2.imread 读图它不理会 EXIF 的 orientation 字段直接把原始像素塞进去。标签是发布者按转正后的图像标注的两边的坐标系就对不上了。解决训练前统一把图片转正重存。用 PIL 的 ImageOps.exif_transpose 处理一遍再覆盖保存之后 EXIF 字段里的旋转信息就被清掉了。这个坑在车辆数据里特别常见因为很多人会用手机在停车场随手拍上传前又没做任何预处理。4.3 类别编号和 names 对不上现象训练完测试卡车被认成公交车但看框的位置其实框得挺准就是类别错。原因数据集的 txt 里编号 0 对应的未必是卡车。有的发布者按 car、truck、bus、motorcycle 排序你按 truck、car、motorcycle、bus 写 names于是每个编号的语义全部错位。模型学的是编号不是语义。解决训练前不要只看 data.yaml 里 names 写得多漂亮抽几张图把类别编号可视化出来。我常用的办法是每个类别各挑 5 张用 2.1 的脚本画框并打印 class_id肉眼确认编号和车种一致后再开训。这个检查我吃过不止一次亏补过无数次数据的人会懂二十分钟的可视化能救回一个版本。4.4 摩托车 AP 极低现象mAP 整体不错但 per-class 里摩托车 AP 明显低一截漏检多、误检也多。原因摩托车在 2129 张图里的绝对样本量少且和行人、自行车在视觉上接近加上部分远距离摩托车只有几十像素高属于小目标加样本稀疏的叠加问题。解决先补样本从原始图里把摩托车框裁出来做复制粘贴增强或者找发布方要原始视频继续抽帧标注。模型参数上可以试 imgsz 从 640 提到 768小目标分辨率收益明显再进一步就换 NWD 距离的回归或者 efficient head 这类对小目标友好的结构但这两步都放在基线模型跑通之后一次只动一个变量不然出了问题你根本不知道是哪一步导致的性能变化。4.5 zip 解压 CRC 报错与文件名乱码现象解压到一半报 CRC failed或者解压出来的目录名、文件名全是乱码训练脚本按 .jpg 后缀找不到图。原因CRC 报错通常是压缩包下载不完整或者存储介质出了问题文件本身已损坏乱码则是压缩包在 Windows 下用 GBK 编码打包zip 规范里又没有统一记录编码Linux 端的 unzip 默认按 UTF-8 解于是中文目录名全部错位。解决CRC 问题回到源头重新下载不要尝试修复损坏的压缩包数据文件修出来也大概率是坏的。乱码问题可以用 Python 的 zipfile 手动解压把每个文件的原始名字从 cp437 解码再转成 gbk就能还原出正确文件名。脚本很短但能救回一批看似不可用的数据。import zipfile from pathlib import Path out Path(datasets/vehicle) out.mkdir(parentsTrue, exist_okTrue) with zipfile.ZipFile(yolo_vehicle_dataset.zip) as zf: for info in zf.infolist(): name info.filename.encode(cp437).decode(gbk, errorsignore) target out / name if not info.is_dir(): target.parent.mkdir(parentsTrue, exist_okTrue) with zf.open(info) as src, open(target, wb) as dst: dst.write(src.read())逻辑说明zipfile 默认把文件名按 cp437 解码这里先还原回原始字节再用 gbk 解码成正确中文。参数说明errorsignore 是为了跳过极少数无法解码的字符解压完记得用 3.1 节的脚本核对图片数量确认没有文件被吞。5. 训练完怎么验收指标、坏例与部署路数估算5.1 三个必看指标mAP0.5、mAP0.5:0.95、每类 AP训练结束不要只看最后一行 mAP50 有多漂亮。这个指标只反映 IoU 阈值 0.5 下的检测质量框偏半个车宽也能算对和你上线要的效果差得远。真正值得看的是三样mAP0.5、mAP0.5:0.95 和每类 AP。指标关注点干净数据集参考值mAP0.5粗检测质量框大概对上就算≥ 0.85mAP0.5:0.95框位置精确度容忍苛刻比前者低 0.1 到 0.2每类 AP暴露少数类短板各类差距应控制在 0.1 以内mAP0.5 数值高代表大目标基本罩得住mAP0.5:0.95 是把阈值从 0.5 到 0.95 每间隔 0.05 算一遍的平均它对框位置的精确度极其敏感是衡量定位质量的核心。在 2129 张这种干净数据集上四类目标 mAP0.5 跑到 0.85 以上算正常mAP0.5:0.95 通常低 0.1 到 0.2这是正常的因为 IoU 阈值提高后容错变严。每类 AP 则暴露短板如果摩托车明显低于其他三类上一章的坑你已经踩过了。验证集表格里还有 Precision 和 Recall 两列建议关注 Recall。车辆检测场景里漏检比误检更致命漏一辆车可能导致计数错误误检还能用后续跟踪或者调高置信度阈值过滤。如果 Recall 明显低于 Precision把置信度阈值往下调一档再看很多场景里 0.25 比默认 0.5 更适合计数任务。5.2 混淆矩阵与坏例分析决定要不要补数据runs 目录下会生成混淆矩阵图横轴是真实类别纵轴是预测类别。四类数据集的理想情况是对角线特别亮其他格子全黑。如果卡车那行公交车那列有亮点说明二者在视觉特征上撞车通常是车头视角或遮挡导致如果最下面一行 background 有亮块说明模型在很多没有目标的地方输出了框这是误检主场对应白天树荫、夜间灯影这类复杂背景。坏例分析不建议只看验证集整体指标而是单独跑一段带标注的视频帧序列把推理结果逐帧存下来翻。我一般会把置信度低于 0.3 但实际有目标的帧挑出来统计它们的共同点是远距离小目标、强光逆光还是遮挡严重统计完再决定补数据的方向比闷头加图效率高得多。补数据时不要只补重复场景优先补坏例里归纳出的那几类把每一类补充一二百张模型在对应场景的召回会有肉眼可见的提升。5.3 T4 上 1080p 25fps 能撑几路给部署算笔账模型训好了部署时最常被问到的问题是T4 上 1080p 25 帧每秒用 TensorRT 把 YOLO 640 分辨率检测跑起来能支持多少路这个问题的答案不只看推理时间还要把解码、缩放、后处理全部算进去。粗算逻辑1080p 25fps 意味着每路每帧只有 40 毫秒的预算。先做 TensorRT fp16 转换yolov8s 在 T4 上单帧推理大约 5 到 10 毫秒看输入尺寸和算子优化解码 1080p H.264 用 NVDEC 约 5 到 8 毫秒letterbox 缩放、归一化和 NMS 后处理再加 5 到 10 毫秒。合计单帧 15 到 28 毫秒单卡理论支撑 1 到 2 路用 int8 量化把推理再压一半能到 3 到 4 路。如果只做 1280x720 或者抽帧检测路数可以翻倍。注意这组数字是估算区间实测值受模型版本、TensorRT 算子、视频码率影响上线前必须压测。这个估算说明一个反直觉结论在车辆计数的视频场景里瓶颈通常不在 YOLO 推理而在解码和后处理。所以部署时用到 TensorRT 的同时记得把解码放到 NVDEC、把 NMS 换成 TensorRT 自带的 EfficientNMS 插件这比继续压模型尺寸更划算。6. 把 2129 张图的价值翻倍三个进阶技巧这组数据真正值钱的地方不在那 2129 张图本身而在于它帮你把标注流程和训练闭环跑通了。跑通之后第一件值得做的事是用训练好的模型做 hard example mining把模型丢到你真实场景的视频流里跑一遍把所有置信度落在 0.3 到 0.6 之间的检测框截图存下来人工快速确认。这个区间的框是模型拿不准的样本补进训练集比随机加图有效得多通常补几百张就能显著提升场景召回率。第二件事是调整增强策略。摩托车和小型车数量偏少复制粘贴增强和 mosaic 增强的组合能显著增加小目标的出现频率在 ultralytics 的增强参数里把 scale 范围调大一点让目标在缩放后更贴近真实路面的远近变化比单纯堆 epoch 有用。第三件事是考虑域扩展和任务升级。如果落地场景有夜间、雨天直接用这 2129 张图硬扛不现实常见做法是把 BDD100K 这类十万帧级的车辆检测数据集拿来预训练再用本数据集微调一批场景特征能保留夜间能力也能补上。如果你后续想做 yolo 实例分割可以基于现有检测框生成粗掩码再人工修正起步成本比从零标注低一大截。最后说一个我自己的教训最早做园区车辆统计时我拿到别人整理好的车辆数据集没有核对类别编号就直接训练上线后公交车全被识别成卡车整整查了三天才发现是 names 顺序的问题。从那以后每个数据集到手先跑体检和可视化二十分钟的检查省下来的是几个通宵。希望帮到你。本文还有配套的精品资源点击获取
返回列表