
简介本资源为面向YOLO系列目标检测算法的工程机械数据集包含自卸卡车、挖掘机、轮式装载机三类目标适合从事智慧工地、矿山监控、工程车辆识别等方向的研究者与开发者直接用于模型训练与验证。压缩包共2000个文件以VOC格式的xml标注文件为主同时提供YOLO格式的txt标签两种标注分别存放于独立文件夹文件名末尾标注对应类别名称便于快速区分与调用。资源已按训练与验证需求划分完毕并附带data.yaml配置文件可无缝适配YOLOv5、YOLOv7、YOLOv8、YOLOv9、YOLOv10及YOLO11等主流版本。YOLO标签采用归一化中心点与宽高格式坐标范围0到1方便直接读取训练。整包约232.47MB内含2656张图像及对应标签目前已有82人学习下载。读者可获得开箱即用的数据集结构与配置省去标注与划分环节将精力集中于模型调参与效果对比。1. 挖掘机数据集与 YOLO 训练从 2656 张图像到可用的工地目标检测器手头拿到一个标注好的工程机械数据集2656 张图像三个类别自卸卡车、挖掘机、轮式装载机。这种规模的数据集在工业检测场景里不算大但足够训练一个能落地的 YOLO 模型。问题在于很多人拿到数据集后直接model.train()一把梭结果 mAP 卡在 0.5 上不去或者某一类几乎检测不出来。这篇笔记围绕这个数据集把 YOLO 训练的完整链路拆开讲——从数据检查、格式转换、参数配置到训练后的排查每一步都给出可复现的操作和参数含义。适合已经跑过 YOLO 官方 demo、但第一次用自己数据集训练的工程师也适合想了解工程机械检测这个方向值不值得投入的从业者。2. 先搞清楚数据集的底子2656 张图像里藏着什么2.1 三个类别的分布决定了训练策略拿到数据集的第一件事不是写训练脚本而是统计类别分布。自卸卡车、挖掘机、轮式装载机这三个类别的实例数量往往不均衡。挖掘机通常是工地场景的主角标注框最多轮式装载机可能只在部分图像中出现实例数偏少。如果直接按默认配置训练少样本类别很容易被模型忽略。用下面这段脚本快速统计每个类别的实例数和图像数import os from collections import Counter from pathlib import Path # 假设标签是 YOLO 格式的 txt 文件每行 class_id x_center y_center w h label_dir Path(labels/train) class_names [dump_truck, excavator, wheel_loader] class_counter Counter() image_with_class Counter() for txt_file in label_dir.glob(*.txt): with open(txt_file, r) as f: lines f.readlines() classes_in_image set() for line in lines: cls_id int(line.strip().split()[0]) class_counter[cls_id] 1 classes_in_image.add(cls_id) for c in classes_in_image: image_with_class[c] 1 for i, name in enumerate(class_names): print(f{name}: 实例数{class_counter[i]}, 出现图像数{image_with_class[i]})这段代码的逻辑很直接遍历所有标签文件统计每个类别的总实例数和出现在多少张图像中。参数方面label_dir指向训练集标签目录class_names的顺序必须和data.yaml里的names一致否则统计结果会张冠李戴。如果发现某个类别的实例数不到总数的 10%就需要在训练时考虑类别权重或者过采样。2.2 图像尺寸和标注质量检查2656 张图像的来源可能比较杂分辨率不统一。YOLO 训练时默认会 resize 到 640×640但如果原图长宽比差异太大resize 后目标会变形。先统计一下图像尺寸分布from PIL import Image import numpy as np image_dir Path(images/train) sizes [] for img_path in image_dir.glob(*.jpg): with Image.open(img_path) as im: sizes.append(im.size) sizes np.array(sizes) print(f宽度范围: {sizes[:,0].min()} - {sizes[:,0].max()}, 均值: {sizes[:,0].mean():.0f}) print(f高度范围: {sizes[:,1].min()} - {sizes[:,1].max()}, 均值: {sizes[:,1].mean():.0f})如果宽度和高度均值相差不大说明图像大致是方形或接近方形直接 resize 问题不大。如果长宽比普遍是 16:9 甚至更宽建议在data.yaml里设置rectTrue开启矩形训练减少 padding 带来的无效计算。标注质量方面重点检查两类问题一是标注框超出图像边界二是同一目标被重复标注。YOLO 格式的坐标是归一化的如果x_center ± w/2超出 [0,1] 范围训练时虽然不会报错但会导致定位损失异常。写个简单的校验脚本def validate_label(txt_path): issues [] with open(txt_path) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: issues.append(f第{i}行字段数不对: {len(parts)}) continue cls_id, x, y, w, h map(float, parts) if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): issues.append(f第{i}行坐标越界: {x:.3f} {y:.3f} {w:.3f} {h:.3f}) if x - w/2 -0.01 or x w/2 1.01: issues.append(f第{i}行水平方向超出图像) if y - h/2 -0.01 or y h/2 1.01: issues.append(f第{i}行垂直方向超出图像) return issues这个校验函数返回的问题列表可以直接打印出来逐条人工确认。常见的情况是标注员在图像边缘画框时稍微超出了几个像素这种一般可以接受但如果超出比例超过 5%就需要修正或丢弃该标注。3. 把数据集喂给 YOLO格式转换与配置文件3.1 从原始标注到 YOLO 格式的转换数据集自带的标签格式可能是 VOC XML、COCO JSON 或者 LabelImg 生成的 XML。YOLO 训练需要的是每张图像对应一个 txt 文件每行格式为class_id x_center y_center width height全部归一化到 [0,1]。以 VOC XML 为例转换脚本如下import xml.etree.ElementTree as ET from pathlib import Path def voc_to_yolo(xml_path, output_dir, class_map): tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.findall(object): cls_name obj.find(name).text 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) x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) out_path Path(output_dir) / (Path(xml_path).stem .txt) with open(out_path, w) as f: f.write(\n.join(lines)) class_map {dump_truck: 0, excavator: 1, wheel_loader: 2} for xml_file in Path(annotations).glob(*.xml): voc_to_yolo(xml_file, labels/all, class_map)转换逻辑的核心是坐标归一化VOC 用的是绝对像素坐标(xmin, ymin, xmax, ymax)YOLO 需要的是归一化后的中心点和宽高。class_map的键必须和 XML 里的name字段完全一致包括大小写。转换完成后建议随机抽 5 张图像用可视化脚本画框确认避免坐标计算错误导致框偏移。3.2 data.yaml 的关键字段与路径陷阱YOLO 训练依赖一个data.yaml文件描述数据集结构。典型配置如下path: /home/user/excavator_dataset train: images/train val: images/val test: images/test names: 0: dump_truck 1: excavator 2: wheel_loader这里有几个容易翻车的点。path必须是绝对路径或者相对于训练脚本运行目录的路径。train、val、test是相对于path的子路径不是绝对路径。如果写成绝对路径YOLO 会拼接出错。另外names的键必须是整数且从 0 开始连续不能有跳号。如果类别名里有空格或特殊字符用引号包起来。提示划分训练集和验证集时不要随机打乱所有图像再按比例分。工地场景的图像往往来自连续视频帧相邻帧高度相似。随机划分会导致验证集里出现和训练集几乎一样的图像mAP 虚高。正确做法是按视频片段或拍摄批次划分确保验证集的场景和训练集有差异。4. 训练参数怎么设从 batch size 到数据增强4.1 显存和 batch size 的平衡2656 张图像在 YOLO 训练里属于小数据集通常 100 到 300 个 epoch 就能收敛。但 batch size 的设置直接影响训练稳定性和显存占用。以 YOLOv8 为例在 8GB 显存的显卡上640 分辨率、batch size 设为 16 通常能跑起来如果显存不够YOLO 会自动调整但手动设置更可控。yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs200 \ imgsz640 \ batch16 \ patience50 \ device0 \ workers4 \ projectexcavator_runs \ nameexp01参数逐个说modelyolov8n.pt用的是 nano 版本参数量小适合快速验证。如果 mAP 不达标再换yolov8s.pt或yolov8m.pt。patience50表示 50 个 epoch 内验证指标没有提升就早停避免过拟合。workers4是数据加载的进程数设太大反而会拖慢训练一般设为 CPU 核心数的一半。4.2 数据增强参数的调整逻辑YOLO 默认开启 mosaic、mixup、HSV 增强等。对于工程机械检测有些增强要关掉或调小。比如mixup会把两张图像按透明度叠加工地场景里挖掘机和自卸卡车经常同时出现mixup 可能导致类别混淆。建议把mixup设为 0.0 或 0.1。mosaic增强把四张图拼成一张对小数据集有正则化效果可以保留但close_mosaic设为最后 20 个 epoch 关闭让模型在真实分布上微调。yolo detect train \ datadata.yaml \ modelyolov8s.pt \ epochs200 \ imgsz640 \ batch16 \ mixup0.0 \ mosaic1.0 \ close_mosaic20 \ hsv_h0.015 \ hsv_s0.7 \ hsv_v0.4 \ degrees0.0 \ translate0.1 \ scale0.5degrees0.0是因为工地场景里挖掘机不会倒着开旋转增强反而引入不真实的样本。scale0.5允许目标缩放模拟不同距离下的拍摄效果。hsv_h调小到 0.015因为工程机械的颜色黄色挖掘机、白色装载机是重要特征色相变化太大会让模型学不到颜色线索。5. 训练完别急着部署验证与排查的五个坑5.1 坑一mAP 看着不错但实际漏检严重现象验证集 mAP0.5 达到 0.85但拿几张新图像测试挖掘机漏检明显。原因通常是验证集和训练集分布太接近模型过拟合了训练场景。解决方法是重新划分验证集确保验证集包含不同光照、不同角度、不同背景的图像。如果数据集本身场景单一可以考虑用外部图像做交叉验证。5.2 坑二轮式装载机被识别成自卸卡车现象混淆矩阵显示轮式装载机和自卸卡车之间有大量误判。原因在于这两个类别在远距离或遮挡情况下外观相似都是大型工程车辆。解决方法是增加这两个类别的区分性样本或者在损失函数里对这两个类别的分类损失加权。YOLOv8 支持在data.yaml里设置cls_weights但更直接的办法是检查标注确认没有把装载机标成卡车。5.3 坑三训练 loss 震荡不收敛现象box_loss 和 cls_loss 在训练前期剧烈震荡甚至发散。原因可能是学习率太大或者 batch size 太小导致梯度噪声大。解决方法是把初始学习率从默认的 0.01 降到 0.001同时开启cos_lr余弦退火。如果显存允许把 batch size 翻倍。5.4 坑四推理时框重叠严重现象一张图里同一个挖掘机出现多个重叠的检测框。原因是 NMS 的 IoU 阈值设得太高或者模型对同一目标输出了多个高置信度预测。解决方法是在推理时把iou参数从默认的 0.7 降到 0.5同时检查训练时conf阈值是否设得太低。5.5 坑五导出 ONNX 后精度下降现象PyTorch 模型 mAP 0.85导出 ONNX 后掉到 0.78。原因通常是导出时的动态轴设置不对或者预处理和后处理不一致。解决方法是导出时指定dynamicFalse固定输入尺寸并确保 ONNX 推理时的归一化参数和训练时一致。yolo export modelexcavator_runs/exp01/weights/best.pt formatonnx imgsz640 dynamicFalse simplifyTruesimplifyTrue会调用 onnx-simplifier 优化计算图减少冗余算子。导出后用 onnxruntime 跑一遍验证集对比 PyTorch 的输出确认精度损失在可接受范围内。6. 小数据集提点技巧从 2656 张里榨出更多信息6.1 用预训练权重做领域适配YOLO 官方提供的预训练权重是在 COCO 上训练的COCO 里没有挖掘机、自卸卡车这些类别但底层特征边缘、纹理、形状是通用的。加载yolov8s.pt做初始化比从头训练收敛快得多。如果数据集里某些类别和 COCO 里的卡车、公交车有相似之处迁移效果会更明显。from ultralytics import YOLO model YOLO(yolov8s.pt) model.train( datadata.yaml, epochs200, imgsz640, batch16, freeze10, # 冻结前10层只训练检测头 lr00.001, cos_lrTrue )freeze10冻结 backbone 的前 10 层这些层学的是通用特征不需要大幅调整。lr00.001比默认值小因为预训练权重已经很好大学习率会破坏已有的特征表示。训练 50 个 epoch 后可以解冻所有层用更小的学习率微调。6.2 用测试时增强提升推理精度如果部署环境对速度要求不高可以在推理时开启 TTATest Time Augmentation。YOLO 支持augmentTrue会对每张图像做翻转、缩放等变换然后融合多个预测结果。代价是推理速度降低 2 到 3 倍但 mAP 通常能提升 1 到 3 个百分点。results model.predict( sourcetest_images/, augmentTrue, conf0.25, iou0.5, imgsz640 )conf0.25是置信度阈值低于这个值的框会被过滤。iou0.5是 NMS 的 IoU 阈值控制重叠框的合并程度。这两个参数需要根据实际场景调工地场景里目标较大conf可以设到 0.3 以上减少误检。6.3 一个我踩过的坑别在验证集上调参刚开始做这个数据集时我习惯在验证集上试不同的学习率和增强参数看到 mAP 涨了就保留。结果模型在验证集上表现很好但换一批新图像就崩了。后来才意识到验证集被我用成了第二个训练集。正确的做法是从训练集里再切出一部分作为test集调参只看val最终评估只看test。test集在调参过程中绝对不能碰。这个习惯帮我省了很多后悔药。现在每次拿到新数据集第一件事就是按 7:2:1 划分 train/val/test然后锁死 test 集直到最后一步才用它跑一次评估。希望帮到你。本文还有配套的精品资源点击获取