
简介工程机械识别数据集针对目标检测任务构建面向深度学习者与算法工程师解决施工场景中挖掘机、装载机、自卸卡车、移动起重机、压路机、推土机、平地机等七类设备的自动识别问题适合YOLO系列、Faster RCNN、SSD等模型训练与验证。资源共2000个文件以txt标签文件为主内含一份yaml类别配置文件压缩包大小约361.74MB配套图片与txt、xml格式标注且已划分好训练集、验证集和测试集可直接接入YOLOv5至YOLOv10等主流框架使用。数据包含6338张真实场景图片既可用于模型效果对比也可用于算法调参与部署落地。资源还附带指定类别信息的yaml配置省去手工编写配置与格式转换的时间。目前已有308人学习适合有目标检测基础并希望使用现成工程机械数据快速开展实验的开发者。1. 工程机械识别数据集在施工安全场景里的位置工地的视频监控里挖掘机、渣土车和塔吊通常不是画面主角机位架在围挡高处几十米外的设备在1080p帧里只有三四十像素见方扬尘、夜间红外噪点和钢丝绳遮挡还会进一步吃掉轮廓。此时把目标检测模型从COCO换到专用权重上涨点不如先把训练数据做对。工程机械识别数据集要做的就是补上这个空缺把施工场景里的挖掘机、装载机、压路机等设备框出来、命好名、整理成目标检测框架能直接消费的标注格式。它适合做智慧工地监管、施工安全监测、无人机巡检和矿山无人化的算法团队。这些人碰到的第一道坎往往不是网络结构而是数据从哪来、类别怎么定、标注按什么规范做才不返工。2. 工程机械类别规划与图像采集策略2.1 类别体系怎么定按机种还是按作业状态类别是数据集的骨架也是后面一切标注成本的上限。直接照搬工程机械分类标准会把类别数撑到十几个检测难度和标注成本都会失控。常见做法是只保留工地高频出现的机种再按作业状态细分。下表是一套容易落地的六类划分类别标签名典型形态履带式挖掘机excavator履带底盘、长工作臂、驾驶室在履带一侧轮式装载机loader前端铲斗、铰接车身、底盘为轮胎推土机bulldozer前方宽铲刀、履带底盘压路机roller前后大钢轮、无长臂结构汽车起重机crane_truck伸缩臂、行驶时有支腿收拢自卸车dump_truck后方液压货斗、车架较高选类别的核心判断是应用场景。只做设备禁区报警六类足够要区分挖掘机改装破碎锤和标准挖斗就需要加“破碎锤状态”这个维度但代价是同类设备不同工况之间必须单独补样本。反过来如果强行把履带式和轮式挖掘机分成两类工地俯视线里两者正面轮廓几乎一样检测器很难分开标注一致性也会被打穿。以我接触过的目标检测项目类别粒度宁可粗一点先把稳定可分的机种做扎实再用第二级分类器去细分工况。2.2 采集渠道监控机位、无人机航拍与互联网图像工程机械识别数据集和通用目标检测数据集最大的差别在视角分布。COCO里的挖掘机多是平视特写而工地部署的摄像头一般在围挡高处往下看目标同时带俯仰角和小尺度两种特性。采集时要覆盖三个渠道固定机位监控画面用来对齐真实部署场景无人机航拍画面俯视角更高能补足远距离小目标样本互联网图片则用来补充平视角和不同涂装的颜色多样性但只作为辅助不能让这类构图占比太高否则模型对俯视场景的适应性会变差。如果有精力公开的施工安全数据集也可以作为类别分布和视角规划的参考但直接复用时要注意拍摄设备和机位差异。每个类别的多样性不能只按张数算要按场景数算。我一般会在采集表里加几列约束每个类别至少来自100个不同施工场景同一场景内连续帧抽帧间隔不少于2秒避免训练集被高度相似的相邻帧刷屏目标短边尽量覆盖16像素到512像素的区间因为工程机械在监控里经常是典型的小目标全是近景大目标会让模型对远景设备失明。夜间的红外模式、雨天反光、扬尘浓度高这三个状态单独建文件夹记录后面分析模型掉点原因时能直接对照。2.3 标注规范与最小目标过滤标注规范要提前写成一页纸再开工否则多人协作时会出现“同一个模糊目标这个人标那个人不标”的反复返工。常见做法是目标被遮挡超过70%不标两辆设备紧贴时边框允许轻微重叠但不能互相吞并阴影不纳入检测框目标短边小于阈值时过滤。这里给一个按短边阈值过滤 XML 标注的脚本适合刚转完 VOC 格式、还没清洗标注的阶段import xml.etree.ElementTree as ET def filter_small_objects(xml_path: str, min_side: int 20) - None: tree ET.parse(xml_path) root tree.getroot() for obj in root.findall(object): box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) if min(x2 - x1, y2 - y1) min_side: root.remove(obj) tree.write(xml_path, encodingutf-8)min_side 怎么定要看部署相机的分辨率。如果1080p画面里目标最短边经常小于20像素且业务还必须要识别那正确方向是把原始帧切块放大而不是把这些框直接丢掉只有在业务只关心中近距离报警时过滤小框才能帮模型收敛得干净。过滤前后分别统计一次每张图片的标注数量防止某个场景被整体误删。注意规范里要写明是否区分“停靠”和“作业中”两种状态。工程机械作业时机械臂形态变化剧烈如果只标停靠状态训练完会对作业姿态大量漏检。3. 从标注文件到YOLO训练集的格式转换标注工具最常见的输出是 VOC XML 和 COCO JSON而 yolov5、yolov8 原生训练要吃 YOLO txt 格式。格式转换看起来是体力活但坐标系的坑会让前面所有标注工作报废这一章把转换逻辑和数据划分一起讲清楚。3.1 标注格式对比VOC XML、COCO JSON 与 YOLO txt格式坐标表示常见来源典型注意点VOC XML绝对像素 x1,y1,x2,y2LabelImg类别名在name节点可能带中文COCO JSON绝对像素 x,y,w,hRoboflow、CVATannotations 里可能有 segments 字段转换时忽略YOLO txt归一化 cx,cy,w,hyolov5/yolov8类别 id 从 0 开始一行一个目标VOC 和 COCO 的差别不只是字段名COCO 的 bbox 是左上角和宽高YOLO 要求的是中心点和宽高而且全部要除以图像宽高做归一化。图像尺寸在 XML 里由 size 节点提供COCO JSON 则在 images 数组里拿错尺寸会把标注映射到错误位置。有云端标注经验的可以对比 COCO 2017 数据集结构的组织方式本质上都是把逐张图片的标注汇总成一个大的 JSON 字典。3.2 Python 脚本VOC 转 YOLO txt 并完成数据集划分下面是工程里能直接改用的转换脚本。它先读 XML把标签映射成类别 id再输出与图片同名的 txt 文件最后按视频片段划分 train/val。import random import xml.etree.ElementTree as ET from pathlib import Path CLASSES [excavator, loader, bulldozer, roller, crane_truck, dump_truck] def voc_xml_to_yolo_txt(xml_path: str, label_dir: str) - None: 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): name obj.find(name).text.strip() if name not in CLASSES: continue box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) cx ((x1 x2) / 2) / img_w cy ((y1 y2) / 2) / img_h bw (x2 - x1) / img_w bh (y2 - y1) / img_h lines.append(f{CLASSES.index(name)} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) Path(label_dir).mkdir(parentsTrue, exist_okTrue) out_path Path(label_dir) / (Path(xml_path).stem .txt) out_path.write_text(\n.join(lines), encodingutf-8) xml_files sorted(Path(annotations).glob(*.xml)) for xml_file in xml_files: voc_xml_to_yolo_txt(str(xml_file), labels)代码逻辑分三段先解析 size 字段拿到图宽高再把每个 object 的绝对坐标换算成归一化的中心宽高最后批量写出 txt。换算时注意算完宽高后要保持浮点精度保留6位小数足够。txt 文件名称必须和图片名称完全一致目录再分成 labels/train 和 labels/val。数据划分比转格式更容易被忽视。如果视频数据是按帧抽的直接对 xml 文件做随机 shuffle 会把同一台挖掘机的相邻帧同时分到训练集和验证集模型相当于见过目标后再考一次val 的 mAP 虚高上线必翻车。正确做法是先按视频片段 ID 分组完整片段落入 train 或 val再用固定随机种子切一次 80/20# 文件名形如 site01_clip03_000123.jpg取前两段作为片段ID video_ids sorted({_.join(f.stem.split(_)[:2]) for f in xml_files}) random.seed(42) random.shuffle(video_ids) train_count int(len(video_ids) * 0.8) train_videos set(video_ids[:train_count]) val_videos set(video_ids[train_count:]) for xml_file in xml_files: vid _.join(xml_file.stem.split(_)[:2]) split train if vid in train_videos else val voc_xml_to_yolo_txt(str(xml_file), flabels/{split})按片段划分的价值在于验证集更接近真实部署——部署时模型面对的永远是新场景、新工地不可能和训练视频有连续帧。划分完成后统计一下两边每类目标的框数量如果装载机在 val 里只有几十个框评估指标没意义应该在采集阶段补样本。3.3 目录结构与 data.yaml目录结构dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yamltrain: dataset/images/train val: dataset/images/val nc: 6 names: 0: excavator 1: loader 2: bulldozer 3: roller 4: crane_truck 5: dump_truckdata.yaml 里的 names 顺序必须和转换脚本里的 CLASSES 一致名称错位会在训练时出现“标签是第一类但模型学成第二类”的问题。路径建议写相对 dataset 根目录的形式训练命令在根目录执行避免换机器后绝对路径失效。另外不要用中文做类别名或文件名yaml 解析和多框架兼容性都会出问题。4. 工程机械识别模型训练与小目标优化4.1 训练环境与显存需求yolov8 训练自己的数据集需要用到 GPU 吗训练阶段强烈建议 GPU纯 CPU 训练一个几百张图的工程机械数据集要几小时迭代实验根本跑不动推理阶段 CPU 可以顶住但工地如果有多路视频流还是建议 GPU 做批量推理。显存需求由模型规模、输入分辨率和 batch 共同决定工程机械数据经常需要开高分辨率这里给一组参考值配置显存占用参考适合场景yolov8s imgsz640 batch16约8GB快速验证类别少yolov8m imgsz640 batch16约12GB中大规模数据集yolov8s imgsz1280 batch8约14GB小目标多的场景yolov8x imgsz1280 batch8约24GB以上追求上限训练慢分辨率从640提到1280后输入面积变成四倍显存开销按面积倍数上涨而小目标 AP 的提升往往抵消不了训练时间的增加。初版训练建议从640开始看清混淆矩阵后再决定要不要升分辨率。4.2 训练参数imgsz、epochs、anchors 与多尺度启动命令yolo detect train \ modelyolov8s.pt \ datadata.yaml \ imgsz640 \ batch16 \ epochs200 \ patience30 \ scale0.5 \ hsv_h0.015 \ hsv_s0.7 \ hsv_v0.4参数说明model 用预训练权重而不是随机初始化工程机械在 COCO 里类别少但底层纹理和边缘特征仍然有效imgsz640 是起步值epochs 给 200 轮配 patience30 做早停数据集小的时候模型很快收敛早停能避免过拟合到某个场景的涂装颜色。scale0.5 是缩放增强范围工地监控中目标尺寸跨度大这个值不建议关。hsv_h、hsv_s、hsv_v 控制色调、饱和度和明度抖动施工场景白天黑夜对比强烈适度抖动能提升光照鲁棒性。yolov5 训练自己的数据集也是同一套流程差别只在命令行参数名比如 yolov5 用--img 640 --epochs 200训练逻辑没有本质区别。再提醒一个锚框问题yolov5 和 yolov8 在训练时会自动从标注里重新聚类 anchors自建数据集的框比例和 COCO 差得很远这一步保留自动计算就行不要手动沿用 COCO 的预设锚框。数据集规模越偏这个影响越明显尤其是塔吊这种长宽比极端的目标。4.3 小目标检测、遮挡和类别不均衡的处理策略工程机械识别数据集里最影响落地的是小目标检测。一个画面里 16 像素的挖掘机检测器和人眼一样只能看到一小团纹理完全靠提高输入分辨率性价比太低。常见的处理路径有三条。第一是图像切片把 1080p 原始图像切成有重叠的 patchpatch 尺寸常用640步长用320到512重叠部分保证跨 patch 的目标至少在一个 patch 里完整。切片后目标短边等效放大小目标 AP 会直接提升推理时也要走同样的切片流程否则训练和部署不一致。第二是 copy-paste 增强把标注好的挖掘机区域抠出来随机贴到没有设备的背景上背景来自同一批采集数据即可。这对小目标数量提升非常明显但要注意把设备贴在天空或围挡顶部这类不可能出现的区域否则模型会学出错误的上下文依赖。第三是类别加权装载机、压路机这类数量少的类别可以按 1:2 或 1:3 的采样权重过采样不要为了均衡把挖掘机的样本砍掉一半数据集的多样性本来靠多数类撑起来的。遮挡问题不要只依赖自然样本。工地里钢丝绳、围挡和来往人员会频繁遮挡设备标注时把被遮挡但可见部分按实际边界框标出来训练时用随机遮挡增强手法制造更多遮挡上下文。如果验证集里某个类别的 recall 明显低于其他类先看这类标注框数量占比再看夜间和雨天样本占比不要一上来就换损失函数。5. 从 mAP 到上线的迭代技巧5.1 正确读评价指标mAP0.5 与 mAP0.5:0.95工程机械识别属于目标检测评价体系沿用目标检测评价指标的通用配置。提交实验时最好同时看 mAP0.5 和 mAP0.5:0.95 两个值mAP0.5 衡量宽松条件下的检测能力和业务里“框住大概位置”的报警需求接近mAP0.5:0.95 更苛刻能反映出框位置的精度对后期做设备测距和轨迹跟踪的人更关键。单看总 mAP 会掩盖很多问题自建数据集一定要按类别看 AP。工程机械场景里挖掘机和自卸车样本多、AP 自然高压路机样本少、AP 通常被拉低。小目标 AP 低于大目标 AP 是正常现象但如果小目标 AP 只有大目标的一半还不到优先检查切片流程而不是堆模型参数量。5.2 硬样本挖掘与主动学习闭环第一版模型训练完成后把训练集里漏检和误检的样本捞出来回填标注迭代一轮效果往往比直接加深网络更明显。具体操作是用训练好的模型对未标注的原始视频帧做推理设置低置信度阈值0.3把得分在0.3到0.7之间的检测框导出成待确认列表交给标注员只确认这些区域。这些硬样本集中在扬尘遮挡、夜间红外和极端小目标这几个难点击中几轮之后数据集质量比均匀补数据提升更快。我还会把误检最高的背景类别单独截出来做负样本集比如围挡上的施工铭牌被误检成设备这类负样本对降低误报率的作用是纯标注正样本替代不了的。5.3 部署时的滑动窗口推理与结果合并高分辨率图像部署时可以沿用训练时的切片策略窗口预测的坐标是局部的合并时要加上窗口在原图中的偏移量def sliding_window_infer(model, image, patch_size640, stride512): h, w image.shape[:2] detections [] for y in range(0, h, stride): for x in range(0, w, stride): patch image[y:y patch_size, x:x patch_size] results model(patch, conf0.25, imgsz640) for box in results[0].boxes: x1, y1, x2, y2 box.xyxy[0].tolist() detections.append([x x1, y y1, x x2, y y2, float(box.conf[0]), int(box.cls[0])]) return detections这个简单实现会返回所有候选框但同一个目标在重叠窗口里会出现两次最后必须做一次 NMS 合并否则设备计数和轨迹跟踪都会翻倍。本地小项目可以用 cv2.dnn.NMSBoxes服务端用 torchvision.ops.nms。窗口切片和 NMS 合并完把每轮推理结果回写进待标注队列后续训练只围绕这些漏检和误检框补样本数据集的增长就会始终集中在当前模型最薄弱的部分。本文还有配套的精品资源点击获取