
简介面向工业质检、焊接工艺监测及机器人视觉等场景YOLOv8焊缝质量好坏检测资源包提供了一套可直接使用的检测方案。模型已训练完成包含PR曲线、loss曲线等评估指标可用于焊缝缺陷的快速判别配套的钢材缺陷数据集由LabelImg标注jpg图片配合xml与txt两种格式的标签文件分别存放适配Ultralytics YOLOv8的训练与验证流程。资源共2000个文件以txt标注文本、md学习笔记、jpg图像、py训练/推理脚本及yaml模型配置为主另有cpp推理代码、pt权重文件及可视化页面压缩包约155.52MB。资源按功能划分清晰既可直接加载模型进行推理也可基于标注数据重新训练或调参还能通过源码与配置学习YOLOv8的完整工作流。目前已有224人学习/下载适合需要快速落地焊缝检测或深入理解YOLOv8实践的开发者。1. YOLOv8焊缝质量好坏检测模型、数据集与推理代码一次给全先给结论这份资源不是只给一个训练好的模型而是把「标注数据 训练产物 C 推理 前端展示」整条链路都打包好了。焊缝质量检测传统上依赖老师傅目视或者超声波探伤老师傅一天看几百米焊缝疲劳之后漏检率其实不低而用 YOLOv8 做初筛可以把气孔、焊瘤、裂纹这一类缺陷直接从焊缝图像上框出来省掉大量重复劳动。资源里的检测模型已经训练完成附带了 PR 曲线和 loss 曲线你可以直接看到它性能大概在什么水平数据集是 labelimg 标注的钢材缺陷图片jpg 原图配了 xml 和 txt 两套标签。适合两类人做毕业设计或课程设计的学生以及想在产线里做焊缝初筛的质检工程师。下面我从数据集格式、训练参数、C 部署到常见坑按实际落地顺序拆开讲。2. 先摸清数据集底细labelimg 的 xml 与 txt 双标签怎么对齐很多人拿到数据集第一步就卡住一个文件夹里放 xml一个文件夹里放 txt到底以哪个为准其实两个都是真的只是格式不同。xml 是 labelimg 保存的原生标注Pascal VOC 风格人类可读方便你查某个框的坐标txt 是 YOLO 训练时真正要吃的格式。搞清楚这层关系后面训练才不会翻车。2.1 两套标签的字段对应关系labelimg 保存的 xml 长这样annotation foldersteel/folder filenameweld_001.jpg/filename size width640/width height480/height depth3/depth /size object nameporosity/name bndbox xmin120/xmin ymin80/ymin xmax260/xmax ymax210/ymax /bndbox /object /annotation这段结构里最关键的信息是 filename、width/height 和每个 object 的 name 与 bndbox。注意 bndbox 里存的是像素绝对坐标xml 看的是一张图上有哪几个缺陷、每个缺陷在哪。而对应的 txt 是 YOLO 格式每行代表一个目标0 0.296875 0.302083 0.218750 0.270833四个数字分别代表 class_id、中心点 x、中心点 y、宽 w、高 h后四个全部除以图片宽高做了归一化。也就是说同一张图的同一批框从 xml 转成 txt 时要把坐标做一次换算换算公式就是x_center (xmin xmax) / 2 / width y_center (ymin ymax) / 2 / height w (xmax - xmin) / width h (ymax - ymin) / height我一般拿到这种双格式资源后第一步不是急着训练而是先抽几张图做这个换算反向验证看 txt 里的框和 xml 里的框能否对应上。如果两边对不上说明数据集被二次处理过比如图片被压缩过、有人手工改过 xml 没同步 txt这种数据直接用训练时很容易出现 loss 正常但 mAP 上不去的情况。2.2 写个脚本验证两套标签是否真的对齐手工一张张看图太慢压测数据集的正确姿势是写脚本批量检查。我常用的验证思路是先比对文件名集合再随机抽 50 张图做坐标回算最后画框目检。import os import xml.etree.ElementTree as ET import random xml_dir labels_xml # xml 标签目录 txt_dir labels_txt # txt 标签目录按文件名前缀一一对应 xml_files {os.path.splitext(f)[0] for f in os.listdir(xml_dir) if f.endswith(.xml)} txt_files {os.path.splitext(f)[0] for f in os.listdir(txt_dir) if f.endswith(.txt)} # 1. 找出只存在于其中一边的文件 print(只在 xml 中:, xml_files - txt_files) print(只在 txt 中:, txt_files - xml_files) # 2. 随机抽 50 个文件做坐标回算 sample random.sample(sorted(xml_files txt_files), min(50, len(xml_files))) mismatch [] for name in sample: tree ET.parse(os.path.join(xml_dir, name .xml)) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) xml_boxes [] for obj in root.findall(object): bb obj.find(bndbox) xmin int(bb.find(xmin).text) ymin int(bb.find(ymin).text) xmax int(bb.find(xmax).text) ymax int(bb.find(ymax).text) xml_boxes.append((xmin, ymin, xmax, ymax)) with open(os.path.join(txt_dir, name .txt), r) as tf: lines tf.read().strip().splitlines() if len(lines) ! len(xml_boxes): mismatch.append((name, 框数量不一致)) continue for line, (xmin, ymin, xmax, ymax) in zip(lines, xml_boxes): parts line.split() cx, cy, w, h float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) rxmin (cx - w / 2) * img_w rymin (cy - h / 2) * img_h # 允许 2 像素以内的误差labelimg 手标难免有舍入 if abs(rxmin - xmin) 2 or abs(rymin - ymin) 2: mismatch.append((name, 坐标偏移过大)) break print(抽查不一致:, mismatch[:10] if mismatch else 全部通过)这段脚本做了两层校验。第一层比较 xml 与 txt 的文件名集合解决的是「漏标或重复标」的问题很多数据集被反复拷贝后会出现两张图共用一个 txt 的情况这类脏数据不查出来训练时会在加载阶段就报错。第二层做了坐标回算把 txt 里的归一化坐标还原成像素值和 xml 里手标的框对比允许 2 像素以内的误差是因为 labelimg 导出时本身有取整超过这个量说明两套标签不是同一次标注的产物要警惕。2.3 训练集与验证集划分的边界条件对齐验证通过之后还要做数据集划分。很多人习惯把所有图片丢进去让 YOLO 自己随机分但焊缝检测这类工业场景数据往往存在「同一条焊缝的连续帧」——前一帧和后一帧非常相似如果随机划分训练集里出现第 100 帧、验证集里出现第 101 帧验证指标会虚高实际换到新焊缝上效果立刻打折扣。我一般会先看图片文件名是否有编号规律比如 weld_001.jpg、weld_002.jpg 这种有连续编号就先按编号分组再按组切分而不是按单张图切分。常见比例是训练集占 80%、验证集占 20%如果数据量少于 500 张建议提到 90% 训练、10% 验证并且用 K 折交叉验证来补可靠性。划分后还要确认一件事所有类别在训练集和验证集里都有分布。焊缝缺陷有个典型问题是长尾分布气孔可能占 70%裂纹只占 5%如果裂纹全被切到验证集里训练时模型根本没见过裂纹推理时自然漏检。这一步用一条简单命令就能查for split in train val; do echo $split cat labels_$split/*.txt | awk {print $1} | sort | uniq -c | sort -rn done这行命令把每个子集里所有 txt 的第一列 class_id 做了频数统计。如果某个类别在 val 里出现但在 train 里没有或者 train 里某类只有十几条就要回去重新划分或者干脆手动把这类样本复制几份做复制增强。这属于处理数据集用于 YOLOv8 训练时的基础操作别嫌麻烦。3. 训练与评估YOLOv8 参数含义和 PR/loss 曲线的判读数据集搞定之后下一步是把训练跑起来并看懂结果。这一章不会教你背诵网络结构而是讲清楚怎么基于这份已训练好的资源继续微调以及如何从曲线判断模型到底是真强还是虚强。3.1 为什么焊缝检测场景适合 YOLOv8选择 YOLOv8 做焊缝缺陷检测不是因为它新而是因为几个具体特性恰好命中这个场景。焊缝缺陷有两个特点一是缺陷面积占整图比例很小二是在同一条焊缝上形态接近、但不同批次钢材差异明显需要模型有较强的特征复用能力。YOLOv8 用了 C2f 结构在残差连接的基础上把梯度流做了更细的分叉浅层特征和深层特征融合更充分对这类「背景单调、目标小且碎」的图像比 YOLOv5 的 C3 结构更稳。另一个原因是 YOLOv8 改成了 anchor-free 检测头每个位置直接预测距离四条边的偏移不再依赖预设 anchor 的尺寸。焊缝缺陷的宽高比变化很极端气孔接近正方形而裂纹可以细长到宽高比 1:10anchor-based 的方法需要精心聚类 anchoranchor-free 则省掉这一步省下的调参功夫对于工业落地非常实在。如果你是在 Ubuntu 20.04 上用 CPU 环境跑YOLOv8 的安装依然很轻pip install ultralyticsCPU 版本不需要额外装 torch 的 GPU 版ultralytics 会自动拉取 CPU 版 PyTorch。训练会慢但推理一张 640 分辨率的图通常仍能跑到几百毫秒做验证完全够用。3.2 训练命令与关键参数照着改就能用假设你要基于这份资源重新训练或微调先建一个数据配置文件。YOLOv8 从 v8 开始把数据路径和类别定义集中在 yaml 里# steel.yaml path: ./datasets/steel train: images/train val: images/val names: 0: porosity 1: slag 2: crack 3: undercut这里 path 是数据集根目录的相对路径train 和 val 分别指向训练及验证图片目录。names 里的类别序号必须和 txt 标签里的 class_id 严格一致这是 YOLOv8 训练自己的数据集时最常见的出错点——labelimg 里类别名的排序和 yaml 里不一致模型训练时就会把「气孔」当成「裂纹」而且这个错非常隐蔽因为训练不会报错只有看混淆矩阵才露馅。训练命令我习惯这样写yolo detect train datasteel.yaml modelyolov8n.pt \ epochs200 batch16 imgsz640 \ patience20 lr00.01 \ projectruns/weld exp_nametrain_v1逐参数说。model 用官方预训练权重做迁移学习正常情况不要从零训练YOLOv8 的预训练权重下载一次后会自动缓存到当前目录后续离线也能跑。epochs 焊痕检测建议至少 200因为缺陷样本占比小浅层特征需要更多轮次才能收敛。batch 在 16GB 显存的卡上可以开到 16如果你只有 8GB 显存就降到 8显存不够时优先降 batch 而不是降 imgsz因为 imgsz 降低会直接影响小缺陷的检测率。patience 是早停参数连续 20 轮验证集 mAP 不涨就自动停止这是防止过拟合的后悔药。lr0 保持 0.01 就好改大容易出现 loss 曲线震荡。3.3 从 results.csv 读真实水平PR 曲线和 loss 曲线怎么看训练结束后所有指标都落在runs/weld/train_v1/目录下。很多人只会看最后一行 mAP但我会先翻 results.csv它是每轮的原始记录epoch, train/box_loss, train/cls_loss, train/dfl_loss, metrics/precision(B), metrics/recall(B), metrics/mAP50(B), metrics/mAP50-95(B), val/box_loss, val/cls_loss, val/dfl_loss, lr 0, 1.42, 2.10, 1.18, 0.52, 0.10, 0.20, 0.08, 1.30, 1.90, 1.12, 0.01看这份 CSV 有三个重点。第一看 train 和 val 的 box_loss 是否同步下降如果 train 降而 val 不降说明过拟合开始可以在训练时增加增强强度或提前截断。第二看 mAP50 和 mAP50-95 的差距如果 mAP50 有 0.9 但 mAP50-95 只有 0.4说明模型对缺陷的定位精度不够框的位置飘这在焊缝这种需要精确评估缺陷面积的场景很致命。第三看 precision 和 recall 的取舍焊缝质检宁可用低一点 precision 换取高 recall漏检一个缺陷上产线就是事故这个倾向要体现在推理时的 conf 阈值上而不是改训练参数。PR 曲线图PR_curve.png是综合判断模型性能的另一个入口。曲线越靠近右上角越好注意看曲线右下角有没有突然的「塌陷」如果存在说明置信度阈值降到某个值以下时模型开始大量输出低质量框这时候需要结合 precision 和 recall 数值表确定一个合理阈值而不是默认用 0.25。至于 loss 曲线重点不是看它降得多低而是看是否存在周期性尖峰尖峰出现的位置通常对应某张「脏图」比如标注框越界、图片亮度异常到这一步就要把那几个 epoch 附近的数据样本筛出来重新清洗。4. C 推理与前端展示把 pt 模型落到实际检测训练好的模型最终要部署。资源里的 inference.cpp 和 main.cpp 说明项目侧走的是 C 推理路线这类做法在产线里非常常见——C 直接读取模型文件不依赖 Python 环境启动快、内存占用低、便于集成到现有的质检工控机程序里。下面按实际部署流程拆解。4.1 C 侧的整体推理链路从 PyTorch 训练产物到 C 能跑的推理中间有一道标准工序。第一步是把 pt 权重导出为部署格式常见做法是导出成 ONNX 再转 TensorRT engine如果你的目标平台是 RK3588 这类嵌入式设备再向前一步转成 RKNN。导出命令很直接yolo export modelruns/weld/train_v1/weights/best.pt formatonnx imgsz640导出成功后C 端的推理流程是固定的四步读图做 letterbox 预处理把图像缩放成模型输入尺寸归一化并转换成 RGB 连续内存运行模型拿到输出张量对输出做解码和 NMS 后处理得到最终的框、类别和置信度。这里有一个我在实际部署时反复踩的点C 端的预处理必须和训练时完全一致包括 letterbox 的填充颜色、归一化系数、是否 BGR 转 RGB。很多项目在 Python 里验证时好好的一迁到 C 准确率就掉九成是预处理不一致。下面把预处理和后处理两个核心模块拆开讲代码是基于这份资源场景下最典型的写法。4.2 核心代码letterbox 预处理与 NMS 后处理letterbox 的作用是保持宽高比地把图片缩放并填充到目标尺寸YOLOv8 训练时默认填充的是 114 这个灰度值#include opencv2/opencv.hpp #include algorithm // 把任意尺寸的输入图变成 model_w x model_h 的方形图保持宽高比其余区域填充 cv::Mat letterbox(const cv::Mat src, int model_w, int model_h) { float scale std::min((float)model_w / src.cols, (float)model_h / src.rows); int new_w (int)std::round(src.cols * scale); int new_h (int)std::round(src.rows * scale); cv::Mat resized; cv::resize(src, resized, cv::Size(new_w, new_h)); // 用 114 灰度填边和 YOLOv8 训练时保持一致 cv::Mat canvas cv::Mat::zeros(model_h, model_w, CV_8UC3); canvas.setTo(cv::Scalar(114, 114, 114)); int dx (model_w - new_w) / 2; int dy (model_h - new_h) / 2; resized.copyTo(canvas(cv::Rect(dx, dy, new_w, new_h))); return canvas; }这段代码的逻辑是计算缩放系数 scale取宽高两个维度中较小的那个保证图片缩放后完全落在画布内不留信息损失。然后创建一个 model_h 乘 model_w 的全灰画布把缩放后的图居中贴上。dx 和 dy 是贴图时的偏移量后面 NMS 结束把框坐标映射回原图时这两项必须原样减回去否则框会整体偏向右下角这就是 C 推理最常见的「框全飘了」的原因。NMS 后处理的核心逻辑是从模型输出的一堆候选框里剔除重叠框// 输入为解码后的候选框输出为保留的框索引 std::vectorint nms(const std::vectorcv::Rect boxes, const std::vectorfloat scores, float iou_thres) { std::vectorint indices; std::vectorint order(scores.size()); std::iota(order.begin(), order.end(), 0); // 按置信度从大到小排 std::sort(order.begin(), order.end(), [](int a, int b) { return scores[a] scores[b]; }); std::vectorbool removed(scores.size(), false); for (int idx : order) { if (removed[idx]) continue; indices.push_back(idx); for (int jdx : order) { if (removed[jdx]) continue; if (idx jdx) continue; float iou (boxes[idx] boxes[jdx]).area() / (double)(boxes[idx] | boxes[jdx]).area(); if (iou iou_thres) removed[jdx] true; } } return indices; }NMS 的做法是先把候选框按置信度排序优先保留置信度最高的框然后把它和所有更低置信度框计算 IoU重叠面积超过阈值的直接删除。iou_thres 焊缝场景我一般设 0.45比通用的 0.5 略低因为焊缝缺陷框之间经常靠得很近IoU 阈值设太高会把两个不同缺陷并成一个框。这里要注意 boxes 的坐标已经通过上面 letterbox 的 dx、dy 反向换算回原图尺寸NMS 必须在原图坐标系下做否则不同尺寸的图片结果会乱。4.3 检测结果的可视化与前端留档资源里的 style.css 和 comments.html 说明项目做了一个展示页面这套东西的工程意义比看起来大。焊缝检测不只是把框画在屏幕上就完了还需要让质检员能复核、能留档。我经手过的生产项目里最实用的做法是把每一帧检测结果连同置信度、缺陷类别、检测时间输出成 JSON 或者直接渲染成 HTML 记录方便事后追溯。// 把检测结果写入 HTML 片段供 comments.html 展示 void write_result_html(const std::string img_name, const std::vectorcv::Rect boxes, const std::vectorint cls_ids, const std::vectorfloat confs) { std::ofstream ofs(result_ img_name .html); ofs div classdetect-item; ofs img src img_name /; for (size_t i 0; i boxes.size(); i) { ofs span classbox styleleft: boxes[i].x px; top: boxes[i].y px; width: boxes[i].width px; height: boxes[i].height px;class cls_ids[i] conf confs[i] /span; } ofs /div; }这段代码把检测结果直接生成一个带定位样式的 HTML 片段用 CSS 里的绝对定位把检测框画在图片对应位置再附上类别和置信度文本。这种做法比弹窗展示更实用——生成的 HTML 文件可直接归档也可以在后端统一汇总成检测报表后续做缺陷率统计分析时直接从这些文件里抓数不用再让 C 程序额外写一堆数据结构。5. 避坑记录标注、训练与 C 部署的五个现场问题这份资源整体完整但落地过程中有几个坑几乎每个人都会撞上。我把现场遇到过的典型问题按现象、原因、解决的方式整理出来这属于血泪经验能帮你省掉至少一周的排查时间。5.1 标注与格式xml 和 txt 数量对不上现象训练启动时报错提示找不到某张图片对应的标签文件或者数据集加载完成后样本数量比图片数量少了几十张。原因labelimg 在标注过程中如果手动删除过已标注的图片xml 会被删掉但 txt 可能因为被单独拷贝过而残留反过来也会发生。双格式数据被多次复制后两边的文件数量很难完全一致。解决在训练前必须用 2.2 节那段脚本做集合比对把只在单边存在的文件列出来。我的习惯是列出来之后直接删除多余那个而不是补齐缺失那个因为缺失的那张图当时为什么没标注已经无法考证强行补标反而会引入主观错标。做完这一步再到 images、xml、txt 三个目录做一次三方总校验确保文件名一一对应。5.2 标注与格式类别名不统一导致多出「幽灵类别」现象训练完看混淆矩阵发现多了一个不在预期内的类别而且这个类别和真实缺陷混在一起比如「气孔」和「blowhole」被当成了两类。原因这份数据集可能是多人标注的不同人一个用中文一个用英文或者 labelimg 的 classes.txt 在工作过程中被改过导致同一类缺陷存在两个名字。更隐蔽的是YAML 里 class_id 的映射和 txt 文件里的序号不一致模型学到的语义和你想的不一样。解决拿到资源的第一个动作就检查 labelimg 的 classes.txt和 data.yaml 里的 names 列表逐行对齐。发现多重命名时统一到一组标准名然后重新生成全部 txt 标签。这个步骤必须在训练之前完成训练后再发现就只能重训没有后悔药。5.3 训练与评估loss 曲线在某个 epoch 突然飙升现象训练的 loss 曲线整体下降但到某个 epoch 突然出现一个尖峰之后又恢复正常。原因这个尖峰对应的几乎都是脏数据——某张图的 xml 坐标越界比如 xmax 写成了负数或者图片本身是损坏的 JPEG解码后一片黑。YOLOv8 在数据加载阶段不会校验这些模型被迫在这张图上强行学习错误特征loss 自然异常。解决把 loss 曲线出尖峰的那几个 epoch 对应的数据批次单独拉出来做可视化检查。实操上我会在训练前先跑一遍数据清洗脚本检查所有标注框是否在图片边界内以及图片能否被 OpenCV 正常解码。具体到这份资源重点检查 xml 里的 xmin/xmax因为手标时很容易把两个值写反写反不会报错但模型训练时等于学了一个完全错误的边界。5.4 C 部署推理结果框整体偏移现象Python 端用同一份模型推理完全正常但 C 端检测出的框位置明显向某个方向偏移偏移量还随着图片尺寸变化。原因这是 letterbox 的 dx、dy 没在输出坐标里减回去。很多人在 Python 里用了 ultralytics 的封装封装层自动做了坐标还原换成手写 C 后把这个步骤漏掉了。框向右下偏移和向左上偏移分别对应 dx、dy 的正负号算反这类问题在代码 review 阶段很难发现因为单张图看偏移量像模型预测误差。解决在 NMS 输出每个框的坐标后把原始 (x, y) 分别减去 letterbox 阶段的 dx 和 dy再除以缩放系数 scale。更稳妥的做法是在 letterbox 函数里把 dx、dy、scale 三个量作为结构体返回而不是只返回处理后的图这样调用处不会忘记取参数。5.5 C 部署同一个模型在不同电脑上效果不一样现象同一份权重和同一张测试图在自己电脑上检测正常到工控机上 mAP 掉了一截或者出现大量低置信度的假阳性框。原因最常见的是 OpenCV 版本问题新版本 OpenCV 的imread默认按 8 位深度读图但老版本在某些压缩格式上可能读出不同通道顺序另一个高频原因是模型推理时用的必须是 RGB 通道顺序而 OpenCV 读图默认是 BGR如果 C 代码里漏掉cvtColor模型看到的特征分布直接就错了。解决在 C 推理入口加一行固定转换cv::cvtColor(img, img, cv::COLOR_BGR2RGB);并且不要依赖 OpenCV 编译环境的默认行为。把通道顺序、归一化方式、输入尺寸这三个变量在配置文件里写死部署到新机器时只核对配置不用重新猜代码。6. 进阶技巧难样本挖掘与小目标切片推理模型能跑通只是起点焊缝检测真正难的是把那些「看着像缺陷但其实不是」和「明显是缺陷但模型漏掉了」的样本捞回来。这一章分享两个我实际用过的提升手段。6.1 难样本挖掘让模型再吃一遍自己的漏检用训练好的模型反向跑一遍训练集把所有低置信度的检测结果挑出来人工复核是快速提升准确率的做法。具体操作是写脚本批量推理然后按置信度排序输出from ultralytics import YOLO import os model YOLO(runs/weld/train_v1/weights/best.pt) hard_samples [] for img in os.listdir(datasets/steel/images/train): path os.path.join(datasets/steel/images/train, img) results model(path, conf0.1, verboseFalse) # 故意放低阈值 for r in results: for box in r.boxes: conf float(box.conf.item()) if conf 0.3: # 低于正常阈值但确实输出了框 hard_samples.append((img, conf, box.xyxy.tolist())) hard_samples.sort(keylambda x: x[1]) for img, conf, xyxy in hard_samples[:50]: print(f{img}: conf{conf:.2f}, box{xyxy})这段代码有两个关键点。第一个是 conf 参数故意降到 0.1因为正常推理时阈值 0.25 会把很多真缺陷直接过滤掉只有降低阈值才能看到模型「犹豫」的样本。第二个是只收集那些模型输出了框、但置信度在 0.1 到 0.3 之间的样本这些是模型有响应但不确定的模糊地带把它们挑出来人工复核后一些被误标成背景的真缺陷也就暴露了。但是难样本挖掘的结果不能直接全部加进去训练要先按三类处理标注错误的人工修正标注正确但特征确实难辨的加入数据集并做随机增强纯粹是模型误检的单独留存用于后续调阈值。直接混合训练会把噪声也学进去。6.2 切片推理把焊缝小缺陷放大再看焊缝图像里气孔这类缺陷有时只占 20 乘 20 像素在整张 640 分辨率的图上非常不明显。这类小目标问题上与其盲目换大模型从 yolov8s 换到 yolov8l 的收益通常很小不如先做切片推理。思路很直接把一张原图切成 2 乘 2 或 3 乘 3 的切片每个切片独立送进模型推理再把切片上的检测框映射回原图坐标。相当于让同样的小模型用 4 到 9 倍的「分辨率」去看每个区域。焊缝图像背景相对单调切片的边界条件比自然场景更好把控。实现时要注意切片之间保留 10% 到 15% 的重叠防止缺陷正好被切成两半推理完再对重叠区域的重复框做一次 NMS。代价是推理时间近似乘以切片数量如果产线节拍不允许全部切片推理可以设计两阶段策略先用整图低阈值跑一遍只有整图置信度低于某个值或框数量异常时才对该区域做切片细分。另外一个方向是改检测头的注意力机制比如给 C2f 模块加上协调注意力这一类的改动对长条形的裂纹缺陷有一定收益。但改动网络结构意味着要重新训练、重新导出 ONNX、重新跑 C 端时间成本不小我通常是在切片推理已经做到瓶颈时才考虑动模型结构。说到底焊缝质检落地靠的不是某个单点技巧而是「数据干净、训练合理、部署一致」这条链路每一环都不能侥幸。从那以后我每次做这类工业检测项目都会把「训练集难样本统计」和「C 端预处理参数核对」写进交付清单强制走一遍才敢说模型能上线。希望这套拆解对你有用拿到资源后照着第 2 章先把数据验一遍能少走很多弯路。本文还有配套的精品资源点击获取