ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

起重机目标检测实战:YOLO标注数据与YOLOv8训练全流程指南

起重机目标检测实战:YOLO标注数据与YOLOv8训练全流程指南 简介面向计算机视觉初学者、目标检测算法研究者及工地、港口等工业场景开发者这份起重机图像目标检测数据集包含约2900张已标注图片及对应标签类别仅起重机一类并已完成训练集与验证集划分采用YOLO标准标注格式可直接接入YOLOv5、YOLOv8等主流框架完成训练与评估。压缩包共2000个文件以txt标签文件为主标签与图片同名对应内容记录类别编号与归一化坐标另附一个py可视化脚本可快速核对标注框是否准确整体约146.53MB。数据集已按规范整理好目录省去自行采集、清洗与标注的时间既适合作为目标检测课程作业与入门实战数据也可用于检测模型改进实验的基准对比。目前已有498人学习下载对需要快速获得规范检测数据的研究者与开发者较为友好。1. 起重机图像目标检测数据先看清这 2900 张 YOLO 标注的底细在工地、港口这类场景做视觉落地遇到的第一道坎永远是数据。公开数据集里起重机类别占比低标注还常带着 VOC 那套 XML 转换的负担拿回来要先写脚本转成 YOLO 格式坐标换算一旦出错后面训练全部白费。这份约 2900 张已标注图像的起重机目标检测数据直接用 YOLO 标注格式等于把最容易翻车的格式转换环节省掉了。它适合做施工吊装区域的安全监测、港机自动化里的吊具识别以及起重机视觉检测方向的研究预实验。一句话定位它不是能直接部署的成品模型而是一份能快速喂进 YOLO 训练流程的现成标注数据你省下的时间应该花在调参和补样本上。2. 用 YOLO 训练起重机检测看懂标注格式、划分数据并生成 data.yaml拿到数据集先别急着开训练。一份标注数据能不能高效用起来取决于你对 YOLO 标注格式和目录结构的理解。所谓 YOLO 标注格式本质上是把每个目标框用「中心点 宽高」四元组描述并归一化到 0 到 1 区间标签文件是一个纯文本 txt每行一个目标。这个设计让数据集的搬运、切分和训练前的检查都变得非常简单。2.1 YOLO 标注格式归一化坐标与类别 ID 的换算逻辑YOLO 标签每行五个数class x_center y_center width height前四个数值都是相对图片宽高的比例。例如一张 1920×1080 的吊车照片某根大臂中心点落在像素坐标 (960, 600)框宽 768、高 216换算成归一化就是0 0.5 0.5556 0.4 0.2。图片被缩放或裁剪时这些比例值依然成立所以 YOLO 格式对训练时的随机缩放、拼接增强天然友好。和 VOC 的xmin ymin xmax ymax绝对像素坐标相比YOLO 格式最大的好处是不依赖外部 XML 解析一个 txt 就能完整描述一张图的全部目标。自己做数据集时用 LabelStudio 或 LabelImg 这类常用标注工具导出 YOLO 格式也很常见。拿到这份现成数据集后你要做的不是写转换脚本而是确认标签里的类别 ID 和归一化数值是否有越界这比处理 VOC 的 XML 省心得多也是这类「已标注、YOLO 格式」数据最直接的落地价值。# crane_0001.txt 内容示例类别0中心(0.4823, 0.4355)宽高(0.0987, 0.2431) 0 0.4823 0.4355 0.0987 0.2431这段示例说明一个很现实的问题约 2900 张数据里如果每张图只有一个目标训练信号其实非常稀疏如果多目标每张图就是多行。你要想清楚这个数据集标注的是单个吊车还是包含吊臂、吊钩、配重等多个部件这会直接影响后面nc的设置。2.2 标准目录结构images 与 labels 必须同名一一对应ultralytics 的训练器只认一套目录约定图片在images/train和images/val标签在labels/train和labels/val同名文件靠主文件名关联。比如images/train/crane_0001.jpg对应的标签必须是labels/train/crane_0001.txt后缀扩展名不要求一致但文件主名必须完全相同。这份约 2900 张的数据集拿到手先确认目录是不是长这样不是的话要按下面这个结构重新整理。crane_dataset/ ├── data.yaml ├── images/ │ ├── train/ │ │ ├── crane_0001.jpg │ │ └── ... │ └── val/ │ └── ... └── labels/ ├── train/ │ ├── crane_0001.txt │ └── ... └── val/ └── ...图片和标签要么都按images/labels分开放要么都放训练集目录别出现只有图片没有同名 txt 的情况。训练时这种不配对样本会被静默忽略但验证集会因此虚高——因为缺标签的难样本恰好不会计入误差这点在 4.1 里还会再提。2.3 数据划分脚本固定随机种子复制而不是移动如果原始数据是全部塞在一个images文件夹和一个labels文件夹里第一步是划分训练集和验证集。我一般会写死随机种子再洗牌这样每次运行得到同一个划分之后换网络、调参数做对比时结论不会被数据划分的随机性干扰。import os import random import shutil from glob import glob random.seed(42) img_src all_images # 原始图片目录 lab_src all_labels # 原始标签目录 out_dir crane_dataset # 输出根目录 imgs sorted(glob(os.path.join(img_src, *.jpg))) random.shuffle(imgs) val_ratio 0.15 val_n int(len(imgs) * val_ratio) splits { train: imgs[val_n:], val: imgs[:val_n], } for split_name, paths in splits.items(): img_out os.path.join(out_dir, images, split_name) lab_out os.path.join(out_dir, labels, split_name) os.makedirs(img_out, exist_okTrue) os.makedirs(lab_out, exist_okTrue) for img_path in paths: base os.path.splitext(os.path.basename(img_path))[0] lab_path os.path.join(lab_src, base .txt) shutil.copy(img_path, os.path.join(img_out, os.path.basename(img_path))) if os.path.exists(lab_path): shutil.copy(lab_path, os.path.join(lab_out, base .txt))这段脚本的逻辑是先把所有 jpg 路径读进来打乱前 15% 当验证集后 85% 当训练集再分别复制到输出目录。用shutil.copy而不是os.rename是为了保留原始一份数据划分错了还能重来。图片后缀不是 jpg 时要把 glob 里的通配符和 basename 处理一起改掉这是最容易漏的一处。如果原始数据里图片是 png 或 jpeg建议在脚本里统一匹配*.jpg、*.png两种后缀。2.4 生成 data.yamlnc 和 names 必须与标签严格一致训练前还要在数据集根目录放一个data.yaml告诉 YOLO 数据在哪、共几个类别、类别名是什么。单类别起重机数据写起来最简单但路径和类别编号不能写错否则训练器会一直报找不到图片或标签维度不匹配。path: /home/yourname/crane_dataset # 改成你本机实际路径 train: images/train val: images/val nc: 1 names: 0: cranepath字段是后续相对路径的根目录建议写绝对路径避免从不同目录启动训练命令时找不到文件。nc是类别数如果这份数据里标签最大类别 ID 是 0那nc: 1就是对的如果混入了第二类目标比如安全帽或行人nc要改成 2names列表也要补上对应名称。names的层级实际是给可视化用的但顺序错误会让你误以为模型分不清类别排查时很耽误时间。提示约 2900 张的规模验证集比例 15% 足够大约 400 张。不要因为担心过拟合就切 30% 出来验证小数据集上验证集太大会让 mAP 波动大到没法判断调参效果。3. 用 YOLOv8 训练起重机检测预训练权重、关键参数与数据集处理流程数据准备好了接下来进入正式训练。这里以 YOLOv8 为例因为它的训练命令和数据接口已经是当前最主流的习惯用法如果你更习惯 YOLOv5脑内翻译一下命令即可核心参数逻辑完全一样。训练时很多人的第一反应是换更大的模型但 2900 张的规模不足以喂饱大模型真正决定结果的是预训练权重选择、输入分辨率和增强策略。3.1 预训练权重怎么选n、s、m 三档的取舍YOLOv8 官方提供了 n、s、m、l、x 五档预训练权重文件名的语义是 nano、small、medium 等。对于约 2900 张的起重机数据我的建议是先跑通流程用yolov8n.pt确定数据没问题、指标曲线能正常下降后再换yolov8s.pt或yolov8m.pt提升精度。有一个高频疑问是「预训练模型下载到哪里」ultralytics 包在第一次调用时会尝试从官方仓库自动拉取对应.pt文件到当前项目目录不需要手动下载离线训练环境里更稳的做法是提前在联网机器上下好权重文件拷到离线机的项目目录再设置环境变量让训练器直接用这个本地权重。注意权重文件名必须与你在命令里写的一致否则 ultralytics 会尝试重新联网拉取然后卡在超时。3.2 训练命令与核心参数从 epochs 到 batch 的显存估算在数据集根目录执行下面的命令即可开始训练。以yolov8s.pt为起点跑 100 轮输入分辨率 640yolo train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch16 workers8 device0几个关键参数按落地场景这样调参数推荐值说明epochs100 起步先看 100 轮曲线再决定加不加小数据集跑 300 轮容易过拟合imgsz640起重机目标在画面里一般不算小但吊臂细长降到 416 会明显丢精度batch8~16显存不够优先降 batch不要在 4 和 8 之间反复横跳看玄学workers4~8Windows 建议不超过 4数据线程太多会拖慢而不是加快device0单卡训练写 0多卡写 0,1没有 GPU 就删掉 device 参数用 CPU 慢得能睡一觉lr00.005~0.01发现 loss 前几轮就爆炸先把它砍半输入分辨率是最被低估的参数。起重机的大臂往往细长低分辨率下细杆特征会被卷积反复压缩最后只剩一个模糊的亮条所以 2900 张数据训练宁可 batch 小一点也别把 imgsz 压到 416 以下。在 V100、A100 这类大显存卡上imgsz640加batch32没有任何压力显存只有 8G 时batch 16 配 640 也已经很极限。3.3 训练日志怎么看loss 曲线、mAP50 与过拟合判断训练结束后runs/detect/train目录下会留下results.csv和weights/里的last.pt、best.pt。不要只看最终 mAP 数字要用曲线确认训练过程是否正常。下面这段脚本可以把 loss 和 mAP 画出来import pandas as pd import matplotlib.pyplot as plt log pd.read_csv(runs/detect/train/results.csv) log.columns [c.strip() for c in log.columns] fig, axes plt.subplots(1, 2, figsize(12, 4)) axes[0].plot(log[epoch], log[train/box_loss], labeltrain box) axes[0].plot(log[epoch], log[val/box_loss], labelval box) axes[0].set_title(Box Loss) axes[0].legend() axes[1].plot(log[epoch], log[metrics/mAP50(B)], labelmAP50) axes[1].plot(log[epoch], log[metrics/mAP50-95(B)], labelmAP50-95) axes[1].set_title(mAP) axes[1].legend() plt.tight_layout() plt.savefig(training_curves.png)判断过拟合最直接的标准不是 train loss 有没有降到很低而是 val loss 是否在某个 epoch 后开始回升同时 mAP 曲线走平甚至下滑。best.pt是验证集上最优的权重部署、测试、导出都以它为准last.pt只管最后一步的状态只在你想继续训练时才用。代码里读的results.csv列名带括号和斜杠记得做 strip 去空格Windows 下偶发的列名带空格问题会在这里让你白报一个 KeyError。3.4 混淆矩阵总和为什么不是 1归一化方式的误读训练日志里有一张 confusion_matrix.png很多人第一次看会疑惑为什么矩阵所有格子加起来不是 1这不是 bug也不是模型出了问题。YOLO 的混淆矩阵默认按每个真实类分别归一化每一行的总和才是 1表示某个真实类别被预测到各个类别的比例因此整个矩阵的总和不唯一取决于类别数和背景类。看的时候重点看对角线够不够亮、有没有某个真实类被大面积分到另一列如果对角线很亮、背景列只有零星散布训练就基本健康。这个误读属于「热知识」查资料时你还会看到有人拿着总和不是 1 的截图发帖求助其实换个角度看矩阵就通了。真正需要警惕的反而是另一件事当验证集 mAP 很高但现场表现很差时先回去看混淆矩阵的背景列如果很多框落在背景上说明模型学到的是背景纹理而不是起重机的结构特征这在后面的部署阶段会吃大亏。4. 起重机标注数据训练的 4 个踩坑点越界、细长目标、BN 崩溃与光照这章写的都是这份数据以及同类细长目标数据集上我实际遇到的高频问题每条按「现象 → 原因 → 解决」展开踩过任何一个都能省下半天排查时间。4.1 现象loss 正常但 mAP 一直很低 → 标签归一化越界或零宽高训练曲线掉得很顺loss 也降到 0.03 附近但验证集 mAP50 一直卡在 0.2 到 0.4 上不去。这类情况我先怀疑标签文件而不是模型。YOLO 标签要求中心点坐标和宽高都归一化在 0 到 1 之间标签转换脚本一旦把像素坐标和归一化坐标混用就会出现框的一半在画面外、甚至中心点超出图片范围的情况。import os bad [] for root in [labels/train, labels/val]: for name in os.listdir(root): path os.path.join(root, name) with open(path) as f: lines f.read().strip().splitlines() if not lines: continue for line in lines: parts line.strip().split() if len(parts) ! 5: bad.append((name, f字段数不为5: {line})) continue cls_id, x, y, w, h map(float, parts) if w 0 or h 0: bad.append((name, f宽高非正: w{w} h{h})) if x - w / 2 0 or x w / 2 1 or y - h / 2 0 or y h / 2 1: bad.append((name, f越界: x{x:.4f} y{y:.4f} w{w:.4f} h{h:.4f})) print(异常标签数:, len(bad)) for item in bad[:20]: print(item)解决跑一遍上面的检查脚本把越界文件找出来用标注工具打开重新导出或者直接删掉这几张问题样本。注意不要只改数值不重新看原图越界往往说明原始框本身标歪了。判断越界用的是中心点加减半宽半高是否落在 0~1 区间比只看 w、h 是否小于 1 更严格。如果标签文件里额外带有置信度列先把字段数判断改成不小于 5再决定要不要保留那一列。4.2 现象mAP50 不差但 mAP50-95 很难看 → 大臂细长正框含太多背景起重机尤其是履带吊、塔吊目标形态是长长的桁架臂。模型在 mAP50 上表现尚可mAP50-95 却大幅下滑原因在于 IoU 阈值提高后水平矩形框和真实细长框的交并比迅速跌到阈值以下。起重机标注框的宽高比常常大于 5 比 1这种框天然不利于高 IoU 指标。解决思路有三条。第一接受现实把验收指标定为 mAP50工程上安全监控更看重「有没有框住」而不是「框得有多准」。第二把 imgsz 从 640 提到 768 甚至 960保持细长杆件的特征响应代价是显存和训练时间上升。第三在增强里加大水平翻转和轻微旋转让模型见到的长条框朝向更多样比无脑堆数据更有效。别指望旋转框检测模型来解决HBB 数据硬转 OBB 会引入一排新坑不是这个数据集的使用方向。4.3 现象训练中途 loss 变成 nan或 BN 层崩溃 → 学习率过大、标签异常或半精度不稳YOLO 训练中有一个高频词叫「BN 崩溃」表现为训练到某个 epoch 后 loss 突然变成 nan或者 val 指标断崖下跌。遇到这个现象先不要慌按顺序查三样学习率、标签、AMP 半精度。学习率在 0.01 以上配合小 batchBN 统计量容易爆炸标签里混入了 NaN 数值会让梯度直接变无效AMP 在某些显卡驱动上也有偶发不稳。解决的常见做法是先跑一遍 4.1 的标签清洗脚本然后把lr0降到 0.001batch 固定到 8 或 16最后加上ampFalse关闭半精度试 20 轮。如果关闭 AMP 后曲线稳定那就是驱动或 GPU 相关的问题可以尝试更新 CUDA 版本如果依然 nan回去检查数据增强里有没有把某个旋转角度设成把框旋出画面。小数据训练碰到这类问题十有八九是超参在极端区间游走把它拉回保守值通常一次见效。4.4 现象白天效果好傍晚和夜间漏检 → 光照多样性不足增强参数没跟上2900 张的数据如果大多来自白天模型在傍晚、逆光、夜间补光条件下会系统性漏检。这不是 YOLO 的问题是训练分布和现场分布的偏移。对比结果往往很反直觉白天样本 mAP 到 0.9夜间 mAP 直接腰斩。原因就是训练数据的光照分布过于单一模型没有后悔药可吃——它不能凭空学会没见过的亮度。解决办法先从数据侧入手把 HSV 增强里的亮度、饱和度通道打开。一般用hsv_h0.015、hsv_s0.7、hsv_v0.5起步如果现场确认以黄昏和夜间为主把hsv_v调到 0.6 以上同时搭配灰度化。第二选择是补一批夜间样本做半自动标注把第 5.4 节那套流程用起来。最忌讳的是盲目加大degrees旋转起重机本身朝向固定旋转过多只会教模型把地面认成吊臂。5. 训练完怎么验证和落地指标解读、ONNX 导出与半自动标注回灌训练只是前半场后半场是验证、导出和把这份数据集的价值继续放大。5.1 跑通验证命令conf 与 iou 阈值影响 mAP 高低用训练得到的best.pt在验证集上跑一轮验证命令如下yolo val modelruns/detect/train/weights/best.pt datadata.yaml conf0.25 iou0.5 imgsz640conf0.25是置信度阈值低于它的预测框会被过滤iou0.5是 NMS 去重的 IoU 阈值不是评估用的 IoU 标准。常见误用是把iou当作 mAP 计算时的 IoU 阈值去调结果指标忽高忽低还找不到原因。mAP50 计算的是预测框与真实框 IoU 超过 0.5 时的平均精度mAP50-95 则把 0.5 到 0.95 的阈值全部算一遍取平均。对起重机这种细长目标mAP50 更贴近工程需求mAP50-95 更严格也更难刷。验证输出里还会给每个类别的 Precision、Recall。安全监控场景更看重 Recall漏检一次可能出安全事故所以现场部署时conf调到 0.15 甚至 0.1 都可以误报多一些总比漏报好。反过来如果做的是库存统计这类自动化场景再拉高conf换取 Precision。5.2 导出 ONNXdynamic shape 与 opset 的边界验证通过后部署端最常用的导出格式是 ONNX。命令yolo export modelbest.pt formatonnx opset12 dynamicTrue halfTruedynamicTrue让模型接受任意宽高的输入起重机画面来自不同分辨率的球机这个开关会让部署灵活很多halfTrue导出 FP16 权重在支持 FP16 的推理框架上速度更快但如果目标设备不兼容会直接跑出 nan先在本地用onnxruntime验证一遍再发布。opset 版本不是越新越好得看部署环境支持哪个就导哪个比如老的 Jetson 镜像里 CUDA 和 TensorRT 版本陈旧opset 13 以上反而可能加载失败。这里多说一句部署脚本很多人找「一键部署脚本」但 ONNX Runtime 那十几行调用代码真不值得抄来抄去自己照着官方示例写一遍报错时一眼就能定位问题。数据集的活已经被人替你干完了部署这步还是自己过一遍心里有数。5.3 视频流与边缘设备推理从 RTSP 到板卡选型工地现场最普遍的接入方式是 RTSP 视频流推理命令和图片几乎一样yolo predict modelbest.pt sourcertsp://user:password192.168.1.10:554/stream1 conf0.4 device0这里conf建议从 0.4 起步因为视频流相邻帧高度相似误报会在时间维度上不断重复出现阈值太低会让告警刷屏。需要落地的算力平台从 Jetson Orin 到 X86 小主机都有2900 张数据训练出来的模型在边缘设备上真正要权衡的是在保 Recall 的前提下尽量用小模型和 FP16。如果你最后要下放到单片机级或更低成本的边缘板卡那模型档位基本只有 nano 可选验证策略就得从「mAP 多高」改成「每帧处理时间和漏检率能不能同时过关」。5.4 半自动标注把 unlabeled 图片变成第二批训练数据这份数据集只有约 2900 张想让它发挥更大价值最常见也最可靠的做法是用训练好的模型做半自动标注把现场新增的无标注图片变成第二批训练数据。流程很简单用best.pt去预测新图片保存 YOLO 格式的 txt人工修正后再合回训练集。from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) results model.predict( unlabeled_images, save_txtTrue, save_confTrue, conf0.5, )save_txtTrue会把预测结果按 YOLO 格式写到runs/detect/predict/labels目录save_confTrue同时在 txt 里追加置信度方便你按分数筛框。回灌训练集时只保留置信度高于 0.7 的框人工用标注工具打开原图检查一遍把明显框错的删掉再合入。一轮回灌大约能把训练规模扩大 30% 到 50%比翻来覆去调参更有效。这就是数据集的价值放大器模型先帮你干一遍标注的活人来复核边界比从零标注省出一半以上的时间。6. 把 2900 张数据用到极致针对性增强与两轮伪标签迭代到了最后一步谈点直接的进阶技巧。约 2900 张数据对小模型来说够用但想把它当成长期资产就要把增强参数和伪标签迭代结合起来。6.1 按起重机形态定增强参数起重机的标注框几乎都是水平矩形目标主体是桁架臂和配重。增强参数我有两个习惯一是旋转不给太大degrees8.0足够旋转过猛会教模型把地面纹理识别成吊臂二是亮度通道要舍得给hsv_v0.5起步因为工地现场从清晨到傍晚光照跨度极大。以下面的命令行方式传给训练器即可yolo train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch16 hsv_h0.015 hsv_s0.7 hsv_v0.5 degrees8.0 scale0.5 mosaic1.0scale0.5让目标在缩放上有半个档位的自由度适配不同观测高度mosaic1.0保持默认它在小数据上相当于免费扩充了背景多样性。6.2 用模型自己扩数据的心得伪标签迭代的用法在 5.4 已经给了代码这里补一个分寸问题做两轮就停不要贪多。第一轮用 best.pt 预测未标注图片过滤高置信框合入训练集第二轮再训练、再预测、再合入。第二轮通常还有收益到第三轮时模型已经开始过度自信伪标签里的错误被当成正确答案不断自我强化指标看着在涨实际是把验证集也污染了。一个我在数据上吃过亏的教训是拿到标注好的数据不要跳过数据体检直接训练。哪怕数据声称已经 YOLO 标注好也要先跑一遍 4.1 的检查脚本再画一下标注框的宽高分布确认是不是只有大目标、细长目标比例有多高。我当时跳过这一步模型在验证集上 mAP 不低到了现场看到塔吊的细长大臂疯狂漏检回头一查训练集里细长框只占三成。先看清标签分布再决定增强和阈值能帮你少走最远的那段弯路。希望帮到你。本文还有配套的精品资源点击获取
返回列表