简介:面向工业质检与计算机视觉学习者的 YOLOv7 钢材缺陷检测完整资源包,已训练好检测模型并附带权重文件,适用于表面缺陷分类与定位场景,也可作为目标检测实战项目参考。包内除了训练权重,还包含 PR 曲线、Loss 曲线等训练过程记录,便于分析模型收敛情况;数据集已用 LabelImg 完成标注,同时提供 xml 与 txt 两种标签格式,分别存放于独立文件夹中,可直接用于 YOLO 系列模型的训练和验证。资源共 166 个文件,涵盖 yaml 配置、jpg 图像、py 脚本、ipynb 示例、pt 权重、xml/txt 标注文件等类型,整体压缩包约 203.86MB,结构清晰,适合下载后按需选用。目前已有 1290 人学习浏览,对希望快速上手钢材缺陷检测或扩充训练数据的开发者具有较高参考价值。
1. 钢材缺陷检测为什么绕不开 YOLOv7:一个权重文件背后的完整链路
钢材表面的划痕、麻点、氧化皮,在传统视觉里是「特征工程的地狱」——不同钢种、不同轧制批次、不同光照下,同一类缺陷呈现的纹理差异,有时候比缺陷和背景的差异还要大。YOLOv7 在这类工业检测里被频繁选型,不是因为它比后来的版本快多少,而是它的权重结构、训练策略和部署生态恰好覆盖了钢材场景最头疼的三个问题:数据量少、类别极度不均衡、产线对误检零容忍。这篇文章不写论文复现,只讲一条可落地的链路:拿到一套钢材缺陷检测权重和数据集之后,从选型、训练、参数调试到部署避坑,把它变成一条能真正跑起来的检测流程。适合正在做表面质检项目选型,或者已经在训练但指标始终上不去的开发者。
2. 数据集与权重的三个关键选型:YOLOv7 钢材缺陷任务的地基
2.1 缺陷类别与标注格式:从缺陷样本到可用数据集的转换思路
YOLOv7 是监督检测模型,数据集决定了下限。钢材表面缺陷的公开资源里,最常见的是六类划分:裂纹、夹杂、麻点、凹坑、氧化皮、划痕。这六类的形态差异非常大——裂纹和划痕都是线状,但裂纹短而曲折、边缘粗糙,划痕长而连续、边缘相对整齐;麻点是密集的小圆斑,氧化皮则是大片的暗色覆盖区。这些形态差异直接决定了 anchor 设计和数据增强策略,后面第 3 章会展开说。
标注格式必须统一成 YOLOv7 默认的 txt 格式,每张图片对应一个同名 txt 文件。每行代表一个目标,总共五个数值:类别 ID、归一化中心 x、归一化中心 y、归一化宽 w、归一化高 h。类别 ID 从 0 开始编号,顺序一旦确定就不要在训练中途改动,否则换了 labels 目录或权重文件,类别就会整体错位,训练出来也是废的。
很多钢材项目手里的数据是从 VOC 的 xml 或 COCO 的 json 格式拿来的,转换脚本的核心逻辑就是读取 bbox 坐标后做归一化并写入 txt。我一般会写一个十几行的 Python 脚本完成转换,重点检查三个地方:bbox 坐标是否越界、类别 ID 是否有缺号或跳号、图片尺寸是否和标注一致。钢材样本经常从大图上裁切出来,裁切时没有同步调整 bbox 坐标是最常见的脏数据来源,训练时表现为 loss 降不下去且大量漏检。
import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_dir): tree = ET.parse(xml_path) root = tree.getroot() img_w = int(root.find("size/width").text) img_h = int(root.find("size/height").text) lines = [] for obj in root.findall("object"): cls_id = CLASS_MAP[obj.find("name").text] # 类别名 -> 类别ID bndbox = obj.find("bndbox") x1 = float(bndbox.find("xmin").text) y1 = float(bndbox.find("ymin").text) x2 = float(bndbox.find("xmax").text) y2 = float(bndbox.find("ymax").text) # 转中心点坐标并归一化,防止越界 cx = ((x1 + x2) / 2) / img_w cy = ((y1 + y2) / 2) / img_h w = (x2 - x1) / img_w h = (y2 - y1) / img_h lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.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))逻辑说明:这个脚本从 VOC 的 xml 里读出每个目标的 bbox 坐标,统一转成中心点格式并做归一化,输出 YOLO 系列的 txt 标注。参数说明:CLASS_MAP要按你的数据集类别顺序手工定义,比如 crack=0、inclusion=1、patches=2、pitted_surface=3、rolled_in_scale=4、scratches=5;img_w和img_h必须以 xml 里的 size 节点为准,不能直接用 PIL 读图尺寸,否则在 JPEG 带 EXIF 旋转信息时会错位。
钢材数据集普遍存在类别不平衡:划痕样本往往占一半以上,裂纹和夹杂可能只有几十张。直接随机划分 train 和 val,很容易出现某个类别在验证集里一张都没有,导致 mAP 看起来很高,实际漏检严重。我一般会按类别做分层抽样;先统计每张图片包含哪些缺陷类别,再按类别比例把数据均匀拆到 train 和 val,保证每个类别在验证集里至少有 10 个以上的标注框。这一步不改变模型结构,但对训练结果的可信度影响极大。
2.2 预训练权重与专用权重:yolov7.pt 与钢材缺陷权重的区别
YOLOv7 官方发布的 yolov7.pt 是在 COCO 数据集上训练的,输出层对应 80 个类别。直接拿这个权重对钢材缺陷做推理,是不可能检出裂纹和划痕的,因为模型根本没有见过这些类别。它真正的价值是作为迁移学习的起点:COCO 上学到的通用边缘、纹理和形状特征,对钢材表面依然有效,不需要从零开始训练。
训练时常见的做法是下载 yolov7.pt 作为初始权重来微调。YOLOv7 的代码会在加载权重时根据你改写的类别数自动调整 head 输出层的维度,你只需要把模型配置里的 nc 从 80 改成你的缺陷类别数。加载时日志会提示Transferred xxx/xxx items,如果看到类似「Transferred 360 多个 / 362」这样的结果,说明除 head 层以外的部分都成功加载了,属于正常现象,不是错误。如果看到大量 key 丢失,才需要检查 cfg 文件是否被改错。
专用权重则指已经用钢材缺陷数据训练好的权重文件,来源有两种:同任务公开项目附带,或者你自己训练出来的 best.pt。拿到别人的专用权重时,第一件事不是跑推理,而是确认它对应的类别顺序。同一个六类钢材数据集,有人把 crack 排在第 0 类,有人把 scratch 排在第 0 类,类别顺序不一致时模型检出的框位置是对的,但标签名全部错位,现场看到「划痕」实际是「裂纹」,这比漏检更麻烦。
从实践角度我的建议是:有 yolov7.pt 就优先用它做迁移学习,不要从随机权重开始;有同数据分布的专用权重可以拿来做二次微调,但一定要先拿几张已知类别的图片验证类别映射。不要迷信「别人训练好的权重直接就能用」——钢材表面的成像差异太大,同一台相机换一个光源,旧权重就可能失效,这和模型好坏无关,是数据分布已经变了。
2.3 数据集目录组织与类别平衡:训练前必须定死的规矩
YOLOv7 对目录结构没有硬性要求,只要 data yaml 里写的路径能找到就行,但为了让后续迭代省事,建议按固定结构组织:images/train、images/val、labels/train、labels/val 四个目录。钢材缺陷数据量通常在几百到几千张之间,这种情况下我一般做 8:2 的划分,并且保证 val 里每张图在训练集里没有重复或裁切自同一张大图。
同一张大图裁出的多个小图同时出现在 train 和 val 里,是钢材数据集最容易忽略的泄漏问题。表面缺陷数据往往来自产线截图,工程师为了扩充样本会把一张 4000x3000 的大图切成十几张 640x640 的小图,如果划分前不做去重,切出来的子图会同时落入训练集和验证集,模型在验证集上的表现会被虚高。解决办法是在划分前按原图文件名做分组,确保同一原图的所有子图要么全部进 train,要么全部进 val。
数据清洗也值得花时间。钢材表面缺陷样本里常见的脏数据有四种:标签框明显偏大把背景包进去、类别标错(划痕标成裂纹)、目标太小或太模糊人眼都难分辨、以及大图裁切后产生的半截缺陷框。图省事把这些样本直接丢进训练集,模型会学到错误特征,典型表现是训练 loss 很漂亮但现场误检多。我一般会先跑一轮快速训练(50 个 epoch),用训练出的权重对验证集做推理,把置信度高但类别明显不对的样本挑出来人工复核。
3. 用 YOLOv7 复现钢材缺陷检测训练:完整命令链与参数解析
3.1 环境准备:省掉 80% 装环境时间的最小依赖清单
YOLOv7 对运行时环境要求不算高,但版本错配是新人入坑的第一道坎。我推荐的基础组合是:Python 3.8 到 3.10、PyTorch 1.12 或更新的稳定版、CUDA 11.6 以上、GPU 显存至少 8GB。钢材缺陷训练通常用 640x640 输入,batch size 16 时 8GB 显存勉强能跑,但要留出验证阶段的内存余量。
安装依赖不要手动一个个 pip install,直接用 requirements.txt 一次装完。拿到代码目录后:
cd yolo7-steel pip install -r requirements.txt逻辑说明:requirements.txt 里排好了核心依赖的版本范围,直接安装即可。参数说明:其中 torch 和 torchvision 的版本需要和本机 CUDA 匹配,建议先用nvidia-smi查看驱动支持的 CUDA 版本,再装对应版本的 PyTorch;装错的表现是torch.cuda.is_available()返回 False,后续所有训练命令都会跑在 CPU 上,慢得让人怀疑人生。
装完环境后先跑一行验证,输出 True 再继续,False 就回去查 CUDA 版本。钢材图像处理相对耗时,CPU 推理一张 640x640 图要几百毫秒甚至一秒多,GPU 上可以压到几十毫秒。这一步虽然简单,但能避免后面所有命令都跑在错误环境里,属于最值得花一分钟做的检查。
3.2 修改数据配置与模型配置:两个必改的 yaml 文件
YOLOv7 训练需要两个 yaml:一个描述数据集的 data yaml,一个描述网络结构的 cfg yaml。data yaml 里要写明 train 和 val 的图片目录路径、类别数量 nc、类别名字列表 names。钢材六类缺陷的典型写法:
train: ./datasets/steel/images/train val: ./datasets/steel/images/val nc: 6 names: ['crazing', 'inclusion', 'patches', 'pitted_surface', 'rolled_in_scale', 'scratches']逻辑说明:train 和 val 指向图片目录,YOLOv7 会依据同名规则自动到 labels 目录找对应 txt 标注;nc 必须等于 labels 里最大类别 ID 加 1;names 的顺序就是推理时显示的标签顺序,和标注 txt 里的类别 ID 一一对应。参数说明:路径建议写相对路径,然后从 YOLOv7 代码根目录执行训练命令,否则换机器后绝对路径失效,报 FileNotFoundError,排查起来很费时间。
模型配置文件只改一个关键点:把 nc 改成你的类别数量。在 cfg/training/yolov7.yaml 里找到nc: 80这一行,改成nc: 6,其余结构不要动。注意有些项目会额外调 depth_multiple 和 width_multiple 两个缩放系数,钢材缺陷目标相对小且细长,不建议调小模型宽度,保持默认 1.0 即可。
3.3 启动训练:batch、epoch 与图像尺寸怎么定
一切就绪后的训练命令长这样:
python train.py \ --data data/steel.yaml \ --cfg cfg/training/yolov7.yaml \ --weights yolov7.pt \ --batch-size 16 \ --epochs 200 \ --img-size 640 \ --workers 4 \ --device 0逻辑说明:train.py 会根据 cfg 里的 nc 自动调整输出层,加载 yolov7.pt 时跳过尺寸不匹配的 head 层。参数说明:batch-size 受显存限制,8GB 显卡建议 8 或 16,溢出时优先降到 8 而不是换更小的模型;epochs 在钢材小数据集上我一般设 200 起步,如果第 150 轮之后 val mAP 还在涨就继续加;img-size 用 640,除非缺陷目标特别细小且显存紧张,否则不建议降到 512,因为裂纹和划痕这类细长目标在低分辨率下特征会丢失;device 0 表示第一块 GPU,多卡时写成 0,1 这样的形式。
训练中断续跑是钢材项目里很容易遇到的操作。训练到一半断电或显存溢出,不要从头再来,YOLOv7 支持断点续训:
python train.py --resume runs/train/exp/ --data data/steel.yaml参数说明:resume 指向训练输出目录,代码会自动读取 last.pt 中保存的 epoch、优化器状态和超参数。继续训练时不需要再传 cfg、weights 和 batch-size,以 last.pt 里的记录为准。这里要特别提醒:如果中途改过数据集划分或类别顺序,不要 resume,否则会把新旧标签混在一起,训练结果完全不可信。
3.4 训练日志怎么看:loss、mAP 与过拟合信号
训练一启动,终端会滚动打印每个 epoch 的 box loss、obj loss、cls loss、val 指标和 mAP。钢材缺陷场景里,我习惯重点看三个信号。
第一是 box 和 obj loss 的下降是否平稳。正常情况前 20 个 epoch 下降很快,之后变缓;如果 loss 曲线剧烈震荡或卡在同一个水平线不下来,多数是数据集问题——标注错乱、类别不平衡过于极端,或者图片尺寸与 bbox 归一化不匹配。
第二是 mAP@0.5 和 mAP@0.5:0.95 之间的差距。钢材缺陷检测最终对框的位置精度要求因场景而异:只看有没有缺陷,mAP@0.5 够了;要做缺陷定位和分类,mAP@0.5:0.95 更有参考价值。两类指标都持续上涨说明正常;若 mAP@0.5 高但 0.5:0.95 低,说明框的位置不稳定,模型对细长目标的定位能力不足。
第三是过拟合信号。钢材数据集小,过拟合非常常见。当 train loss 还在下降但 val loss 开始回升、mAP 指标开始抖动,就是典型过拟合前兆。处理手段按优先级排列:先加一点随机光照扰动和旋转增强,再考虑 dropout 或扩充数据集,最后才是缩短 epochs。不要一上来就换网络结构,YOLOv7 在钢材小数据集上过拟合,绝大多数是数据多样性不足引起的。
4. 钢材缺陷权重怎么用:推理、导出与部署三条路径
4.1 用训练好的权重跑单张图片和离线视频推理
训练结束后,runs/train/exp/weights 目录下会有 best.pt 和 last.pt,通常用 best.pt 做推理,因为它是验证集上指标最高的权重。离线推理一条命令即可:
python detect.py \ --weights runs/train/exp/weights/best.pt \ --source test_images/ \ --conf-thres 0.4 \ --img-size 640 \ --save-txt逻辑说明:detect.py 会逐张处理 source 目录下的图片,绘制检测框并把结果保存到 runs/detect/exp 下。参数说明:conf-thres 默认 0.25,但钢材缺陷检测现场误检比漏检更让质检员反感,建议从 0.4 起步调整;save-txt 会额外输出每张图的检测结果 txt,里面是类别 ID 和坐标,方便后续做数据回流或二次统计。
推理结果里最容易出问题的是类别 ID 和 names 的对应。如果你用的是别人训练的钢材缺陷专用权重但没有同步他的 names 列表,模型输出的「class 0」可能不是你以为的第一类缺陷。所以我拿到任何陌生权重后,第一件事永远是拿几张已知缺陷的图片先跑一遍,确认类别映射正确后再谈批量推理。
还要注意 NMS 对交叉缺陷的影响。钢材表面裂纹和划痕经常同时出现,两者在图像上可能交叉,默认 NMS 阈值有可能把其中一条抑制掉,导致漏检。遇到这种情况,可以微调 NMS 的 IoU 阈值,看看哪一类更容易被抑制;我在现场通常从默认值开始,用同一批测试图做多组对比后确定。
4.2 导出 ONNX 与 TensorRT:产线部署的常见做法
离线推理只是验证权重可用,产线部署几乎都要转成 ONNX 或 TensorRT 格式。YOLOv7 提供 export.py,常见导出命令如下:
python export.py \ --weights runs/train/exp/weights/best.pt \ --img-size 640 \ --batch-size 1 \ --simplify逻辑说明:export.py 会把 PyTorch 权重转换成 ONNX 格式,输出的 best.onnx 可以直接用 ONNX Runtime 或 TensorRT 加载。参数说明:simplify 会去掉 ONNX 图里多余的计算节点,减小体积并提升推理速度;如果你的部署端输入尺寸固定,就不要加 dynamic 参数,这样导出的图会更利于推理引擎做优化。
| 部署格式 | 精度损失 | 加载方式 | 适合阶段 |
|---|---|---|---|
| PyTorch 权重 | 基准 | detect.py / 自定义脚本 | 算法验证 |
| ONNX | 极小 | ONNX Runtime | 跨平台验证 |
| TensorRT FP16 | 可接受 | trt 引擎文件 | 产线正式部署 |
TensorRT 引擎和显卡型号、驱动版本强绑定,在一台机器上生成的文件换到另一台机器上往往不能直接加载。所以在工厂部署时,我一般把 ONNX 作为通用中间格式,到每台工控机上再各自生成 trt,而不是拷贝一份引擎文件到处用。转换时指定 FP16 精度,在工业相机常用的 640x640 输入下,单张推理延迟能显著低于 PyTorch 原始权重。
4.3 权重文件校验:别把坏权重直接上产线
权重文件损坏这件事比想象中常见。从协作工具下载的权重可能只下载了一半,也可能别人用不同版本训练,直接加载会报各种奇怪错误。上产线前我会固定跑一遍完整性检查:先看文件体积是否明显偏小或为 0KB,再加载权重检查 state_dict 的模块数量是否合理,最后拿至少 20 张覆盖全部缺陷类别的样图做推理,统计每类的检出数和置信度分布。
import torch ckpt = torch.load("best.pt", map_location="cpu") model_state = ckpt["model"] if "model" in ckpt else ckpt["state_dict"] count = sum(1 for k in model_state if "anchor_grid" not in k) print("模块数量:", count)逻辑说明:torch.load 加载权重后,统计 state_dict 里非 anchor_grid 的模块键数量,确认文件里保存的结构信息是否完整。参数说明:如果模型配置是 YOLOv7 基础版,模块数量通常在 360 到 365 之间;如果少了 20 个以上,说明权重可能来自旧版本或不同配置,加载时容易出问题。
校验这一步虽然不增加任何功能,但能避免在产线调试时浪费几个小时才发现是权重文件本身的问题。我自己的习惯是:任何新拿到的权重,先在校验脚本上过一遍,再做推理测试,最后才谈部署。运行完校验后,如果每类缺陷都有检出且平均置信度在 0.5 以上,权重基本健康;比如裂纹类平均置信度只有 0.1,说明模型对这个类几乎失效,优先排查类别映射是否错位,或者训练样本里裂纹数量是不是太少。
5. 避坑指南:YOLOv7 钢材缺陷检测的 5 条踩坑记录
5.1 表面划痕与背景纹理混淆:数据增强的双刃剑
现象:训练时 mAP 很高,但一到现场就大量误检,把钢材表面的轧制纹理、水渍误报成划痕,质检员一天能标记几百个假框。
原因:钢材表面背景纹理复杂,训练时开了较强的 Mosaic 增强,拼接图之间的边界会产生伪纹理,模型学到了「纹理差异等于缺陷」的错误关联。现场钢种换一批,背景纹理一变,误检立刻爆发。
解决:先关闭 Mosaic 增强,或只在训练前半程使用,后半程关闭让模型收敛到真实缺陷特征。划痕类别要单独控制随机旋转和裁剪的角度范围;划痕有明确的方向性,旋转 90 度语义仍然正确,但旋转 45 度会让模型学出大量虚假的交叉划痕。
验证:关闭增强后跑一遍同样的验证集,对比误检框数量,通常现场误检能降低一半以上。这条坑踩过之后,我养成的习惯是:任何钢材项目的数据增强都要按类别单独评估,而不是全套默认配置直接用。
5.2 loss 在降但 mAP 不动:anchor 尺寸与缺陷尺度的错配
现象:训练日志里 box loss 和 obj loss 稳定下降,但 val mAP 一直在 0.5 附近波动,怎么调参数都上不去。
原因:YOLOv7 默认 anchor 是针对 COCO 目标分布的,而钢材缺陷里划痕是极端细长框,氧化皮是大而扁的框,默认 anchor 的表征能力覆盖不了这些形状,模型定位能力受限。
解决:训练前用 k-means 聚类工具对训练集标注框重新生成 anchor,替换 cfg 文件里的 anchor 配置。聚类时 anchor 数量按目标分布复杂度来定,默认 9 个够用。聚类后的 anchor 值如果与默认值相差 2 倍以上,说明数据集目标尺度确实特殊,这个调整有必要。每次数据集更新后都要重新聚类一次,不要沿用旧项目的结果。
验证:重新聚类后重训,观察 mAP 是否有明显回升。这条坑踩过之后,我的习惯是数据准备阶段就先生成 anchor 分布图,看一眼目标框的长宽比分布再决定要不要改配置。
5.3 训练中途显存溢出:batch size 与图像尺寸的平衡
现象:训练命令刚跑完第一个 epoch 就报 CUDA out of memory,程序直接退出,之前白跑的时间全部浪费。
原因:显存不足,最常见的是 batch size 设太大,或 workers 数量过高导致数据加载时系统内存被吃满,GPU 反而在空等。
解决:把 batch-size 从 16 降到 8 再试,还不够就降到 4;如果检测目标不是极端细小,可以尝试把 img-size 从 640 降到 512,显存占用会明显下降。注意不要同时把 batch 和图片尺寸都降到极低,否则模型学习不稳定。开启--cache-images参数把图片预加载进内存能提升训练速度,但如果数据集太大,系统内存会被占满,反而触发另一种溢出。
验证:在 4GB 显存机器上训练时,可以关闭 cache-images 并把 workers 降到 2,训练速度慢一点但能跑通。这条的教训是:显存不足时优先降 batch,不要动模型结构,改模型结构会让后续部署链路全部重来。
5.4 验证集 mAP 高但现场误检多:光照迁移导致的场景失效
现象:验证集上 mAP 达到 0.8 以上,拿到产线相机上运行时漏检率骤增,检测框乱跳,同一个缺陷白天能检出来晚上就检不出来。
原因:训练数据采集自实验室或特定光照条件下的静止样本,产线相机是流水线动态拍摄,光照变化、运动模糊、镜头畸变都会造成分布漂移,验证集指标不能代表真实场景性能。
解决:数据扩充时特意加入现场采集样本,同一缺陷至少覆盖暗光、强光、反光三种情况;训练时开启颜色扰动增强并适当加大幅度。如果现场样本收集困难,先做推理置信度统计,确定哪些类别在低置信度区间分布密集,再针对性地补数据。
验证:把现场采集的图片单独做成一个测试集,每次训练完都跑一遍,用这个现场测试集的指标来评估,而不是只看数据集的 mAP。这条坑让我明白,验证集只是训练过程的信号,现场测试集才是真正决定上不上线的标准。
5.5 加载权重报错 key 不匹配:版本与类别数的双重陷阱
现象:加载 yolov7.pt 微调时终端报 unexpected or missing keys,或者直接抛 RuntimeError,训练无法启动。
原因:两种情况最常见——一是用了与当前代码版本不匹配的权重文件,结构字段名对不上;二是改了 nc 之后 head 层前的输出层尺寸不一致,加载时 shape mismatch。
解决:确认权重文件与代码版本匹配,用对应发布页的预训练权重;改 nc 后看到部分 missing keys 不要慌,这是正常现象,关键是确认除了 head 层之外没有大面积 key 丢失。大批 key 丢失就检查 cfg 文件是否被改动了通道数相关参数。
验证:加载后跑一轮推理,对比一张已知缺陷图的检测框位置和类别,确认输出数值合理。还有一种情况是权重文件用了 EMA 平均参数,而代码加载时走了普通参数路径,两者指标略有差异;遇到加载后指标比报告低时,检查是不是这个问题,不要急着重新训练。
6. 最后的进阶手法:给钢材缺陷权重加一道产线自检保险
6.1 一个最小自检脚本:每班次验证权重健康度
权重在产线上跑久了,数据分布会漂移,旧权重可能悄悄退化。与其等质检员投诉,不如每班次自动跑一个快速自检:准备一组固定的验证样本,推理后检查每类的平均置信度是否低于阈值,低就触发告警。
import torch import glob model = torch.hub.load("你的YOLOv7代码目录", "custom", path="best.pt", source="local") images = glob.glob("qa_set/*.jpg") conf_map = {} for impath in images: results = model(impath) for det in results.xyxy[0]: cls_id = int(det[5]) conf = float(det[4]) conf_map.setdefault(cls_id, []).append(conf) for cls_id, confs in conf_map.items(): avg = sum(confs) / len(confs) if avg < 0.3: print(f"类别 {cls_id} 平均置信度偏低: {avg:.2f}")逻辑说明:脚本对固定的 qa_set 目录逐张推理,按类别统计平均置信度,低于阈值就输出告警。参数说明:qa_set 的选择是关键,每类至少 5 张典型缺陷图,且覆盖不同光照条件;阈值 0.3 是从经验值起步,根据现场正常权重运行时的统计结果来调整。这套小工具不用写进框架,任何时候权重被替换或环境变化,跑一遍就能发现问题。
6.2 用蒸馏把大权重压成轻量模型:实时检测的另一条路
如果产线对帧率要求高,原始权重在低端工控机上跑不满需求,可以考虑把训练好的大模型作为教师网络,蒸馏到一个更轻量的学生结构上。常见做法是用教师权重对无标注的现场图像生成 soft label,再和真实标注混合训练学生网络。钢材缺陷类别少、特征集中,这个做法在小数据集上往往比直接训练小模型更稳。蒸馏后推理耗时通常能明显下降,mAP 损失在可接受范围内,对产线质检来说是划算的交换。
我养成了一个习惯:每次训练完成,顺手保存一组现场验证图的检测结果和置信度分布摘要。这样权重有没有退化、是不是该重新采集数据,看一眼摘要就知道,不用再翻旧日志。希望这些经验能帮你在钢材缺陷检测这条路上少走几步弯路。
本文还有配套的精品资源,点击获取