news 2026/9/23 15:19:23

YOLOv11零件表面缺陷检测实战:从数据标注到TensorRT部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLOv11零件表面缺陷检测实战:从数据标注到TensorRT部署

简介:面向工业质检从业者与计算机视觉学习者,这份《工业质检新突破-基于YOLOv11的零件表面缺陷检测实战教程》PDF系统讲解了如何使用YOLOv11实现零件表面缺陷检测。内容从传统质检局限切入,涵盖YOLO系列演进、YOLOv11架构、数据标注与增强、模型训练调优、评估指标、部署落地及汽车零部件等真实场景案例,适合希望掌握单阶段目标检测并快速落地工业项目的读者。资源为单个PDF文件,压缩包大小2.14MB,共36页并支持目录跳转与大纲定位,文字图表完整清晰。目前已有113人浏览学习。文档不仅梳理了YOLOv11的核心机制与训练流程,还提供了数据清洗、增强、迁移学习微调、评估优化、本地/云端/边缘部署及可视化分析等实操思路,可帮助读者降低试错成本,构建一套可参照的工业缺陷检测解决方案。

1. 一份零件缺陷检测实战路线:为什么先选 YOLOv11

产线质检老师傅拿着强光手电一枚枚翻零件表面找划痕、压伤、毛刺,是很多中小工厂的常态。疲劳导致漏检、标准不统一、招不到人,这三件事几乎是所有想上视觉质检团队的共同痛点。基于 YOLOv11 的零件表面缺陷检测,最近在工业质检圈讨论度很高,原因是它把一阶检测器的训练门槛和部署友好度压到了一个比较低的水平:不需要自己设计网络,数据准备好之后用官方训练脚本就能跑通,推理端也支持 ONNX、TensorRT 导出。这套实战教程要解决的就是“从一堆缺陷图片到产线上一条稳定可用的检测流”这个完整过程。比较反直觉的一点是,这类项目真正翻车的地方往往不在模型,而在数据标注和验证集划分上。

2. YOLOv11 网络结构里,哪些设计对工业缺陷检测真正有用

2.1 从 YOLOv8 到 YOLOv11:结构演进与工业场景的匹配点

YOLOv11 是 ultralytics 在 YOLOv8 基础上继续迭代的检测框架版本,熟悉 YOLOv8 的工程师迁移过去几乎不需要改习惯,因为入口 API、数据集组织方式、训练参数风格完全一致。这恰恰是工业质检团队最看重的一点:换模型不动整套流程,试错成本非常低。

从网络结构角度看,YOLOv11 延续了 anchor-free 的设计思路,同时把主干网络里的部分 C2f 模块替换成了带有注意力机制的轻量结构,骨干网络末段对多尺度特征的提取更充分。anchor-free 对缺陷检测有一个隐藏优势:缺陷目标的形状极不规则,比如一条弯曲的划痕、一块不闭合的压伤,anchor-free 不需要人为预先设计锚框的宽高比,模型直接从特征图上回归目标中心与边框,减少了规则先验对不规则缺陷的约束。对工业场景来说,不需要像早期 Faster R-CNN 那样针对每一种缺陷形态重新聚类 anchor,省掉了一轮调参。

另一个值得关注的改动是损失函数和训练策略的优化。YOLOv11 的边界框回归在默认设置下收敛更平稳,对高分辨率输入的支持也比前代友好。做零件表面缺陷检测时,工业相机拍出来的图经常是 500 万像素起步,甚至直接上 1200 万像素,模型需要能扛住大图输入,YOLOv11 在这方面的训练显存占用和推理耗时都比同体量的两阶段模型更可控。

真正驱动大家升级到 YOLOv11 的原因还有一个生态因素:周边工具链完善。训练、验证、剪枝、导出、部署的路径在同一个框架内闭环,不需要把模型文件在不同工具之间来回搬运。这对工程师而言意味着问题好排查,模型出了问题能快速定位是训练环节还是推理环节。

