简介这份资源是面向计算机视觉初学者与目标检测实践者的YOLOv5车辆检测数据集类别聚焦为car可用于交通监控、自动驾驶、安全驾驶等场景下的模型训练与验证。压缩包共2000个文件以1285个txt标签、1284张jpg图像和1284个xml标注为主txt提供边界框坐标xml记录类别、位置与面积等细节整体约147.64MB采用PASCAL VOC格式便于直接接入YOLOv5训练流程。目前已有4470人学习下载热度较高。读者可据此完成图像缩放、归一化、标签格式转换与随机翻转、裁剪、旋转等数据增强并围绕学习率、批次大小、训练轮数等超参数展开实验用mAP及不同IoU阈值评估检测效果同时针对光照变化、遮挡、视角差异等难点做迁移学习与调优快速搭建可复现的车辆检测基线。1. 拿到 car 车辆检测数据集.rar 之后先别急着解压训练很多人从网上拖下来一个car车辆检测数据集.rar第一反应是解压、改data.yaml、python train.py三连然后盯着 loss 曲线等结果。我见过太多人卡在这一步训练跑起来了mAP 却低得离谱或者验证集上框得乱七八糟最后怀疑是模型不行、超参不对其实问题出在数据集本身没摸清楚。车辆检测这个方向数据集的标注质量、类别定义、场景分布比 yolov5 用哪个版本、batch size 设多少重要得多。这篇笔记就围绕这个 car 车辆检测数据集展开讲清楚拿到压缩包之后该怎么验、怎么转、怎么配、怎么训以及那些让我翻过车的坑。适合手里已经有一个车辆检测数据集、准备用 yolov5 跑通自己第一个模型的同学也适合已经跑通但效果不理想、想回头查数据问题的熟手。2. 拆开 car 车辆检测数据集目录结构、标注格式与类别定义2.1 先看清压缩包里到底装了什么car车辆检测数据集.rar这种命名方式很典型通常来自公开数据集搬运或者个人整理里面装的东西五花八门。解压之前先用命令行看一眼文件列表别直接双击解压到桌面几十 G 的图片散落一地很难收拾。# Linux/macOS 下先看压缩包内容不解压 unrar l car车辆检测数据集.rar | head -50 # 如果没装 unrar用 7z 也行 7z l car车辆检测数据集.rar | head -50这一步的目的是确认三件事图片是放在一个文件夹还是按 train/val 分好了标注是 XMLVOC 格式、JSONCOCO 格式还是 TXTYOLO 格式有没有已经写好的data.yaml或者classes.txt。常见的目录长这样car_dataset/ ├── images/ │ ├── 000001.jpg │ └── ... ├── annotations/ │ ├── 000001.xml │ └── ... └── classes.txt如果标注是 XML说明是 VOC 格式yolov5 不能直接吃必须转成 YOLO 的 TXT 格式。如果已经是 TXT每个文件里每行是class_id x_center y_center width height且坐标是归一化到 0 到 1 的那就能直接用。这里有个血泪经验有些数据集号称是 YOLO 格式结果坐标没归一化还是像素值训练时 loss 直接爆炸看日志才发现框的坐标全是几百上千。2.2 类别定义决定了你的模型能检出什么车辆检测数据集最容易踩的坑就是类别定义混乱。有的数据集只有一个类car有的分car、bus、truck、van还有的把car和vehicle混着标。先看classes.txt或者data.yaml里的names字段确认类别数量和顺序。# 查看类别文件 cat classes.txt # 统计每个类别的标注数量判断是否严重不均衡 for f in annotations/*.txt; do awk {print $1} $f done | sort | uniq -c | sort -rn如果发现某个类别只有几十个标注而另一个类别有上万条训练时模型会严重偏向多数类。车辆检测里car通常占绝大多数truck、bus少是正常的但如果少到个位数建议先合并类别或者补充数据。我一般会先把类别统计跑一遍心里有数再决定要不要做类别合并。提示类别顺序一旦确定训练和推理必须一致。改data.yaml里的names顺序而不重新训练推理结果会全部错位。2.3 图片尺寸、数量与场景分布的快查方法图片尺寸不统一是常态yolov5 训练时会统一 resize 到imgsz指定的大小但极端长宽比会导致目标变形。先统计一下图片尺寸分布import os from PIL import Image from collections import Counter img_dir car_dataset/images sizes Counter() for name in os.listdir(img_dir): if name.lower().endswith((.jpg, .png, .jpeg)): with Image.open(os.path.join(img_dir, name)) as im: sizes[im.size] 1 for size, count in sizes.most_common(10): print(size, count)如果发现大量图片是 1920x1080 而少数是 640x480训练时统一 resize 会让小图目标更小。常见做法是把imgsz设成 640长边缩放到 640短边按比例补齐。场景分布也要看白天、夜间、雨天、拥堵、空旷如果数据集里全是白天高速场景拿去测夜间城区必然翻车。这个没有脚本能完全自动化抽几十张图肉眼过一遍最靠谱。3. 把 VOC 标注转成 YOLO 格式转换脚本与四个边界坑3.1 转换脚本的核心逻辑VOC 的 XML 里存的是xmin, ymin, xmax, ymax像素坐标YOLO 需要的是归一化的中心点和宽高。转换公式不复杂但边界处理容易出错。import os import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path, class_map, out_path): tree ET.parse(xml_path) root tree.getroot() with Image.open(img_path) as im: w, h im.size lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in class_map: continue cls_id class_map[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 - 1)) ymin max(0, min(ymin, h - 1)) xmax max(0, min(xmax, w - 1)) ymax max(0, min(ymax, h - 1)) 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}) with open(out_path, w) as f: f.write(\n.join(lines))这段脚本的关键点在于坐标裁剪到图片边界内、过滤零面积框、归一化保留六位小数。class_map是一个字典把类别名映射到从 0 开始的整数 ID必须和data.yaml里的names顺序完全一致。3.2 四个容易翻车的边界情况第一个坑是坐标越界。有些标注工具导出的 XML 里xmax等于图片宽度归一化后是 1.0理论上没问题但如果图片被重新裁剪过而 XML 没更新坐标就会超出范围。不裁剪的话YOLO 训练时可能报错或者产生异常梯度。第二个坑是宽高为负。xmax小于xmin的情况虽然少见但确实存在通常是标注时拖拽方向反了。转换时必须判断并跳过否则归一化后宽高是负数训练直接崩。第三个坑是类别名大小写和空格。Car、car、car在 XML 里可能同时出现如果不做统一处理class_map匹配不上这些标注会被静默丢弃。我一般会先跑一遍所有 XML 的类别名统计确认没有变体。# 统计 XML 中所有类别名 grep -h name annotations/*.xml | sort | uniq -c | sort -rn第四个坑是图片和标注文件名不匹配。000001.jpg对应000001.xml但有些数据集图片是.jpeg而标注是.xml或者文件名里有空格、中文。转换脚本里最好用文件名主干去匹配而不是硬编码扩展名。3.3 转换后的验证别跳过这一步转换完不是就完事了必须验证。最简单的办法是用 yolov5 自带的可视化脚本抽几张图看看框对不对。# 假设已经 clone 了 yolov5 仓库 python utils/plots.py --labels labels/ --save-dir vis_check或者自己写个快速可视化import cv2 import os img_path car_dataset/images/000001.jpg label_path car_dataset/labels/000001.txt img cv2.imread(img_path) h, w img.shape[:2] with open(label_path) as f: for line in f: cls_id, xc, yc, bw, bh map(float, line.split()) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite(check_000001.jpg, img)抽十张不同场景的图肉眼确认框的位置和类别都对。如果框整体偏移或者大小不对大概率是归一化时用错了宽高比如用了 resize 后的尺寸而不是原图尺寸。4. 配置 yolov5 训练data.yaml、超参与显存不够时的取舍4.1 data.yaml 的写法与路径陷阱yolov5 的数据配置文件看着简单但路径写错是新手最常见的翻车点。标准写法path: /home/user/car_dataset train: images/train val: images/val nc: 1 names: [car]path是数据集根目录train和val是相对于path的路径。注意train指向的是图片目录yolov5 会自动去找同级的labels目录。也就是说如果你的图片在images/train标注必须在labels/train文件名主干一致扩展名是.txt。如果目录结构是images和annotations平级没有分 train/val那就需要自己划分。常见做法是写个脚本按 8:2 随机拆分同时移动图片和标注。import os import random import shutil img_dir car_dataset/images lbl_dir car_dataset/labels out_root car_dataset_split random.seed(42) names [os.path.splitext(f)[0] for f in os.listdir(img_dir) if f.endswith(.jpg)] random.shuffle(names) split int(len(names) * 0.8) train_names, val_names names[:split], names[split:] for subset, subset_names in [(train, train_names), (val, val_names)]: os.makedirs(f{out_root}/images/{subset}, exist_okTrue) os.makedirs(f{out_root}/labels/{subset}, exist_okTrue) for n in subset_names: shutil.copy(f{img_dir}/{n}.jpg, f{out_root}/images/{subset}/{n}.jpg) shutil.copy(f{lbl_dir}/{n}.txt, f{out_root}/labels/{subset}/{n}.txt)划分时注意别把同一段视频的连续帧分到 train 和 val 两边否则验证集精度会虚高。如果数据集来自视频抽帧按视频来源划分更合理。4.2 超参怎么设从默认值开始只动关键几个yolov5 的默认超参在data/hyps/hyp.scratch-low.yaml里对大多数车辆检测任务够用。我一般只动这几个参数默认值建议调整说明imgsz640640 或 1280小目标多用 1280显存翻倍batch-size16按显存调显存不够就降别硬撑epochs300100 到 300数据少时早停更划算lr00.010.01 或 0.001batch 变小时学习率也要降workers84 到 8Windows 下设 0 避免报错训练命令python train.py \ --data car_dataset.yaml \ --weights yolov5s.pt \ --img 640 \ --batch-size 16 \ --epochs 100 \ --workers 4 \ --project runs/train \ --name car_exp1--weights yolov5s.pt是从预训练权重开始微调比从头训快得多精度也更高。车辆检测这种常见目标预训练权重里已经有很好的特征微调几十个 epoch 就能出效果。4.3 显存不够时的三个降级方案显存爆了别急着换卡先试这三个办法。第一降batch-size从 16 降到 8 甚至 4同时把lr0按比例降一点。第二降imgsz从 640 降到 416 或 320但小目标会受影响。第三用yolov5n.pt或者yolov5s.pt这种小模型别一上来就yolov5x。# 显存紧张时的保守配置 python train.py \ --data car_dataset.yaml \ --weights yolov5n.pt \ --img 416 \ --batch-size 8 \ --epochs 100如果还是爆检查是不是workers设太高导致内存也吃紧或者验证集太大。训练日志里会打印每轮显存占用盯着看别等崩了才找原因。5. 训练过程中的排查loss 不降、mAP 不动、框乱飞怎么查5.1 loss 不降的常见原因现象是训练跑了十几个 epochbox_loss和obj_loss几乎不动。原因通常有三个学习率太大导致震荡标注格式不对导致模型学不到东西或者数据里负样本太多。先看标注用第 3 章的验证脚本抽图确认框是对的。然后降学习率从 0.01 降到 0.001 再跑几轮看 loss 有没有变化。如果还是不动检查data.yaml里的nc和names数量是否一致类别数写错会导致输出层维度不对。5.2 mAP 不动但 loss 在降这种情况说明模型在拟合训练集但验证集泛化差。常见原因是训练集和验证集分布差异大比如训练集全是白天验证集混了夜间。解决办法是重新划分数据保证两个集合场景分布接近。另一个原因是过拟合数据量太少时加数据增强yolov5 默认开了 mosaic、HSV 增强可以在hyp文件里调大mosaic和scale。5.3 推理时框乱飞或类别错位训练完用detect.py跑测试图发现框的位置离谱或者类别全错。先确认推理时的--data和训练时一致类别顺序不能变。然后看置信度阈值默认 0.25太低会出很多误检太高会漏检。python detect.py \ --weights runs/train/car_exp1/weights/best.pt \ --source test_images/ \ --conf 0.4 \ --img 640如果框的位置整体偏移大概率是推理时imgsz和训练时不一致或者图片预处理方式不同。yolov5 推理时会自动 letterbox但如果你自己写了预处理又没对齐就会出问题。5.4 排查清单按顺序过一遍遇到问题别乱试按这个顺序查标注格式对不对用可视化脚本确认data.yaml路径和类别数对不对训练日志里nc和names是否匹配学习率和 batch size 是否合理验证集和训练集分布是否一致推理配置是否和训练一致。大部分问题在前三步就能定位。6. 从能跑到好用提升车辆检测精度的几个实操技巧6.1 用测试时增强和模型集成榨精度训练完一个模型只是起点。如果精度还差一点先试测试时增强TTA推理时对图片做翻转、缩放把多次预测融合通常能涨一两个点。python detect.py \ --weights runs/train/car_exp1/weights/best.pt \ --source test_images/ \ --augment \ --conf 0.3--augment就是开 TTA。如果还不够训两个不同 backbone 的模型比如yolov5s和yolov5m推理时用加权框融合WBF合并结果。这个在车辆检测里很实用因为不同模型对遮挡和远距离小车的敏感度不一样。6.2 针对小目标和遮挡的调参车辆检测里远距离小车和遮挡是两大难点。小目标可以把imgsz提到 1280但显存和速度代价大。更划算的做法是在hyp里调anchor_t让 anchor 匹配更宽松或者用--img 640训练但推理时用--img 1280yolov5 支持训练和推理尺寸不同。遮挡问题靠数据增强缓解hyp里的mixup和copy_paste可以开大一点。如果数据集里遮挡样本少可以手动合成一些把车辆抠图贴到复杂背景上但要注意贴图后的标注要同步生成。6.3 验证精度提升是否真实调完参数别只看 mAP 数字要分场景看。把验证集按白天/夜间、近距/远距、单车/拥堵分组分别算精度。如果整体 mAP 涨了但夜间精度降了说明调参偏向白天场景实际部署会出问题。我一般会写个脚本按文件名前缀分组统计或者用val.py输出每张图的预测结果再自己分析。python val.py \ --weights runs/train/car_exp1/weights/best.pt \ --data car_dataset.yaml \ --img 640 \ --save-json \ --project runs/val--save-json会输出 COCO 格式的预测结果方便后续用 pycocotools 做细粒度分析。6.4 我踩过的最后一个坑有次我训完模型mAP 0.85 看着不错部署到实际场景却频繁漏检。回头查发现验证集里全是清晰近景车实际场景是俯拍远距离小车分布完全不对。后来我把验证集换成实际场景抽帧mAP 掉到 0.6但重新调参训完实际效果反而好了。数据集和验证集的场景匹配比刷高 mAP 重要得多。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?