简介施工场景下的工程车辆类型识别数据集面向计算机视觉学习者、算法工程师与目标检测实践者适用于智慧工地、施工现场车辆分类、智能安防监控等任务场景。资源按YOLOv8标准格式整理涵盖装载机、搅拌车、挖掘机、拉土车等多类施工车辆标注图像标注信息完整可直接接入算法训练流程。该压缩包共2000个文件其中661张jpg图像提供多样化的正样本素材1338个txt文件记录每张图像对应的类别标签与边界框坐标另含1个yaml配置文件用于快速定义类别与数据路径信息。压缩包总大小约92.06MB整体结构清晰便于本地部署与快速调试。目前已有762人学习使用。借助这套标注数据读者可省去图像采集与人工标注的大量时间直接开展施工车辆识别模型的训练、验证与迭代也可参考其标注规范与目录组织方式迁移至其他工程机械检测场景。1. 先说结论工程车类型识别不是分类题是检测题做施工车辆、工程车类型识别最常见的误区是把它当成图像分类。真实工地里挖掘机和拉土车同框、装载机被沙堆挡住半截、搅拌车远到只有几十个像素——分类网络只能回答「图里有没有挖掘机」回答不了「挖掘机在哪、是不是越界作业」。所以这个方向的落地几乎都走 yolov8 目标检测先框出目标再判断类别一套检测框同时解决「在哪」和「是什么」。这篇笔记按照实际做过的路线把数据准备、训练参数、部署验证和踩坑点完整讲一遍适合智慧工地、毕业设计、渣土车监管这类需求的从业者照着复现。2. 工程车识别为什么选 yolov8从工地视觉约束反推选型2.1 施工场景对模型的三个硬约束遮挡、低对比度、多车同框工地画面的整体特点先说清楚固定机位的广角监控拍摄目标尺度变化很大一辆装载机近的时候可以充满画面远的时候只有 100 像素左右这类机械普遍有长臂结构作业中机械臂与车身颜色、与背景地面颜色混在一起而且工地扬尘大晴天逆光时整幅画面对比度低阴影里的设备几乎消失。我实际标数据时最直观的感受是挖掘机斗齿部分经常和土堆同色标注时要靠轮廓而不是颜色来判断边界。这些视觉约束排掉了几个常见思路。纯分类网络不输出位置精度再高也没法做区域违规判断传统图像处理方案比如 HOG 特征加 SVM 分类器在低对比度和强遮挡下特征鲁棒性不足只能识别干净背景下的标准角度两阶段检测器精度高但速度慢最典型的 Faster R-CNN 在工地监控这种多路并发场景里单路推理就要几十毫秒一拖四路摄像头时算力压力直接翻倍。相比而言yolov8 这类单阶段检测网络在精度和速度之间拿到了更划算的平衡。这里要具体说下 yolov8 相对之前 YOLO 系列的改动Backbone 用 C2f 结构替换了 C3同一层特征经过更多分支的梯度流动再融合对小目标的特征表达比 v5 版本更稳Head 从耦合检测头换成分离的 cls 分支和 reg 分支分类与回归损失不再相互干扰。做工程车识别时分离检测头带来的直接好处是遮挡场景下回归框和类别判断不会互相拖累——比如搅拌车的滚筒把车头挡住时回归分支还能把车身主体框住分类分支依然能给出搅拌车类别。从落地角度看工程车识别这个任务天然绑定目标检测框架yolov8 因为在数据格式、训练脚本、导出链路上的生态完整是当前最划算的起点。这也是标题里直接写「支持 yolov8」的原因数据集、训练脚本、推理脚本都围绕 yolov8 的格式生态封装后续做标注和训练都要按这个标准对齐。2.2 和传统方案与两阶段检测对比为什么偏选 yolov8方案位置能力小目标能力速度工程落地成本分类网络ResNet 等无弱快成本低但用途受限HOG SVM 传统视觉有但粗糙极弱快需要反复调特征鲁棒性差Faster R-CNN 两阶段强强慢训练复杂部署推理贵yolov8 单阶段强较强快生态完整导出部署顺畅工程车识别不是学术刷榜看的是「标注一次、训练一次、部署多路」的总成本。yolov8 的生态在这里的价值被不少人低估——它自带标签格式转换、训练时数据增强、导出 ONNX 和 TensorRT 的脚本这些在项目排期里都是实打实的工时。另一个角度是数据规模。工程车类别不像 COCO 那种 80 类通用物体公开的工地车辆数据本身少项目大多靠自标注几百到一千张图起步。小数据量下yolov8 预训练权重微调的收益比训练一个大而重的两阶段网络更明显。我试过用 COCO 预训练的 Faster R-CNN 在 500 张工地图上做微调收敛速度明显慢于 yolov8 同数据量下的表现推理阶段 CPU 上更是跑不动。2.3 yolov8 的 n/s/m/l 怎么选按算力和监控路数决定yolov8 按模型宽度和深度分为 n、s、m、l、x 五个档位实际项目里用到前四个。很多教程默认用 yolov8s但这事不绝对。决定用哪个档位先问两个问题跑在什么设备上实时性要求多高。如果是纯 CPU 服务器做离线批量识别yolov8n 单张 640 分辨率大概几十毫秒到一百多毫秒s 档要慢一到两倍如果有 GPU哪怕是一张消费级显卡s 和 m 档性价比最高。如果目标是边缘设备比如 Jetson 系列或 RK3588 这类通常 n 或 s 档加 INT8 量化才能保证多路实时。工程车识别场景有一个特殊性工地画面里真正需要检测的车辆密度不高很少出现几十辆车挤在一块的情况所以模型容量不用太大yolov8s 是多数情况下的默认起点。我的习惯是先用 s 档跑通一条线再把同一份数据集喂给 n 档和 m 档对比 mAP 与推理耗时用数据决定而不是拍脑袋。补一句网络结构的常识模型档位变化主要影响 C2f 模块的重复次数和通道数对输入分辨率并没有硬性要求。640 是官方默认建议不是强制值——这一点在第 5 章讲小目标时还会再展开。3. 数据集准备把工程车标注做成 yolov8 能吃的格式3.1 数据从哪来工地自有监控、公开数据与网络图的选择标准工程车数据没有现成的标准数据集多数项目从三个渠道凑。第一是工地自有监控截图这是最理想的数据因为拍摄角度、光线和灰尘环境都贴近真实部署场景缺点是得协调现场还得人工筛选。第二是公开的标注数据集比如一些开源平台上有建筑机械、挖掘机相关的小型数据集可以作为补充但要注意类别定义可能和项目对不上。第三是网络爬图配合手工清洗图片来源杂、尺寸乱筛选成本高而且有版权和隐私边界问题不建议作为主力数据来源。网络图有一个很隐蔽的坑就是水印。我见过一个翻车案例模型在工地实测时把远处广告牌上的 logo 当成了挖掘机因为训练数据里大量带水印图片的 logo 区域和挖掘机斗齿纹理混在一起了。清洗数据时的标准是只保留背景干净但目标完整、有遮挡但可辨认的图剔除带明显文字叠加、目标小于 32 像素、严重失真的图。对工程车这种专业设备图片数量不是第一优先级类别平衡和角度多样性才是。3.2 用 labelme 标注工程车标注规范与转换脚本yolov8 训练需要每张图片对应一个同名的 txt 文件内容是「class x_center y_center width height」坐标全部归一化到 0~1。手工标注最常用的工具 labelme 输出的是 json 格式坐标是绝对像素直接喂给 yolov8 不行要写转换脚本。标注时推荐用矩形框而不是多边形工程车这类目标外形接近矩形矩形框标注效率高类别边界也更清晰。转换脚本要注意的细节不少labelme 的 json 里 points 是顶点列表要归一成外接矩形shape_type 可能是 polygon、rectangle少数情况是 circle。rectangle 的 points 是两个对角点polygon 需要取所有点的 min/maxcircle 要取圆心加半径扩成 bbox。同时还要处理越界问题——标注时手抖把框画到图像外面很常见要裁剪到 [0,w] 和 [0,h] 范围内归一化后宽高为 0 的目标直接跳过。import json import os from PIL import Image def convert_labelme_json(json_path, image_dir, out_dir, class_map): # 读取 labelme 的 json 标注文件 with open(json_path, r, encodingutf-8) as f: data json.load(f) # 找到对应的图片并读取尺寸归一化坐标必须依赖原图大小 img_path os.path.join(image_dir, data[imagePath]) img Image.open(img_path) w, h img.size txt_name os.path.splitext(os.path.basename(img_path))[0] .txt lines [] for shape in data[shapes]: label shape[label] if label not in class_map: continue cls_id class_map[label] points shape[points] # 统一成外接矩形 if shape[shape_type] circle: x0, y0 points[0] r points[1][0] - x0 # 工程车标注用不到圆这里简写 x_min, y_min, x_max, y_max x0 - r, y0 - r, x0 r, y0 r elif shape[shape_type] rectangle: (x_min, y_min), (x_max, y_max) points[0], points[1] else: # polygon xs [p[0] for p in points] ys [p[1] for p in points] x_min, y_min, x_max, y_max min(xs), min(ys), max(xs), max(ys) # 越界裁剪防止标注框画出图片边界 x_min max(0, x_min) y_min max(0, y_min) x_max min(w, x_max) y_max min(h, y_max) if x_max - x_min 1 or y_max - y_min 1: continue # 归一化到 0~1yolov8 的 txt 格式要求 cx (x_min x_max) / 2 / w cy (y_min y_max) / 2 / h bw (x_max - x_min) / w bh (y_max - y_min) / h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) with open(os.path.join(out_dir, txt_name), w) as f: f.write(\n.join(lines)) return len(lines)这个脚本处理了 labelme 最常见的三种 shape_type。circle 那行的半径其实严格应该用欧氏距离而不是 x 坐标差工程车标注里用不到圆所以没展开绕。class_map 是类别到数字 id 的映射建议从 0 开始分配和后续 data.yaml 里的 names 顺序保持一致。转换完成后抽几张图把 txt 坐标画回图片上目检一遍这一步能发现「标注框整体偏移」「类别 id 错位」这类脚本 bug。3.3 类别文件与数据集划分按工地和时间段分别按帧随机分除了图片和 txt训练还需要一个 data.yaml 文件指定类别名称和训练验证目录。放在数据集根目录下# data.yaml 工程车识别类别配置 path: ./engine_data train: images/train val: images/val nc: 4 names: 0: loader # 装载机 1: mixer # 搅拌车 2: excavator # 挖掘机 3: dump_truck # 拉土车 / 渣土车然后是数据划分。最常见的错误是全局随机划分把同一段视频的相邻帧同时分进训练集和验证集。这样验证集和训练集高度相似训练出来的 mAP 虚高部署到新工地马上打回原形。正确做法是按视频片段划分如果数据来自不同工地、不同时段先按片段分组再从片段级别打散。import os import random from shutil import move src engine_data/images train_dir engine_data/images/train val_dir engine_data/images/val # 按文件名中的片段前缀分组同一片段只能进 train 或 val 之一 groups {} for name in os.listdir(src): vid name.split(_)[0] # 假设文件名格式为 site1_seg01_0001.jpg groups.setdefault(vid, []).append(name) items list(groups.items()) random.seed(42) random.shuffle(items) split_idx int(len(items) * 0.8) for vid, names in items[:split_idx]: for n in names: move(os.path.join(src, n), os.path.join(train_dir, n)) for vid, names in items[split_idx:]: for n in names: move(os.path.join(src, n), os.path.join(val_dir, n))注意 txt 文件也要跟着同步移动。如果训练集和验证集来自不同工地而数据总量较少还会出现类别分布倾斜比如训练集装载机 30 辆、验证集装载机只有 2 辆这时要先把每个类别单独统计一遍再划分。统计脚本自己写个循环就可以。mAP 大于 0.9 但实际漏检多的项目八成在划分这一步埋了雷。4. 训练与调参跑通 yolov8 的最小命令和必调参数4.1 环境准备ultralytics 包与预训练权重下载节奏环境搭建是 yolov8 项目里最容易被教程带偏的一步。常见做法是 conda 建一个 Python 3.9 或 3.10 的环境先按官网装对应 CUDA 版本的 PyTorch再执行pip install ultralytics。CPU 版本也能跑通整个流程只是训练速度慢一个数量级如果只是验证数据格式和数据划分用 CPU 跑几十轮也够用真正调参还是建议找个带 NVIDIA GPU 的机器。有两个容易卡住的点。第一个是 ultralytics 包默认联网下载预训练权重第一次训练时会在用户目录下建缓存网络不稳定时会卡在下载阶段。解决方式是提前把权重文件放到指定位置再开始训练# 提前把权重放到缓存目录再验证能否加载 mkdir -p ~/.cache/ultralytics # 把提前下载好的 yolov8s.pt 放到上面的目录中 python -c from ultralytics import YOLO; m YOLO(yolov8s.pt); print(权重加载成功)YOLO 构造函数会检查本地权重路径存在就直接加载不存在才触发下载。这一步跑通后面训练和导出都不会再因为权重问题来回折腾。第二个坑是 CUDA 版本和 PyTorch 不匹配常见表现是device0训练时报错或直接跑到 CPU 上。先跑一句python -c import torch; print(torch.cuda.is_available())返回 True 再开始。4.2 微调还是从头训练工程车数据量决定路线工程车识别几乎用不到从头训练。理由很直接yolov8 在 COCO 上的预训练权重已经学会了纹理、边缘、形状这类通用视觉特征挖掘机的履带纹理、搅拌车的滚筒形状这些底层信息在 COCO 的「卡车」「巴士」等类别里有部分重合。做迁移学习微调时直接全部层一起训练用较小的学习率很快就能收敛到可用水平。有一种情况会建议从头训练类别定义和通用物体差异极大且数据量达到数万张以上。工程车项目一般到不了这个量级硬从头训只会得到更低的 mAP 和更长的调试周期。微调时要不要冻结 Backbone 也是一个常见问题我的经验是小数据量下冻结 Backbone 能缩短训练时间但精度提升有限不冻反而让模型更快适应工地这种特殊光照分布。所以默认建议不冻结全层微调学习率从 0.01 起步。4.3 一次能复现的训练命令参数含义逐个说这是整套流程里最核心的一条命令可以直接复制改路径yolo detect train \ modelyolov8s.pt \ dataengine_data/data.yaml \ epochs100 \ imgsz640 \ batch16 \ patience20 \ workers4 \ lr00.01 \ optimizerauto \ device0参数逐个说清楚这些参数在工程车这类小数据集上几乎不需要大改参数建议值说明epochs100小数据集的起步值100 轮足够看出收敛趋势imgsz640yolov8 默认输入尺寸小目标场景需要加大见第 5 章batch1612G 显存跑 s 档没问题显存不足时 ultralytics 会自动降低patience20连续 20 轮验证指标不上升就早停能省大量时间workers4数据加载线程数Windows 下设 0 防报错lr00.01微调场景偏积极小数据量建议降一半用 0.005optimizerauto让框架沿用预训练权重自带的优化器配置device0指定 GPU 序号CPU 环境改成 cpu训练结束后模型会保存到runs/detect/trainN/weights/best.pt用下面命令做一次快速验证yolo detect val \ modelruns/detect/train/weights/best.pt \ dataengine_data/data.yaml \ imgsz640 \ batch32验证输出里有 mAP50 和 mAP50-95 两个指标。工程车识别场景主要看 mAP50因为部署时用的是置信度阈值而不是严格 IOU 要求。mAP50-95 对标注框的精细程度更敏感数据集中标注框偏大偏小都会有影响不必过分纠结。4.4 训练曲线里藏着数据问题loss 不高但检测烂怎么判训练完先打开runs/detect/trainN/results.png不需要额外写画图脚本yolov8 会输出损失函数曲线图。判断标准box_loss 和 cls_loss 同时稳步下降且 val 曲线不反弹基本正常val loss 先降后升而 train loss 还在降是过拟合数据量小或者增强强度不够两个 loss 从一开始就剧烈抖动先把学习率降到 0.001 重跑。有一种更隐蔽的情况loss 收敛得很漂亮但验证集 mAP 很低。这大概率是类别不平衡或标注框质量参差。工程车四类里拉土车样本通常最多、搅拌车样本最少类别不平衡时 mAP50 可能还行mAP50-95 会比较难看部署时搅拌车漏检率明显偏高。这类问题调参救不回来只能回第 3 章补数据。所以补数据、修标注要放在调参之前这条顺序能帮你少走弯路。5. 工程车识别踩坑记录从标注到部署的 5 个真实问题5.1 搅拌车漏检率高样本姿态单一现象训练集里搅拌车准确率很高一到验证集或现场搅拌车漏检率突然飙升。原因采集的搅拌车图片大多来自同一工地同一角度滚筒形状和车身颜色高度相似模型学到的其实是「那个角度的那个颜色」而不是「搅拌车」这个类别。属于样本多样性不够不是参数问题。解决去另一个工地或换时间段补拍重点覆盖不同拍摄角度、不同颜色搅拌车、空载和满载状态的滚筒形态。每个角度补几十张就能明显改善。如果实在拿不到新工地数据把已有图做高强度数据增强也能缓解但真实分布数据永远比增强更可靠。5.2 挖掘机和装载机互相误判类别定义没写死现象验证集上挖掘机和装载机经常互换一辆明明是挖掘机的车模型给出最高置信度的却是装载机。原因这两类车外观确实有相似处——黄色涂装、履带底盘、长臂结构监控俯拍角度下挖掘机动臂举起和装载机铲斗举起非常像。如果标注规范里只有「装载机就是前边有铲斗那种」这种模糊描述不同标注员会标出不一致的标签训练时类别边界就乱掉了。解决标注规范里把判定标准写死。看行走机构履带还是轮胎看动臂结构挖掘机是「大臂小臂挖斗」三段式折臂装载机是一个整体举升臂带铲斗看驾驶室位置挖掘机驾驶室在回转平台上装载机驾驶室在车体前部。把易混图片单独挑出来做二次人工复核。这条规则不写进代码但必须写进标注文档并培训标注员不然模型上线后误报会持续折磨你。5.3 小目标拉土车识别不到imgsz 和切片策略现象拉土车在监控画面远处目标只有 40 像素左右训练时 mAP 不低实际视频里完全漏掉。原因yolov8 在 640 输入下对 16×16 以下的目标特征很弱推理时远处的小车被下采样到近乎丢失。imgsz640 不是玄学是平衡计算量和感受野的默认值小目标场景可以直接调大。解决训练时 imgsz 设为 960 或 1280显存不够就减小 batch 腾空间或者把监控画面按 2x2 切块每块按原分辨率推理再合并结果本质上就是变相放大目标。切块推理会有重复检测需要按截图坐标裁剪回原图后做一次 NMS 合并。另一个做法是调低训练增强里的大尺度随机缩放别让模型在训练时反复看到被缩得很小的难例——这个细节极少有人提对提升小目标召回很有效。提示imgsz 同时作用于训练和推理两个阶段要保持一致。训练用 1280 部署用 640 会导致输入分布不一致精度反而下降。5.4 训练 loss 正常但验证 mAP 虚高数据划分泄漏现象训练过程的指标非常好看mAP 达到 0.95拿到另一路段实测完全不行。原因数据集划分用了全局随机同一段视频的相邻帧被拆进了 train 和 val。相邻帧之间相似度太高验证集基本等于训练集的抽样等于拿着答案考试。解决按视频片段划分同一段连续画面只能出现在一个集合里脚本在第 3.3 节已经写过了。这个 bug 的隐蔽之处在于数据来自大量不同工地时随机划分的危害会被稀释数据量越少、片段越长危害越大。所以补数据的同时要重新划分别在旧划分上继续训。5.5 导出 INT8 后精度崩溃校准集太敷衍现象训练好的 pt 模型 mAP 0.9导出 TensorRT 做 INT8 量化后 mAP 掉到 0.5 左右现场开始大量误报。原因INT8 量化的校准集随意用验证集的前几十张且这些图里某类车辆数量太少甚至没有。量化时统计的激活值分布偏了另一类特征被压缩到过窄的量化区间。量化掉点不是黑匣子大概率是校准集和量化参数的问题。解决单独制作校准集保证四类工程车各有代表性样本数量和姿态分布接近训练集校准图片数量控制在 100 到 300 张之间。如果量化后还是掉点改用混合精度策略或干脆用 FP16 推理。边缘设备上 FP16 往往已经够用INT8 只在算力真的吃紧时用。6. 部署与进阶从 best.pt 到工地监控的最后一步6.1 导出 ONNX一行命令加一个参数就够yolo export modelruns/detect/train/weights/best.pt formatonnx dynamicFalse opset12opset12 保证兼容大多数推理后端dynamicFalse 固定输入尺寸边缘设备上推理速度更快如果希望任意尺寸输入再开 dynamicTrue但会损失一点性能。导出后建议用 onnxruntime 跑一次推理和 pt 模型的输出对比确保结果一致再往下走。这一步能提前发现算子兼容问题别等部署到板子上再排查。6.2 边缘设备上的性能预期与验证节奏设备类型单帧推理耗时参考适合场景X86 CPU 服务器几十到两百毫秒离线批量、低帧率监控消费级 GPU几到十几毫秒在线实时多路并发Jetson Orin / RK3588 边缘盒十几到几十毫秒FP16/INT8现场一体机以上是相对范围具体数值取决于模型档位和输入分辨率。部署后先喂一张包含四类工程车的合成画面测一遍再上真实视频。直接上真实视频的话误报和漏检混在一起很难定位分层验证能省下大量排查时间。6.3 难样本回灌一个比调参更管用的日常习惯这是我做检测项目一直沿用的方法项目上线后收集一周的误检图把置信度低于 0.6 的目标剪出来人工确认后回灌到训练集做增量微调。一个工地几小时的监控数据就能挖出几百张难例补充标注后跑 50 个 epoch 再出一版模型。这样一轮比调一星期学习率有效得多。背后的逻辑在于工程车视觉模式相似度高黄色涂装、履带、长臂这些特征跨类别重叠模型方差最大的干扰来自外观接近但类别不同的目标这类问题只能回到数据层面解决。我之前吃过一次亏部署前只验证了标准场景结果新项目一开现场就漏检后来养成的习惯是「先导出模型、再针对新场景回灌数据、再验证」这个循环。整套流程跑下来你的工程车识别项目会从一个「能跑通」的状态变成一个「敢上线」的状态希望帮到你。本文还有配套的精品资源点击获取