2.2 小缺陷为什么难检测:语义特征与分辨率博弈

零件表面缺陷检测和通用物体检测有一个明显区别:缺陷目标通常非常小。一条细划痕可能在整幅图中的宽度只有 10 到 20 个像素,一个针孔缺陷可能只有几个像素,这类目标属于典型的小目标检测问题。

小目标困难的本质在于,深度卷积网络通过逐层下采样提取高维语义特征,但下采样倍数越大,小目标在特征图上的响应越弱。YOLOv11 的主干网络通常会进行 32 倍下采样,一个 16 像素宽的缺陷经过下采样后,在最高层特征图上只剩半个像素的响应,几乎不可能被检测头感知。这也是为什么在工业缺陷检测里,单纯最求模型的“大”没有意义,真正决定小缺陷能不能被召回的是输入分辨率和特征层的匹配关系。

工程上判断缺陷是否属于“危险的小目标”,有一个简单的经验标准:缺陷的长边像素数除以输入图像尺寸,结果小于 1/32 就要警惕。比如使用 640 分辨率训练,缺陷长边小于 20 像素,就必须采取针对性措施。常见做法是提升输入分辨率,把 imgsz 从 640 调到 1280 甚至更高,代价是显存占用上升、训练速度下降;另一个做法是使用切图策略,把高分辨率工业图切成多个子图送入模型推理,这也是后面章节会展开的内容。

还有一个容易忽略的维度是缺陷的语义特征。通用目标如“人”“车”有清晰的类别语义,而划痕、脏污、轻微的压伤在特征图上看起来可能非常接近正常表面的纹理变化。模型需要更多的底层纹理信息来做出判断,这也是为什么缺陷检测模型常常在浅层特征图上表现更敏感。YOLOv11 的多尺度检测头融合了浅层和深层特征,但融合的充分程度仍然受限于训练数据的丰富度。

2.3 迁移学习与预训练权重选哪个:yolov11s 还是 yolov11m

YOLOv11 官方提供了 n、s、m、l、x 几个不同规模的预训练权重,工业质检项目里最常用的两个是 s 和 m。选型逻辑主要看推理部署的目标硬件和单张图像上需要检测的缺陷数量。

yolov11s 是性价比最高的选择。它体积小、推理延迟低,在一张入门级工控显卡上处理 640 分辨率图像能跑到较高帧率,适合产线节奏较快的场景。如果缺陷类型少、形态相对固定,用 s 型号在充分训练后通常能获得不错的精度。

yolov11m 的容量更大,特征表达能力更强,适合缺陷形态复杂、类别多、缺陷之间相似度高的场景。比如同时存在划痕和擦伤这两种容易混淆的缺陷,m 型号在区分细粒度差异上会更有优势。代价是显存占用量大约上升一倍,推理延迟也明显增加。在 1200 万像素工业图像上做切图推理时,m 型号的吞吐量可能会成为瓶颈。

一个常被问起的问题是:预训练权重是在 COCO 数据集上训的,里面根本没有“划痕”“压伤”这些类别,迁移学习还有效吗?答案是仍然有效。因为预训练模型学到的是通用视觉特征,比如边缘响应、纹理结构、颜色分布等等,这些底层特征在工业缺陷上同样适用。训练时不需要冻结主干,直接把全套权重加载进来做整体微调,在缺陷数据量不太大的情况下也能较快收敛。

3. 缺陷数据从哪来:样本采集、合成缺陷与 VOC 转 YOLO 格式脚本

3.1 真实缺陷样本永远不够:三类数据来源怎么组合

工业质检项目启动时遇到的第一道坎通常不是模型,而是数据。一条产线刚开始做视觉检测时,良品可能是海量的,但缺陷品少得可怜。一个真实项目里,可能连续收集一个月才攒了几百张带缺陷的图,而深度学习目标检测在这个数据量级下,很难训练出稳定的模型。

