
简介本资源为面向YOLOv5目标检测学习者的车辆检测数据集类别聚焦单一car适用于交通监控、自动驾驶、安全驾驶等场景下的模型训练与验证适合具备一定深度学习基础、希望快速上手车辆检测实践的开发者与研究者。压缩包共2000个文件以1285个txt标签、1284个jpg图像和1284个xml标注为主txt提供边界框坐标xml记录类别、坐标与面积等细节整体约147.64MB采用PASCAL VOC格式便于直接接入YOLOv5训练流程。目前已有4474人学习下载热度较高。读者可据此完成数据预处理、标签格式转换、数据增强与超参数配置并借助mAP等指标评估模型针对光照变化、遮挡、视角差异等难点做迁移学习与调优也可将流程迁移到其他物体检测任务。1. 从一份 car 车辆检测数据集.rar 说起yolov5 训练自己的数据集到底卡在哪很多人拿到car车辆检测数据集.rar的第一反应是解压、改路径、开训结果跑完 300 轮 mAP 只有 0.3回头怀疑是数据集太脏。我踩过这个坑真正拖垮精度的往往不是图片质量而是标注格式没对齐、类别名和 data.yaml 对不上、验证集里混进了训练集同款连续帧。这份数据集通常就是一堆 jpg/png 加对应 txt 或 xml规模从几百到几千张不等场景集中在道路、停车场、卡口。它解决的是「我没有标注数据」这个冷启动问题适合想用 yolov5 跑通车辆检测、做车牌/车流/无人小车感知原型的同学。但「有数据」和「能训出可用模型」之间隔着格式转换、划分策略、超参选择三道坎这篇就把这三道坎按顺序拆开讲。2. 先看清 car 车辆检测数据集里到底装了什么2.1 解压后先做一次目录体检拿到压缩包别急着写训练脚本先解压看结构。常见两种组织方式一种是images/和labels/平行目录另一种是JPEGImages/加Annotations/的 VOC 风格。用下面这段脚本把家底摸清楚比肉眼翻文件夹靠谱。import os from collections import Counter root car_dataset # 解压后的根目录 img_ext (.jpg, .jpeg, .png, .bmp) img_cnt, lbl_cnt 0, 0 ext_counter Counter() for dirpath, _, filenames in os.walk(root): for f in filenames: ext os.path.splitext(f)[1].lower() if ext in img_ext: img_cnt 1 ext_counter[ext] 1 elif ext .txt: lbl_cnt 1 elif ext .xml: lbl_cnt 1 print(图片总数:, img_cnt, 标注文件总数:, lbl_cnt) print(图片格式分布:, ext_counter) # 图片和标注数量对不上说明有漏标或多余文件必须先查逻辑说明遍历整个目录统计图片和标注文件数量图片格式分布能帮你判断是否需要统一转格式。参数上root改成你实际解压路径即可。如果图片数和标注数差得超过 5%基本可以确定存在漏标或孤立标注这时候直接开训等于给模型喂噪声。2.2 判断标注是 VOC XML 还是 YOLO TXT这一步决定了你后面要不要写转换脚本。打开一个标注文件看内容如果是annotationobjectnamecar/namebndbox...这种就是 VOC XML坐标是左上右下绝对像素值如果是0 0.512 0.634 0.120 0.230这种一行五个数就是 YOLO TXT格式为class_id x_center y_center width height且全部归一化到 0~1。格式坐标含义是否需要转换常见来源VOC XMLxmin ymin xmax ymax 绝对像素需要转 YOLO TXTLabelImg 默认、老数据集YOLO TXT归一化中心点宽高直接用Roboflow 导出、YOLO 系COCO JSON绝对像素 类别 id需要转大规模公开集我一般会先head一个 txt再head一个 xml确认到底混没混。有些数据集两种格式混着放这种最坑必须统一。2.3 类别名和类别数必须锁死车辆检测数据集里类别可能只有car一类也可能有car/bus/truck/van多类。用下面脚本统计每个类别出现次数顺便确认类别名有没有大小写不一致、中英文混用。import os from collections import Counter label_dir car_dataset/labels cls_counter Counter() for f in os.listdir(label_dir): if not f.endswith(.txt): continue with open(os.path.join(label_dir, f)) as fp: for line in fp: parts line.strip().split() if len(parts) 5: cls_counter[parts[0]] 1 print(类别 id 分布:, cls_counter) # 如果出现 id 跳跃比如只有 0 和 2说明 data.yaml 的 nc 要按最大 id1 写逻辑说明统计每个 class_id 的框数量。参数上label_dir指向标注目录。如果发现某个类别只有个位数样本训练时要么合并类别要么直接删掉否则模型对这个类基本学不动。类别名最终要写进data.yaml的names列表顺序必须和 id 一一对应错一位整个训练结果就是玄学。3. 把 car 数据集转成 yolov5 能直接吃的格式3.1 VOC 转 YOLO转换脚本与四个边界坑如果体检发现是 VOC XML就得转。核心是把绝对坐标归一化同时处理越界框。import os import xml.etree.ElementTree as ET voc_dir car_dataset/Annotations out_dir car_dataset/labels os.makedirs(out_dir, exist_okTrue) # 类别名到 id 的映射必须和 data.yaml 一致 classes [car] for xml_file in os.listdir(voc_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(voc_dir, xml_file)) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in classes: continue cls_id classes.index(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) # 边界裁剪防止坐标越界导致归一化后为负或大于 1 xmin max(0, min(xmin, w)) xmax max(0, min(xmax, w)) ymin max(0, min(ymin, h)) ymax max(0, min(ymax, h)) x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h # 过滤掉宽高为 0 的脏框 if bw 0 or bh 0: continue lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}) out_name os.path.splitext(xml_file)[0] .txt with open(os.path.join(out_dir, out_name), w) as f: f.write(\n.join(lines))逻辑说明逐 XML 解析把绝对坐标转成归一化中心点格式。四个边界坑分别是坐标越界裁剪、宽高为 0过滤、类别名不在映射表跳过、图片宽高读不到会抛异常需提前确认 size 节点存在。参数上classes必须和后续data.yaml的names完全一致out_dir建议和图片目录分开但保持同名方便 yolov5 按文件名配对。3.2 训练集/验证集划分别用随机划分糊弄车辆检测数据如果来自视频抽帧相邻帧几乎一样。随机划分会让验证集里出现训练集的「近亲」mAP 虚高。我一般按场景或时间划分实在没有元信息就用sklearn分层抽样并保证同一段视频的帧只进一个集合。import os import random import shutil img_dir car_dataset/images lbl_dir car_dataset/labels out_root car_dataset_split val_ratio 0.2 random.seed(42) imgs [f for f in os.listdir(img_dir) if f.lower().endswith((.jpg, .png))] random.shuffle(imgs) val_num int(len(imgs) * val_ratio) val_imgs imgs[:val_num] train_imgs imgs[val_num:] for split, files in [(train, train_imgs), (val, val_imgs)]: os.makedirs(f{out_root}/images/{split}, exist_okTrue) os.makedirs(f{out_root}/labels/{split}, exist_okTrue) for f in files: shutil.copy(os.path.join(img_dir, f), f{out_root}/images/{split}/{f}) lbl os.path.splitext(f)[0] .txt src_lbl os.path.join(lbl_dir, lbl) if os.path.exists(src_lbl): shutil.copy(src_lbl, f{out_root}/labels/{split}/{lbl})逻辑说明按 8:2 划分并复制到标准目录结构。参数val_ratio一般 0.1~0.2数据量少于 500 张时建议 0.2 以上。random.seed固定后结果可复现。注意这里只复制有标注的图片如果某张图没有对应 txt会被跳过训练时 yolov5 会把它当负样本需确认这是不是你想要的。3.3 写对 data.yaml三个字段错一个就白训path: /home/user/car_dataset_split train: images/train val: images/val nc: 1 names: [car]path是数据集根目录train/val是相对路径。nc是类别数names顺序必须和转换时的classes一致。常见翻车是nc写了 1 但 names 里有两个类或者路径用了反斜杠在 Linux 下读不到。改完用python -c import yaml; print(yaml.safe_load(open(data.yaml)))验证一遍。4. yolov5 训练车辆检测模型的参数怎么设4.1 从预训练权重起步别从零训车辆检测数据量通常不大从零训收敛慢且容易过拟合。直接用官方 COCO 预训练权重--weights yolov5s.pt。模型选型上yolov5s适合边缘部署和快速验证yolov5m/l精度更高但显存吃紧。我一般先用 s 跑通全流程再换 m 调精度。python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data data.yaml \ --weights yolov5s.pt \ --cfg models/yolov5s.yaml \ --hyp data/hyps/hyp.scratch-low.yaml \ --project runs/train \ --name car_exp1逻辑说明--img 640是输入分辨率车辆目标通常不大640 够用小目标多可上 1280 但显存翻倍。--batch 16按显存调8G 显存跑 s 模型 640 大概能到 16。--epochs 100对小数据集足够配合早停。--hyp选 low 增强适合小数据数据量大可换hyp.scratch-high.yaml。4.2 三个必调超参lr0、lrf、warmupyolov5 超参文件里几十个参数真正影响收敛的就那几个。lr0初始学习率默认 0.01小数据集建议降到 0.001~0.005否则前期 loss 震荡。lrf是最终学习率比例默认 0.01控制余弦退火终点。warmup_epochs预热轮数默认 3小数据集可降到 1避免预热阶段浪费太多轮。参数默认值小数据集建议作用lr00.010.001~0.005初始学习率lrf0.010.01~0.05最终 lr lr0 * lrfwarmup_epochs3.01.0预热轮数box0.050.05框回归损失权重cls0.50.5分类损失权重改法是在data/hyps/下复制一份改训练时--hyp指过去。别直接改默认文件下次换项目就忘了。4.3 训练过程看什么loss 曲线和 mAP 的读法开训后重点盯三个输出box_loss、obj_loss、mAP0.5。box_loss前期快速下降后趋稳是正常如果一直震荡说明 lr 太大。obj_loss反映目标置信度车辆检测里如果背景误检多这个值会偏高。mAP0.5在 50 轮后还没上 0.5先别加轮数回头查标注和划分。验证集 mAP 涨而训练集 loss 不降是过拟合前兆早停或加增强。5. 车辆检测训练避坑与排查清单5.1 现象mAP 一直是 0 或极低原因data.yaml的names和标注 class_id 对不上或者图片和标注文件名不匹配比如图片001.jpg标注001.txt但实际是1.txt。解决用 2.3 的统计脚本确认 id 分布再写脚本检查每张图是否有同名 txt缺的列出来人工补或删。5.2 现象训练 loss 正常但验证集全框错原因验证集图片和训练集来自同一段视频的相邻帧模型记住了背景。解决重新按视频段或时间戳划分确保同一段只进一个集合。没有元信息就人工看验证集图片和训练集撞脸的挑出来换掉。5.3 现象显存溢出 CUDA out of memory原因--img或--batch太大或者--workers开太多导致内存也爆。解决先把 batch 降到 8 或 4img 降到 416 试通--workers设成 CPU 核数的一半Windows 下建议 0 或 2。还不行就换yolov5n或开启--amp混合精度。5.4 现象推理时框重叠严重、同一辆车多个框原因NMS 的--conf-thres和--iou-thres没调。默认 conf 0.25、iou 0.45车辆密集场景 iou 可降到 0.3~0.4。解决推理时显式传参--conf-thres 0.3 --iou-thres 0.4再根据实际画面微调。别在训练阶段纠结这个后处理调参成本最低。5.5 现象小目标车辆漏检严重原因输入分辨率不够或数据集中小目标样本太少。解决训练--img 1280同时检查标注里小框宽高小于 10 像素占比太少就补充数据或用小目标增强mosaic 已默认开。推理时也可提高输入尺寸但速度会降。6. 训完之后验证、导出与边缘部署的取舍训完不是终点得先验证再谈部署。验证用val.py重点看每类 AP 和混淆矩阵别只看总 mAP。python val.py \ --data data.yaml \ --weights runs/train/car_exp1/weights/best.pt \ --img 640 \ --conf-thres 0.3 \ --iou-thres 0.4 \ --task val逻辑说明--task val只做验证不保存预测图--conf-thres和--iou-thres按 5.4 调。输出里per class AP能看出 car 这一类到底学得怎样如果 AP 高但实际画面漏检多半是验证集分布和真实场景不一致。导出环节如果目标是树莓派 4b/5 或 rk3568 这类边缘板优先导 ONNX 再转对应推理引擎。yolov5 自带export.pypython export.py \ --weights runs/train/car_exp1/weights/best.pt \ --include onnx \ --img 640 \ --opset 12 \ --simplify--opset 12兼容性较好--simplify会做图优化。导出后务必用onnxruntime跑一张图对比 PyTorch 输出数值差超过 1e-3 就要查。量化到 int8 能提速但精度会掉车辆检测里小目标对量化敏感建议先跑 fp16 看速度够不够不够再试 int8 并重新验证 mAP。我自己的习惯是任何数据集先跑通 10 轮看 loss 和 mAP 趋势趋势不对绝不加轮数硬训。这份 car 车辆检测数据集.rar 的价值在于省去标注但省下的时间必须花在格式对齐和划分上。希望帮到你。本文还有配套的精品资源点击获取