ARTICLE DETAIL

资讯详情

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

YOLOv8焊缝缺陷检测:从数据标注到Python/C++部署全流程解析

YOLOv8焊缝缺陷检测:从数据标注到Python/C++部署全流程解析 简介YOLOv8焊缝质量好坏检测完整方案面向工业质检与智能制造领域的算法工程师、科研人员及目标检测初学者覆盖数据准备、模型训练、效果评估与部署调用全流程。资源包内置训练好的模型权重附带了训练阶段的PR曲线、loss曲线等评估图表可以直接用于焊缝好坏的实时检测同时配有经labelimg标注的钢材焊缝数据集包含jpg原始图片以及xml与txt两种格式的标签分别存储在两个文件夹中便于按VOC或YOLO格式直接开展二次训练与迁移学习。文件合计2000个类型以txt标注/说明、md笔记、jpg图像、py脚本和yaml配置为主另有C/Python推理源码、HTML测试页面、PDF参考文档、模型权重pt与缓存文件等整体压缩包约155.52MB目录结构清晰能帮助读者快速定位训练脚本、配置文件、评估结果与部署代码。已有224人学习下载适合希望快速落地焊缝质量检测方案或完整复现YOLOv8训练、评估与推理流程的开发者。1. 焊缝探伤结果还在靠肉眼YOLOv8 已能把“好不好”压成两个类在钢结构、压力容器和管道焊接场景里焊缝外观质量检查是出厂前绕不开的一环。传统做法是老师傅拿着样板比对或者用磁粉、超声设备逐段扫效率低且标准因人而异。这套 YOLOv8 焊缝质量好坏检测方案把焊缝图直接喂给目标检测模型一次前向推理就能标出焊缝位置并给出“好/坏”两个类别。模型已训练好解压即可用附带的数据集是我个人比较认可的——用 labelimg 标注的钢材缺陷照片jpg 格式同时保留 xml 和 txt 两套标签省去反复转换标注格式的时间。适合谁用手里攒了一批焊缝图想快速验证检测可行性的人做质检系统原型开发的工程师以及拿 YOLOv8 做毕业设计、需要完整训练闭环的同学。这篇博文不讲空泛的 AI 概念直接从数据格式、模型结构、loss 曲线怎么读到 Python/C 两侧怎么跑通按一线工程师拆项目的思路写。2. 数据集与标签体系xml 和 txt 并存先看懂再喂给模型2.1 目录结构与标注文件的对应关系解压后你首先看到的是数据部分图片存放在 JPEGImages 或类似命名的目录里xml 和 txt 分别放在两个独立文件夹。xml 是 labelimg 默认导出的 Pascal VOC 格式txt 是 YOLO 训练需要的归一化坐标格式。两者的对应关系不是自动生成的需要脚本统一处理。import xml.etree.ElementTree as ET import os def voc2yolo(xml_path, out_dir, class_list): tree ET.parse(xml_path) w int(tree.findtext(./size/width)) h int(tree.findtext(./size/height)) lines [] for obj in tree.findall(object): name obj.findtext(name) if name not in class_list: continue cls_id class_list.index(name) xmin float(obj.findtext(bndbox/xmin)) ymin float(obj.findtext(bndbox/ymin)) xmax float(obj.findtext(bndbox/xmax)) ymax float(obj.findtext(bndbox/ymax)) cx (xmin xmax) / 2 / w cy (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) out_name os.path.splitext(os.path.basename(xml_path))[0] .txt with open(os.path.join(out_dir, out_name), w) as f: f.write(\n.join(lines)) class_list [good, bad] # 按你训练时的类别顺序 voc2yolo(data/xmls/0001.xml, data/labels, class_list)这段脚本把 VOC 的绝对坐标转成 YOLO 要求的中心点加宽高的归一化格式。注意 class_list 的顺序要和训练时的 data.yaml 完全一致否则类别会对错位。比如训练时放的是[good, bad]这里就必须保持相同排序。2.2 标签质量对模型上限的影响焊缝图像本身背景复杂有飞溅、氧化皮、打磨痕迹这些都不是目标标注时很容易把噪声圈进去。我拿到这套数据时的经验是先随机抽 50 张图检查标签框是否贴着缺陷边缘。框松一点模型收敛快但误检多框太紧训练初期 loss 降得慢。特别要看斜向裂纹xml 里 bndbox 只能给轴向对齐矩形如果缺陷有明显的长条形倾斜建议在标注阶段就按最小外接矩形处理不要为了框住整条裂纹把背景大面积包含进去。训练集和验证集在 labelimg 导出时往往是混在一个文件夹里需要先划分再训练。常见做法是按 8:1:1 划分 train/val/test且划分前先对文件名做随机打乱避免同一个工件连续帧同时进训练集和验证集,导致验证指标虚高。3. 模型训练与结果判读c2f 结构、PR 曲线和 loss 曲线怎么配合看3.1 为什么选 YOLOv8 而不是 YOLOv5 或 R-CNN 系列焊缝检测属于典型的小目标与长条形目标混合场景既有几像素宽的细微裂纹也有大块的咬边。YOLOv8 的 backbone 引入了 c2f 模块在保持轻量的同时增强了梯度回传路径对长条形裂纹这种低对比度目标更友好。另外 YOLOv8 是 anchor-free 结构输出层直接预测中心点偏移和宽高省去了聚类 anchor 的步骤对形状分布不均匀的焊缝缺陷更省心。如果你用的是 GTX 1660 Ti 这类 6G 显存的卡YOLOv8n 或 YOLOv8s 是合理的起点。数据增强方面YOLOv8 默认开启 mosaic 和 mixup。焊缝缺陷很多是细线状mosaic 把四张图拼一起训练模型被迫学习跨上下文的特征反而对检测完整裂纹有帮助。但训练后期如果发现 val loss 震荡优先关闭 mixup。3.2 训练命令与关键参数假设数据目录已经整理成 YOLO 格式yolo train \ modelyolov8s.pt \ datawelding.yaml \ epochs100 \ imgsz640 \ batch16 \ patience20 \ optimizerauto \ device0welding.yaml 内容参考path: ./welding-data train: images/train val: images/val names: 0: good 1: bad训练命令里的参数逐个说batch16 是 6G 显存下 yolov8s 的安全值imgsz640 是速度和精度的平衡点焊缝缺陷如果普遍小于 20×20 像素可以试着调到 960但推理时间会显著增加patience20 表示 20 个 epoch 内 val loss 不下降就早停避免过拟合到训练集的噪声标注上。3.3 PR 曲线和 loss 曲线到底看什么训练完成后runs/detect/train/下会生成PR_curve.png和各类 loss 图。很多人只看 PR 曲线的右上部区域那是错误姿势。PR 曲线是 confidence 从高到低连续变化时 precision 与 recall 的权衡线真正要关注的是曲线下方靠右的拐点位置以及 AP 数值。焊缝检测中 bad 类 AP 通常低于 good 类因为坏焊缝样本本身就是少数类。yolo predict modelruns/detect/train/weights/best.pt source./test-images跑完看labels.jpg和混淆矩阵。若混淆矩阵里 good 被误判成 bad 的比例偏高问题大概率不在模型而在标注阶段对“好焊缝”的边界定义不一致。loss 曲线方面重点看box_loss是否在最后 20 个 epoch 还在明显下降如果是说明 epochs 设短了如果 val/box_loss 上升而 train/box_loss 继续下降就是典型过拟合回退到早停点即可。3.4 训练自己的数据集时如何按需改进如果你的焊缝场景和这份数据差异不大直接用 best.pt 做迁移学习yolo train modelruns/detect/train/weights/best.pt datayour_data.yaml epochs50这比从头训练收敛快得多。改进方向上热词里常提到 yolov8 改进、损失函数改进这类属于锦上添花。实测中 c2f 结构对细长缺陷已经够用更值得优先调整的是scale_range增强参数或fliplr。焊缝缺陷往往有水平对称性但垂直于焊缝的裂纹翻转后物理含义不变而字符类缺陷翻转会语义错误。卤素灯下拍摄的焊缝图还有白色高光这类高光处的缺陷极易漏检可以考虑在训练集中按 5% 概率加入高斯噪声模拟高光干扰。4. 部署与推理验证从 Python 快速验证到 C 侧代码的承接4.1 Python 推理几分钟验证模型效果拿到训练好的模型第一步是在自己的图上快速验证不急着上 C。准备一段最基础的推理脚本from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) results model.predict( sourcetest_images/, conf0.35, iou0.5, saveTrue, save_txtTrue, projectruns/detect, nameinference ) for r in results: boxes r.boxes names r.names if boxes is not None: for i in range(len(boxes)): cls_id int(boxes.cls[i].item()) conf boxes.conf[i].item() xyxy boxes.xyxy[i].tolist() print(fclass{names[cls_id]} conf{conf:.3f} box{xyxy})conf0.35是焊缝场景的推荐起步值。裂纹和咬边这类缺陷边缘模糊confidence 普遍低于日常物体检测设在 0.5 容易漏检。输出端save_txtTrue会把检测框坐标保存到 txt 文件方便后续直接对接 C 后处理逻辑。4.2 C 侧代码再看inference.cpp 与 main.cpp 的衔接工程包里出现了 inference.h、inference.cpp 和 main.cpp这是典型的 C 部署结构。一般做法是 inference 类封装模型加载和推理接口main 负责读取图像、调用推理、画框和结果输出。我建议按三个层次读先看 inference.h 里暴露了哪些接口一般会有构造函数加载权重与初始化 session一个 predict 成员函数接收 Mat 图像返回检测结果再看 main.cpp重点看图像预处理是否对齐到训练时的输入尺寸与归一化方式。C 部署的一个常见坑是图像缩放。训练时 ultralytics 的 letterbox 会先等比例缩放再填充灰色边C 端如果用 OpenCV 简单 resize图像比例失真框会偏移。一般做法是手动实现 letterbox 逻辑并且记录缩放系数和填充偏移后处理画框时再映射回原图坐标。cv::Mat letterbox(const cv::Mat src, int target_size, float scale, int pad_w, int pad_h) { float r std::min(target_size * 1.0f / src.cols, target_size * 1.0f / src.rows); int new_w std::round(src.cols * r); int new_h std::round(src.rows * r); scale r; pad_w (target_size - new_w) / 2; pad_h (target_size - new_h) / 2; cv::Mat resized; cv::resize(src, resized, cv::Size(new_w, new_h)); cv::Mat canvas(target_size, target_size, CV_8UC3, cv::Scalar(114, 114, 114)); resized.copyTo(canvas(cv::Rect(pad_w, pad_h, new_w, new_h))); return canvas; }这段letterbox逻辑说明了部署侧的注意点scale、pad_w、pad_h需要传回后续的框坐标映射函数否则检测框位置整体偏移。C推理时如果用 GPU 跑 torchscript 模型需要注意 torch::jit 的版本和 engine 对齐CPU 版则可以直接把模型导出成 onnx用 ONNX Runtime 加载代码会简洁不少。4.3 从 Python 到 C 的结果一致性验证很多人推进到这一步发现同一张图 Python 和 C 检测结果不一致。这通常不是模型差异而是预处理细节不同。检查项Python 端C 端一致性问题输入尺寸640640必须相同色彩空间BGRBGRimread 默认 BGR别转成 RGB归一化0-1 像素值0-1 像素值除 255.0 注意浮点运算填充颜色灰 114灰 114不一致会导致边缘框掉点我习惯把同一张图在两端各跑一次比对每个框的坐标差异是否在 2 像素以内再放大量图片做批量对比。两端都跑通了再去接工业相机批量检测。YOLOv8 的类别只有 good 和 bad 两个后处理不需要 NMS 类别过滤但如果未来扩展成多种缺陷类型就需要按类别单独设置 confidence 阈值因为裂纹和咬边的最优阈值差异可能相当大。5. 上产线前的三个动作参数校准、难例挖掘与数据增强边界测试5.1 用验证集自动搜索最优 conf 阈值把训练时的 PR 曲线信息落到实际使用中可以写一段遍历 confidence 的脚本找到验证集上 F1 最高的阈值而不是肉眼指定 0.35。import numpy as np from ultralytics import YOLO from pathlib import Path model YOLO(runs/detect/train/weights/best.pt) imgs list(Path(val_images).glob(*.jpg)) thresholds np.arange(0.2, 0.6, 0.05) best (0, 0) for thr in thresholds: f1_total 0 for img_path in imgs: r model.predict(str(img_path), confthr, iou0.5, verboseFalse)[0] tp (r.boxes.cls 1).sum().item() fp (r.boxes.cls 0).sum().item() # good被当bad也算误报 fn max(1, len(imgs) - tp) p tp / max(tpfp, 1) r_ tp / max(tpfn, 1) f1_total 2 * p * r_ / max(pr_, 1e-6) avg_f1 f1_total / len(imgs) if avg_f1 best[1]: best (thr, avg_f1) print(fthreshold{thr:.2f}, avg_f1{avg_f1:.3f})这段把 good 类误检成 bad 也计入 FP更贴合产线逻辑——把合格焊缝判废比漏检更影响效益。实际运行时 p/r 的计算方式可以随业务侧重调整。5.2 难例挖掘把误检样本回炉训练产线跑一周收集误检样本重新标注并加入训练集是提升模型最有效的方式。但注意不要直接把这些图混入原训练集就完事而是保持原始的类分布比例。如果坏焊缝在产线上只占 3%训练集里堆积到 30%模型会过度偏向 bad 类在线推理时把大量合格焊缝框成缺陷。另一个可行手段是只在后处理层面对 bad 类做评分加权不动训练数据。5.3 数据增强边界测试模型训完想确认增强策略是否过猛可以对比增强前后的精度差。YOLOv8 默认开启 mosaic、hsv 扰动、平移缩放。焊缝图中 hsv 扰动对金属表面反光影响不明显而 mosaic 对细长裂纹的影响较大。如果 val loss 曲线显示过拟合早优先调低增强参数而不是加正则项。测试时把增强关掉单独跑一遍yolo train modelruns/detect/train/weights/best.pt datawelding.yaml epochs30 hsv_h0 hsv_s0 hsv_v0 mosaic0.0如果关闭增强后 val loss 反而更低说明原始训练时增强过强应降低 mosaic 频率。如果精度下降明显说明增强是有效的不要动。这个实验值得做很多人在部署早期把所有参数都归零反而牺牲了模型的鲁棒性。本文还有配套的精品资源点击获取
返回列表