常见的三类缺陷数据来源里,第一是真实产线采集,这是最可靠的数据,需要在产线上增加图像采集工位,把人工检出和过程抽检中发现的缺陷品拍下来。第二是合成缺陷,用图像处理程序把划痕、脏污、压痕等效果人工贴到良品图上去。合成数据的量大、标注完全自动化,但模拟效果和真实缺陷之间存在分布差异,模型在合成数据上表现可能不错,到了真实场景准确率反而下降。第三是开源数据集,比如钢材表面缺陷数据集 NEU-DET、工业零件数据集 Kolektor 等,可以用于前期算法预研和流程验证,但不能替代工厂现场数据。

我的实际经验是:合成数据 + 真实数据的混合策略最有效。先用合成数据把整体 pipeline 跑通、把训练流程调稳,然后逐步加入真实缺陷数据做增量训练。合成数据负责让模型先学会缺陷的基本形态,真实数据负责纠正分布偏差。

合成缺陷的生成方式可以很简单地对一张良品图做随机扰动。比如生划痕时,沿随机方向绘制一条亚像素宽度的曲线,叠加亮度变化和高斯模糊;生脏污时,在随机位置粘贴带有边缘羽化的色斑。关键是要让合成缺陷在亮度、对比度、模糊程度上有足够的随机性,否则模型会学到合成痕迹本身的特征。

3.2 标注格式统一:把 VOC XML 转成 YOLO txt 的一次性脚本

缺陷数据的标注格式五花八门。很多工厂之前用过其他质检软件,导出的标注是 VOC 格式的 XML 文件,而 YOLOv11 使用的是每个图像一个同名 txt 文件的格式,每行记录一个目标的类别索引和归一化的中心坐标、宽高。如果不做转换,训练直接报错或者模型完全学不到东西。

以下是一个经过验证的转换脚本,读取 VOC 格式的 XML 标注目录,批量生成 YOLO 格式的标签文件:

import os import xml.etree.ElementTree as ET from pathlib import Path def voc_xml_to_yolo_txt(xml_path, out_dir, class_names): """ 将单个VOC XML标注转换为YOLO格式txt class_names: 类别名列表,索引即为YOLO类别ID """ 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) # 输出文件名与XML文件名保持一致,后缀改为txt txt_path = Path(out_dir) / (Path(xml_path).stem + ".txt") lines = [] for obj in root.iter("object"): name = obj.find("name").text if name not in class_names: continue # 类别索引从0开始计数 cls_id = class_names.index(name) # 解析边界框坐标(像素值) bndbox = obj.find("bndbox") xmin = float(bndbox.find("xmin").text) ymin = float(bndbox.find("ymin").text) xmax = float(bndbox.find("xmax").text) ymax = float(bndbox.find("ymax").text) # 转换为YOLO格式:中心点坐标 + 宽高,全部归一化到[0,1] x_center = ((xmin + xmax) / 2) / img_w y_center = ((ymin + ymax) / 2) / img_h box_w = (xmax - xmin) / img_w box_h = (ymax - ymin) / img_h lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}") with open(txt_path, "w", encoding="utf-8") as f: f.write("\n".join(lines)) # 批量转换整个标注目录 def batch_convert(xml_dir, out_dir, class_names): os.makedirs(out_dir, exist_ok=True) for xml_file in Path(xml_dir).glob("*.xml"): voc_xml_to_yolo_txt(str(xml_file), out_dir, class_names) print(f"converted: {xml_file.name}") if __name__ == "__main__": # 类别顺序必须与后续训练yaml中的names保持一致 names = ["scratch", "dent", "burr", "stain"] batch_convert("annotations/voc", "labels/yolo", names)

这段脚本有几个容易出错的地方。第一个是坐标转换必须用对应图片的真实宽高,有的标注工具导出的 XML 里图片尺寸与实际图片不一致,直接使用会在训练时产生错位的边界框。第二个是类别索引顺序,脚本里的 class_names 列表必须与后续训练配置 YAML 中的 names 顺序完全一致,否则类别信息全乱了。第三个是字典排序问题,glob 遍历 XML 文件顺序不受控,但输出 txt 与同名图片的对应关系不会乱,前提是 XML 的 filename 标签与图片文件名一致。

推荐在转换完成后做一个快速校验:随机打开几张图和对应的 txt 文件,把归一化坐标还原成像素坐标,用 OpenCV 画框检查是否贴住了缺陷位置。这个动作看起来多花几分钟,实际上能避免后面整个训练白跑一遍。

3.3 数据增强的边界:亮度、噪声与几何扰动怎么设

YOLOv11 训练时默认开启一系列数据增强策略,包括随机翻转、缩放、色域变换、马赛克拼接等。对自然场景的目标检测,这些增强策略大胆开没问题,但对工业缺陷检测不能直接照搬默认值。

工业质检有个特殊约束:零件表面的缺陷出现在特定方向上,与零件的加工纹理、装配方向强相关。比如一个轴类零件,划痕方向总是沿着轴向,如果开了 fliplr 水平翻转,模型会学到“轴向上可以有划痕,反方向也可以有”,在真实检测时可能对横向划痕也产生响应,造成误检。一般建议关闭 fliplr 或只在确定零件方向对称时开启。

颜色类增强参数 hsv_h、hsv_s、hsv_v 需要控制幅度。工业零件表面材质对光线敏感,球墨铸铁件表面本身就有明显的颜色变化,增强幅度过大反而会让模型忽略掉真正区分缺陷的纹理细节。建议色相偏移 hsv_h 设为 0.01 左右,饱和度 hsv_s 和明度 hsv_v 设在 0.2 以下。

马赛克增强 mosaic 对缺陷检测是双刃剑。它把四张图拼成一张,增加了背景多样性,但也可能把目标缺陷切在拼接缝处,导致小缺陷信息丢失。处理方式是降低 mosaic 的概率,或者在训练后期关闭它。ultralytics 框架里可以通过调整 mosaic 参数控制,比较保险的做法是前 60% 的 epoch 开启、后面关闭。

4. 从环境配置到训练自己的模型:YOLOv11 的完整跑通路径

4.1 YOLOv11 环境配置:conda 创建、显卡驱动与 ultralytics 安装

YOLOv11 环境配置是整个实战路线里看似简单、实际上最容易劝退新手的环节。大多数问题并不是出在 ultralytics 包本身,而是 PyTorch 和 CUDA 版本不匹配。配置环境的推荐路径是先用 conda 创建独立 Python 环境,避免污染系统环境。

# 创建独立的 Python 3.11 环境,避免污染系统环境 conda create -n yolo11 python=3.11 -y conda activate yolo11 # 先安装支持 GPU 的 PyTorch,注意按自己的 CUDA 版本选择 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 # 安装 ultralytics(YOLOv11 的官方训练框架) pip install ultralytics # 验证安装是否正常:跑一次官方权重推理 yolo predict model=yolo11s.pt source="https://ultralytics.com/images/bus.jpg"

这里两个关键决策点。第一个是 PyTorch 的安装源,不要直接 pip install torch 装 CPU 版本,要按本机 CUDA 版本去 PyTorch 官网选择对应的安装命令。第二个是验证命令,装完 ultralytics 之后立即用官方预训练权重跑一次推理,能确认显卡驱动、CUDA 运行时、PyTorch 三者是否打通。如果这条命令能正常输出检测结果图,环境就算准备好了。

很多项目卡在环境这一关,是因为盲目追求最新版本号。ultralytics 迭代很快,新版本可能会带来配置格式的变化。对于工业项目,建议安装稳定版本后不再频繁升级,优先保证训练脚本和推理脚本的可复现性。

4.2 数据集目录与 YAML 配置:直接对齐训练脚本的约定

ultralytics 框架对数据集目录有一定约定,按它的结构组织数据能省掉很多不必要的配置工作。目录结构如下:

dataset/ ├── images/ │ ├── train/ # 训练集图片 │ └── val/ # 验证集图片 ├── labels/ │ ├── train/ # 训练集标签(txt文件) │ └── val/ # 验证集标签 └── defect.yaml # 数据集配置文件

对应训练数据集配置文件 defect.yaml:

# 数据集配置文件,通过 data=defect.yaml 参数传给训练脚本 path: /home/user/dataset # 数据集绝对路径 train: images/train # 训练图片相对路径 val: images/val # 验证图片相对路径 nc: 4 # 缺陷类别总数 names: # 类别名列表,与转换脚本中的class_names顺序一致 0: scratch 1: dent 2: burr 3: stain

配置文件的要点在于 path 字段使用绝对路径,train 和 val 字段使用相对于 path 的相对路径。YOLOv11 加载数据时要求每张训练图片 dataset/images/train/xxx.jpg 对应同名的标签文件 dataset/labels/train/xxx.txt,文件名完全一致、扩展名不同。标签文件中没有标注的图片可以保留空的 txt 文件或不提供标签,模型会把它当作负样本处理。

在训练前可以用一句命令检查数据标注是否正确:

# 在图像上叠加显示标注框,检查标注是否贴合缺陷位置 yolo detect train data=defect.yaml model=yolo11s.pt epochs=1 imgsz=640

先跑 1 个 epoch,如果训练能正常启动且不报标签相关错误,再去跑完整训练。

4.3 训练命令与参数详解:imgsz、batch、epochs 和损失曲线怎么读

数据准备好之后,训练命令非常简洁。以下是一个在单张显卡上训练的基本命令:

yolo detect train \ data=defect.yaml \ model=yolo11s.pt \ epochs=200 \ imgsz=640 \ batch=16 \ workers=8 \ patience=30 \ device=0 \ project=runs/train \ name=defect_yolo11s

几个关键参数的含义和设置逻辑:

imgsz 是训练时输入网络的图像边长。这个参数直接决定缺陷目标在特征图上的像素占比,如果缺陷细小,优先考虑提高 imgsz 到 1280 而不是增加模型容量。注意 imgsz 提高后显存占用按平方关系增长,batch 要相应调小。

batch 是批量大小,受显存限制。batch 太小会导致 BN 层统计量不稳定,训练震荡明显。常见的做法是先设一个较大的 batch,如果显存溢出报错,逐次减半直到训练能正常启动。

epochs 是训练轮数。工业缺陷数据集通常比较小,模型收敛速度反而快,一般 100 到 200 轮足够。关键要看损失曲线而不是死磕轮数。

patience 是早停参数,代表验证集指标连续多少轮不提升就停止训练。设置 20 到 30 比较合理,既能防止过拟合,又不会因为偶然波动过早停止。

训练过程中要关注输出日志里的损失值。box_loss、cls_loss、dfl_loss 三个值整体下降是正常的,如果某个指标出现“下降后反弹”的形态,说明学习率设置偏大或数据中有噪声标签。验证集指标出现持续不增长,而训练集损失还在下降,这是典型的过拟合信号,应该增加数据增强或加大 dropout。

另外建议保留训练日志文件,后面调整参数时可以对照比较,这个习惯能减少很多重复尝试。

4.4 小样本下的训练策略:数据不均衡与验证集划分

工业缺陷数据集中类别不均衡是非常普遍的现象。划痕类缺陷可能占总样本的 70%,而压伤类缺陷只有 5%。如果不做处理,模型会偏向学习样本量大的类别,小类别缺陷的召回率极低。

处理不均衡的常规手段是对少样本类别做过采样,在构建训练集时按类别比例复制少量类别样本。另一个有效的办法是调整类别损失权重,在 ultralytics 中可以通过配置 class weights 参数给少样本类别更高的损失贡献。实际项目中更常见的是组合使用:先过采样保证每个类别有足够参与训练的样本,再配合验证集指标观察少数类是否被充分学习。

验证集划分是另一个容易被忽略的细节。划分数据集时不能随机打乱,要按工件批次、产线班次来划分。同一批工件在相同的光照条件和加工参数下,表面纹理极其相似,如果一批工件中一部分进了训练集、一部分进了验证集,模型在验证集上的成绩会虚高。正确做法是按批次文件夹划分,比如 1 到 3 号批次的图片全部进训练集、4 号批次的图片全部进验证集,这样才能真实反映模型面对新批次工件时有没有泛化能力。

5. 缺陷检测实战避坑:训练和部署环节的 5 个真实翻车点

5.1 训练 loss 直接变 NaN,模型权重彻底报废

现象:训练启动后一切正常,大约几十个 iteration 后 loss 输出变成了 nan,训练进程不报错,但后续所有指标失去意义,最终保存的权重推理时输出全为零检测框。

原因:最常见的是学习率设置过大导致的梯度爆炸,特别是在小 batch 场景下,BN 层的统计量不稳定会进一步加剧。其次可能是训练数据中存在 NaN 像素值,比如某些 PNG 图像包含非法像素数据,或者标注文件中出现了超过图像边界的坐标值。

解决:检查学习率设置,如果手动调大过 lr 就恢复默认值;检查标签文件中的归一化坐标是否都落在 0 到 1 区间内;在数据加载代码里对图像做一次像素值合法性检查。最稳妥的做法是先关掉 AMP 混合精度,许多 NaN 问题在 fp16 下出现、切换到 fp32 后就消失,虽然训练速度会下降,但能快速定位问题范围。

5.2 验证集 mAP 很高,到了产线上误检多到没法用

现象:训练阶段的验证集 mAP 达到 0.95 以上,部署到产线后,把正常零件误判为缺陷的比例高得离谱,质检员需要不停复核模型结果,效率反倒不如人检。

原因:训练数据里的负样本严重不足。工业瑕疵往往出现在特定背景上,如果训练集中所有图片都是“有缺陷”或“有明显特征背景”的零件,模型会把这种背景特征当成判别依据,遇到没有见过的正常表面纹理变化时就会产生误判。

解决:在训练集中大量加入正常零件的图片,一张正常零件的图,对应生成一个空的 txt 标签文件即可。当负样本比例提升到缺陷样本的 2 到 3 倍后,误检率通常会明显下降。产线上线前还要专门采集一批“易混淆正常件”,这些表面纹理接近缺陷但实际合格,用于验证模型的泛化边界。

5.3 细划痕缺陷漏检严重,召回率不达标

现象:压伤、毛刺这类面积较大的缺陷检测效果很好,唯独细划痕几乎检测不到,训练时损失曲线看起来正常,但验证集上划痕类别的召回率可能只有百分之十几。

原因:划痕太细,在 640 分辨率下像素占比远低于检测器的敏感下限。模型训练时下采样后的特征图已经丢失了划痕信息,这不是训练不充分的问题,是输入信息不足的问题。

解决:优先把训练和推理的 imgsz 提升到 1280 甚至更高,同时把 mosaic 增强关闭,防止划痕在拼接过程中被截断。如果显存不够,把高分辨率缺陷图按划痕所在区域切成子图训练,推理时也用同样的切图策略。另一条思路是增加浅层检测头的权重,但实现复杂度高,一般不建议工业项目贸然尝试。

5.4 训练时 GPU 利用率很低,跑一个 epoch 要几个小时

现象:训练时显卡没有跑满,GPU 利用率在 30% 到 50% 之间徘徊,训练速度远低于预期,影响迭代效率。

原因:数据加载成为瓶颈。缺陷检测数据集的加载过程包含图像解码、尺寸缩放、数据增强等操作,这些都需要 CPU 参与计算。如果 workers 数量设置太小,图像处理跟不上 GPU 的消费速度,显卡就会处于等待状态。

解决:调大训练命令中的 workers 参数,通常建议设置为 CPU 核心数的一半或三分之二。同时确保图片存储在本机固态硬盘而不是网络磁盘上,网络文件系统的延迟会显著拖慢数据加载。如果还不行,可以用 nvidia-smi 监控训练时的显存和显卡利用率,确认瓶颈位置后再做针对性优化。预加载数据的方式适合小数据集,但显存占用大,需要量力而行。

5.5 标签坐标没归一化,所有检测框堆在左上角

现象:训练能正常完成,loss 值也不高,但用模型预测时,所有缺陷框都集中在图像左上角区域,完全不符合真实缺陷分布。

原因:标签格式转换脚本出错,最常见的是直接把 VOC 中的像素坐标当作 YOLO 格式的归一化坐标写入 txt,没有除以图片宽高。模型读入标签时,将 0 到 1 区间外的坐标截断,导致大量标注框被硬压缩到图像的左上角。

解决:检查一个代表性标签 txt 文件里的坐标值,如果出现大于 1 的数字,说明没有做归一化。对照第 3 章的转换脚本,确认转换逻辑中的除法没有遗漏,重新生成全部标签后,在训练前用可视化脚本把标注叠加到图片上逐张检查。标注问题越早发现越省时间,等模型训练完才查,几天的迭代就白费了。

6. 预测后保存与产线部署:把 best.pt 变成一条稳定可用的检测流

6.1 预测后保存结果:单张图、批量推理与结果解析

训练完成后,推理与保存结果是每天都用得到的操作。YOLOv11 的预测 API 支持批量处理目录内的全部图片,并自动保存带检测框的结果图。

from ultralytics import YOLO # 加载训练得到的最优权重 model = YOLO("runs/train/defect_yolo11s/weights/best.pt") # 批量推理目录下所有图片,并保存结果图与标签txt results = model.predict( source="test_images/", # 测试图片目录 conf=0.35, # 置信度阈值 iou=0.5, # NMS的IoU阈值 imgsz=640, # 推理输入尺寸 save=True, # 保存带检测框的结果图 save_txt=True, # 保存检测结果到txt文件 save_conf=True, # 在txt中同时保存置信度 project="runs/detect", # 输出根目录 name="defect_test", # 输出子目录名 exist_ok=True, # 允许覆盖已存在的同名目录 ) # 在代码中精确控制结果 for r in results: for box in r.boxes: cls = int(box.cls[0]) # 类别索引 conf = float(box.conf[0]) # 置信度 xyxy = box.xyxy[0].tolist() # 左上角右下角像素坐标 print(model.names[cls], conf, xyxy)

save_txt 保存的标签文件与训练标签格式相同,每行是“类别 置信度 x_center y_center width height”的格式,方便下游质检系统直接读取。save 保存的结果图会叠加绘制检测框和类别标签,方便人工复核。这里 conf 阈值设置需要说明:离线测试时可以把置信度阈值设低一些,以便观察模型所有可能的输出;上线部署时再根据产线要求的误检率去回调阈值。

6.2 大图切块推理:不换模型也能救回小缺陷

工业相机拍出的原图分辨率往往远超训练时的输入尺寸,直接把原图缩放后送入模型,小缺陷会被压缩到几乎不可分辨。切块推理是既不换模型、又能保住小缺陷的通用方案。

切块策略的三个参数是切块尺寸、重叠率、缩放方式。切块尺寸一般取训练 imgsz 的 1 到 2 倍,重叠率取 10% 到 20%,防止缺陷恰好被切在边界上导致漏检。512x512 切块适合缺陷密集的小零件,1280x1280 切块适合整体检测且缺陷相对较大的场景。

切块尺寸重叠率适用场景
512x51220%小零件、缺陷密集、需要精确定位
640x64015%与训练输入一致,通用场景
1280x128010%大零件、缺陷尺寸相对较大

切块推理后需要把每个子图的检测框坐标换算回原图坐标,然后统一做一次 NMS 去重,合并重叠区域重复检测到的目标。这个流程实现起来不复杂,但对弱纹理零件表面效果明显,是许多实战教程里最常用的“后悔药”方案。

6.3 导出模型到 TensorRT:部署端的参数优化与验收

训练和验证都达到要求后,要把 PyTorch 权重导出为部署格式。TensorRT 相比 ONNX Runtime 在 GPU 上通常能获得更好的推理性能。

# 导出为 TensorRT 引擎文件,启用半精度加速 yolo export model=runs/train/defect_yolo11s/weights/best.pt format=tensorrt imgsz=640 half=True

导出完成后,用测试集重新推理一次,对比 TensorRT 引擎和 PyTorch 权重的检测结果是否一致。由于半精度带来的数值误差,少量检测框的置信度会有细微变化,这是正常现象。部署验收时还有一个细节:产线上的置信度阈值不能直接照搬训练时的设定,应该根据三类指标重新标定,每类缺陷的误检率和漏检率分别统计,取两者交叉点上合适的阈值。

关于阈值标定,我自己的习惯是记录批量测试样本中每个检测框的置信度,按类别分桶统计,画出每个缺陷类别的分布曲线,再与产线可接受的误检率做匹配。这个动作虽然枯燥,但能避免上线后频繁调整参数。另外每次训练前固定随机种子,同时保留 best.pt 和 last.pt 两个权重文件,万一训练后期过拟合,last.pt 还能当一次后悔药。希望这些实战中攒下来的经验帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 15:19:24

5道高频面试题拆解东京都和东京的区别

5道高频面试题拆解东京都和东京的区别 报错一堆看不懂 StackTrace,面试问到行政区划直接懵圈?别慌。 这其实是很多非文科背景开发者的盲区。 东京都和东京的区别 ,看着像文字游戏,实则是考察你对日本行政体系、数据建模乃至国际化业务逻辑的理解深度。 在各大厂后端或中台开发的 高频面试题…

作者头像 李华
网站建设 2026/9/23 15:19:12

吸引人的标题手写实现

手写LRU缓存:3道高频面试题,打通底层逻辑 看了一堆教程还是不会写项目?别慌,这不是你的错。很多开发者卡在“懂原理”和“能落地”之间,面试时一提到 高频面试题 里的 LRU 缓存,脑子里全是概念,手却写不出代码。今天不讲虚的,直接拆解 LRU…

作者头像 李华
网站建设 2026/9/23 15:19:06

3个步骤搞定红楼梦人物分析,面试必问不踩坑

3个步骤搞定红楼梦人物分析,面试必问不踩坑 版本升级后 API 全变了,你还在死记硬背?别慌。 这是大厂面试里的高频坑,也是【红楼梦人物分析】这类文本处理题的核心考点。很多转岗开发者栽在这里,以为只是简单的字符串匹配,结果一上手发现数据结构复杂、依赖库版本不兼容,当场卡壳。…

作者头像 李华
网站建设 2026/9/23 15:18:45

别瞎猜了,一文搞懂GMSK:从原理到代码实战

别瞎猜了,一文搞懂GMSK:从原理到代码实战 看了一堆教程还是不会写项目?这是不是你的常态?资料满天飞,视频看了十遍,一到自己动手写个调制解调器,脑子就一片空白,报错满天飞。别慌,今天咱们不整那些虚的,直接上手,用代码把 GMSK 这块硬骨头啃下来。…

作者头像 李华
网站建设 2026/9/23 15:18:40

银行从业资格证含金量图解:3步吃透价值与考法

银行从业资格证含金量图解:3步吃透价值与考法 刚啃完《Java编程思想》或《Python Crash Course》,对着IDE敲代码心里有底,但一让搭个完整项目,脑子瞬间宕机。这是无数开发者的通病: 学会语法却不知怎么搭项目 。很多人把时间耗在刷题上,却忽略了底层逻辑的构建。今天不聊虚的,直接用…

作者头像 李华