恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
YOLOv11工业零件缺陷检测实战:从数据标注到ONNX部署全流程
首页
资讯中心
/
YOLOv11工业零件缺陷检测实战:从数据标注到ONNX部署全流程
YOLOv11工业零件缺陷检测实战:从数据标注到ONNX部署全流程
发布时间:2026/10/5 2:45:15
简介面向工业质检与计算机视觉开发者的一份完整实战教程PDF格式共36页系统讲解YOLOv11在零件表面缺陷检测中的应用。内容涵盖工业质检背景、YOLO系列演进、YOLOv11架构、数据准备与增强、模型训练与微调、评估指标与优化策略以及从项目搭建到部署的完整流程。通过实际工业场景案例进行结果可视化与效果分析帮助读者掌握从数据标注到模型上线的全链路方法。资源包共1个PDF文件大小2.14MB支持目录章节跳转及阅读器大纲定位阅读体验完整。已有113人学习下载适合希望提升检测效率与精度、入门或进阶YOLOv11的目标检测学习者和工业质检工程师。1. 生产线上的人工质检正在被YOLOv11改写一条3C零件产线质检员每天盯着几千个零件表面找划痕、凹坑和裂纹连续工作两小时后漏检率明显上升。YOLOv11作为ultralytics新一代目标检测模型在保持轻量化的同时把精度往上推了一截让“用一套模型在普通工控机上跑缺陷检测”变成了现实。这份实战笔记不是科普是我按YOLOv11训练零件缺陷检测模型的全过程记录环境配置、数据集转换、训练调参、踩坑记录到最终部署验证。适合刚接手质检自动化项目的工程师也适合想搞清楚YOLOv11和上一代模型差在哪的算法同学。2. YOLOv11的环境配置与网络结构决定后面顺不顺的两件事2.1 用ultralytics跑通最小环境0基础也适用的命令序列先说结论YOLOv11不需要从源码编译ultralytics包已经把训练、验证、预测、导出全部封装成命令行接口。我一般会新建一个干净的conda环境来跑避免和项目里其他深度学习框架的依赖冲突——这是以前被折磨过才养成的血泪经验。# 创建并激活独立环境避免依赖冲突 conda create -n yolo11 python3.10 -y conda activate yolo11 # 安装ultralytics会自动带上pytorch和opencv pip install ultralytics # 验证环境会自动下载yolo11n.pt预训练权重 yolo predict modelyolo11n.pt sourcehttps://ultralytics.com/images/bus.jpg第一行创建名为yolo11的conda环境Python版本3.10-y跳过确认提示。第二行激活这个环境。第三行安装ultralytics它会自动把pytorch、torchvision、opencv等依赖装好不需要手动单独装。第四行是验证命令yolo predict会下载yolo11n.pt权重文件然后对一张示例图片做推理如果终端里输出了目标框坐标说明环境通了。这里有两个参数要注意。第一个是yolo11n.pt中的n代表nano规格权重文件只有几MB跑起来快适合验证流程真正训练缺陷模型时换上s或m规格的预训练权重作为起点。第二个是source参数它可以是图片路径、视频路径甚至摄像头设备号source0表示调用第一个摄像头。如果机器有NVIDIA显卡建议先手动安装CUDA版的pytorch再装ultralytics训练速度快好几倍。工业现场多数工控机只有CPU推理一张图几秒做抽检够用但训练别指望CPU——一个epoch可能要跑一天。常见做法是训练放到有GPU的机器上做再把训练好的权重拷到工控机上推理。2.2 YOLOv11网络结构C3k2和C2PSA到底改了什么很多人直接用YOLOv11但说不清它比YOLOv8改了什么这在调参时会吃亏。YOLOv11网络结构延续了CSPNet的设计思路主要变化集中在两个模块上。第一个是C3k2模块它替代了YOLOv8里的C2f。C3k2在保持梯度流多样性的同时对每个阶段的卷积核大小做了更精细的选择用更小的计算量拿到了接近的通道表示能力。直观理解同样跑一遍前向传播v11的瓶颈层更轻模型在同等算力下能堆更多层。第二个是C2PSA这是一个带注意力机制的跨阶段模块借鉴了PSA的思想在特征图上做空间和通道维度的注意力加权。对缺陷检测来说这个改动很关键划痕和裂纹这类缺陷在图像里占比小注意力机制能让网络把计算资源往这些区域倾斜而不是平均撒在背景上。我实际对比过同一批零件数据上YOLOv8和YOLOv11的效果v11在mAP50上大概高0.5到1个点推理速度几乎没有差别。这个提升对比赛可能不重要但在产线上意味着每月少几十个漏检价值完全不一样。2.3 选n还是选x按产线硬件条件选模型规格YOLOv11提供n、s、m、l、x五种规格从nano到extra large参数量和推理延迟递增精度也跟着涨。工业缺陷检测的选型逻辑和通用目标检测不同产线节拍决定了单张图的推理预算工控机的显存决定了模型上限。我的建议分三步。第一步确定推理预算比如产线节拍是每秒处理两张单张推理必须在500ms以内。第二步在预算内选最大的先跑x看延迟超了就往下降。第三步用同一份验证集对比两三个规格的mAP和延迟选性价比最高的。不要一上来就选最大工业场景里精度差零点几个点远不如稳定运行重要。还有一个很容易被忽视的点权重文件下载。第一次跑yolo命令时ultralytics会自动从网上拉取预训练权重内网环境经常失败。常见做法是先把权重文件手动下载好放到执行目录或者配置镜像源。yolo11n.pt成功跑通后其余规格的下载逻辑相同把命令里的n换成s或m即可。提示训练用的权重和部署用的权重不是一个东西。训练用官方预训练权重当起点部署必须用自己训练出来的best.pt两件事别搞混。3. 把零件缺陷图片变成YOLO格式核心是你自己的数据3.1 缺陷类别怎么定先看产线上到底有哪些缺陷YOLOv11只是工具真正决定模型上限的是标注数据的质量。工业零件表面缺陷常见的有六类划痕、凹坑、裂纹、麻点、氧化、污渍。实际项目中我建议类别不超过五类类别越多所需样本量越大类别间边界也越容易模糊。举例来说划痕和裂纹在图像里都是细长条如果两类标注边界不统一模型训练时就会困惑损失曲线震荡不收敛。我见过一个项目把“轻微划痕”和“严重划痕”分成两类结果模型完全分不开。正确做法是合并成“划痕”一类严重程度留给后处理去判断或者对同一个类的置信度阈值分层。标注工具我一般用X-AnyLabeling它支持Pascal VOC和YOLO两种格式输出内置SAM辅助标注对零件这类背景相对单一的图像自动分割再手动微调效率很高。无论用哪个工具标注规范都要先写成文档边界框要框住缺陷完整区域小缺陷也要保证最小标注尺寸模糊不清的缺陷标不标要有统一规定。没有规范多人标注的数据就是灾难。3.2 从VOC标注转YOLO格式转换脚本与四个边界坑标注工具默认导出Pascal VOC格式也就是XML文件而YOLO训练需要的是TXT文件每行格式类别id 归一化中心x 归一化中心y 归一化宽 归一化高。转换脚本不难写但有几个边界坑。import xml.etree.ElementTree as ET import os from glob import glob def voc_to_yolo(xml_path, out_dir, class_names): tree ET.parse(xml_path) root tree.getroot() # 图片宽高在size节点下用来做归一化分母 img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) txt_name os.path.basename(xml_path).replace(.xml, .txt) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_names: continue cls_id class_names.index(name) box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) # 防止标注工具把左上右下坐标写反 x1, x2 min(x1, x2), max(x1, x2) y1, y2 min(y1, y2), max(y1, y2) # 归一化中心点坐标除以宽高框宽高除以宽高 x_c ((x1 x2) / 2) / img_w y_c ((y1 y2) / 2) / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h lines.append(f{cls_id} {x_c:.6f} {y_c:.6f} {w:.6f} {h:.6f}) if lines: with open(os.path.join(out_dir, txt_name), w) as f: f.write(\n.join(lines) \n) class_names [scratch, dent, crack] for xml_path in glob(annotations/*.xml): voc_to_yolo(xml_path, labels, class_names)代码逻辑解析XML拿图片宽高遍历每个object读取类别名和边界框坐标再把左上右下坐标换算成中心点加宽高的归一化格式。换算公式注意x_center等于左右坐标平均值除以图片宽度宽等于左右坐标差值除以图片宽度y方向同理。这也回答了一个常见问题为什么YOLO格式全是小数因为归一化之后训练时的数据增强可以随意缩放图片不需要关心原始分辨率。四个边界坑要特别留意。第一个XML坐标可能出现xmin大于xmax某些标注工具拖框方向从右往左时会出现脚本里我用min和max做了兜底。第二个坐标值可能是小数解析用float而不是int否则报错。第三个类别不在列表里时要跳过不跳就会生成错误的类别id。第四个有的XML里object存在但bndbox为空脚本里lines为空就不会生成TXT训练时就会报图片缺标注这种文件要单独筛出来修。3.3 数据增强小样本下怎么凑够训练集工业场景的数据集普遍偏小几百张甚至几十张是常态。YOLOv11训练自带数据增强包括马赛克、仿射变换、HSV扰动、随机翻转等默认配置对通用场景够用。但零件缺陷有特殊性划痕有方向性如果产线上划痕方向固定水平翻转会让划痕方向改变增强出来的数据反而误导模型。对这类方向敏感的场景我一般会把fliplr和flipud都关掉只保留旋转和亮度扰动。马赛克增强值得单独说。它把四张图拼成一张对提升小目标检测效果显著但工业零件图背景单一四张图拼在一起可能出现边界错位。数据集不足200张时开启马赛克收益大于风险数据量到500张以上可以降低马赛克比例甚至关掉让模型专注学习真实分布。HSV扰动参数我一般调大一些。产线光照有波动把饱和度扰动从默认的0.7调到0.8明度从0.4调到0.5色调保持0.015附近不动能增强模型对光照变化的鲁棒性。改动的逻辑是工业相机图像色彩相对稳定饱和度扰动可以加大但色调扰动只能微调改太大会让零件本身的金属色失真模型反而学错特征。4. 训练自己的缺陷检测模型参数怎么设才不翻车4.1 第一次训练跑起来训练命令与data.yaml配置数据准备好之后需要写一个data.yaml文件YOLO训练全靠它找到图片和标注文件。文件里定义图片路径和类别列表类别id的顺序必须和转换脚本里的class_names完全一致否则模型学的东西全错。这是最容易翻车的一步我见过好几回。path: /home/user/defect_data train: images/train val: images/val nc: 3 names: [scratch, dent, crack]path是数据集根目录train和val是相对根目录的图片文件夹路径。YOLO会自动在同名的labels目录下找TXT标注所以目录结构必须是images/train/a.jpg对应labels/train/a.txt。nc是类别数names是类别名列表索引从0开始顺序不能乱。写完data.yaml训练命令很简单# 用预训练权重做迁移学习开始训练缺陷模型 yolo detect train datadefect_data/data.yaml \ modelyolo11s.pt \ epochs200 \ imgsz640 \ batch16 \ device0 \ patience30modelyolo11s.pt表示加载small规格的预训练权重作为起点。迁移学习比从零训练收敛快得多即使你的数据集和COCO完全不沾边前几层学到的边缘纹理特征依然有效。epochs200是最大训练轮数imgsz640是输入图片缩放尺寸工业零件图分辨率普遍高640是速度和精度的平衡点batch16显卡显存不够就调到8或4device0表示使用第一张GPU没有GPU就写devicecpupatience30是早停参数验证集指标连续30个epoch不提升就提前停止数据量小时这个参数太重要了能避免无效的后期训练。训练过程会打印当前epoch、显存占用、各类损失值和mAP指标。第一次训练不用太关注每个数字主要看loss是否在下降、mAP50是否在上升。训练到第50个epoch mAP50还是零说明数据或配置有问题停下来排查不要硬跑完。4.2 训练监控loss曲线和mAP哪个先看ultralytics训练结束后会在runs/detect/train目录下生成大量文件。我一般不看训练过程中的终端输出直接看训练结束后的曲线图。results.png包含box_loss、cls_loss、dfl_loss三条损失曲线和precision、recall、mAP50、mAP50-95四条指标曲线。先看loss再看mAP是我的固定顺序。loss下降表示模型还在学loss不动或反弹说明有问题。箱损失box_loss应该平滑下降后趋于平台分类损失cls_loss在类别不平衡时可能一直震荡这正常。召回率recall不涨但精度precision在涨说明模型趋于保守框变少了但更准这时候可以适当降置信度阈值。接着看mAP50。工业缺陷检测以mAP50为主mAP50-95只作参考。原因是缺陷检测对框的位置精度要求不像自动驾驶那么高框稍微偏一点不影响“检测到”这个结论。mAP50到0.85以上模型基本可以上线试运行了。如果mAP50一直卡在0.5到0.7之间大概率是数据问题而不是模型问题回头检查第3章那些细节别在模型参数上瞎折腾。4.3 模型评估从混淆矩阵看漏检还是误检训练结束后看confusion_matrix.png这是打开黑匣子的一把钥匙。混淆矩阵对角线上是正确检测的样本数对角线之外是错误。对缺陷检测来说我重点关注两类错误漏检该检出的没检出和误检不该检出的给了框。混淆矩阵能直观看到哪些类别最容易混淆。划痕被误判成裂纹说明两类特征太接近检查标注时看边界框范围是不是画法不一致或者样本数量差距过大。还有一个跑训练时容易忽略的点每次训练都会生成args.yaml文件记录所有训练超参这是复现实验结果时的后悔药换个环境重新训练时照抄这份配置结果基本能对齐。再补充一个评估指标F1-confidence曲线。它展示不同置信度阈值下F1分数的变化工业部署时据此确定最佳阈值。曲线显示置信度0.35时F1最高推理时就设conf0.35。默认的conf0.25偏保守调高到0.3或0.4能明显减少误检。但阈值设太高也会带来漏检要结合产线对漏检和误检的容忍度来定没有统一答案。5. 工业缺陷检测的五个避坑记录现象、原因和解决5.1 缺陷样本严重不平衡模型只认凹坑不认划痕现象训练集里凹坑有800张划痕只有80张训练完划痕的召回率只有0.3凹坑的召回率0.95。原因YOLO默认按样本数量均匀采样类别少的缺陷在整个训练过程中被模型“看见”的次数太少梯度更新基本被大类主导。解决有三条路。第一是数据层面做增广对划痕样本做复制粘贴和旋转把数量至少拉到大类的三分之一不用完全相等比例低于1比5时就非常危险。第二是调整采样权重让模型每个batch都能见到小类样本ultralytics里可以通过调整数据集分布实现常见做法是直接对少的类别做过采样生成增强副本混入训练集。第三是降低小类的置信度阈值但这个方法治标不治本阈值调太低会带来一堆误检。最有效的是前两条路一起走数据提上来模型才有东西可学。5.2 训练mAP高但验证掉点过拟合了现象训练集mAP50到了0.95验证集只有0.7而且差距随epoch增大越来越明显。原因样本量少加训练轮数多模型把训练集里的背景纹理也记住了真实场景光照一变就失灵。解决先把patience调小到20或30早停卡住最优验证点。其次看增强参数数据量少于500张时把weight_decay从默认值适当调大我一般从0.0005改成0.001让模型权重更平滑。还有一个关键操作部署时务必用best.pt而不是last.pt。best.pt是验证集表现最好的权重last.pt是最后一个epoch的权重很多人不知道这两个文件的区别直接用last.pt部署效果天然差一大截。这个习惯养成了换任何数据集都不容易翻车。5.3 小目标缺陷一直漏检imgsz解决不了现象缺陷面积只占整图0.5%以下比如一块50乘50像素的麻点在1024乘1024的图里无论怎么调imgsz模型就是漏检。原因yolov11网络结构本身有多尺度检测头但小目标的特征在深层特征图里信息丢失严重这是目标检测的通病不完全是模型的问题。解决常见做法是把imgsz从640提到1024或1280图片大了小目标像素占比就大了副作用是显存占用涨训练和推理变慢。另一个思路是切图推理把大图切块成多张小图分别预测再合并结果。对零件缺陷检测我通常先算一下缺陷的平均像素面积如果小于整图的1%优先考虑切图而不是直接上大分辨率。还有一种trick是用更大规格的预训练模型作为起点比如用yolo11m.pt代替yolo11s.pt多出来的表达能力对小目标有稳定提升代价是推理变慢要拿实测数据来衡量值不值。5.4 把螺纹纹理误判成裂纹误检率高得吓人现象验证集mAP不错一到新产线图片误检框多了一倍后来发现误检全部集中在螺纹、砂轮纹这类规则纹理区域。原因规则纹理在视觉上跟裂纹有相似的边缘响应模型没有学到“螺纹不是缺陷”这个语义概念因为训练数据里根本没出现过带螺纹的背景样本。解决这个坑最有效的解法不是在模型参数上折腾而是加背景负样本。把标注为“无缺陷”的零件图片单独建一个背景目录训练时加入这些图片并确保没有对应的TXT标注框YOLO会把它们当作背景来学习纹理误检会明显下降。如果加负样本还分不清考虑增加一个“螺纹”类别直接标注出来让模型学会区分“裂纹”和“螺纹”代价是增加标注和训练工作量。先试负样本不行再上类别这是性价比最高的顺序。5.5 换产线换零件模型直接失效现象同一个模型在A产线跑得好好的换到B产线mAP掉到一半不到。原因各产线的相机角度、光照强度、零件材质和背景都不一样深度学习模型对输入分布变化极度敏感这是工业部署最大的坑。解决没有后悔药只有两条路。第一是做快速迁移收集B产线少量图片50到200张就够在现有模型基础上继续训练几个epoch把骨干冻结只微调检测头保留原来的特征又适应新分布。第二是在推理流程前加图像预处理标准化比如光照归一化和白平衡校正。不要指望一个模型通吃所有产线实际项目中我都是给不同产线保存一套模型推理时按产线编号加载对应权重。花半天时间做快速迁移比花一个月重新标数据划算得多。6. 推理部署与结果保存从best.pt到产线能用6.1 批量预测与结果保存模型训练完ultralytics会在runs/detect/train/weights/下生成best.pt和last.pt两个权重部署时务必选best。产线抽检时我一般用命令行做批量预测直接保存推理结果# 用训练好的best.pt做批量预测保存图片和TXT结果 yolo predict modelruns/detect/train/weights/best.pt \ sourceincoming/ \ conf0.35 \ saveTrue \ save_txtTrue \ projectdefect_results/conf按训练时的F1曲线来确定saveTrue把画好框的图片存下来方便人工复核save_txtTrue把检测结果写成TXT每行是类别id、置信度和归一化坐标。TXT文件是给MES系统做数据对接用的产线上不可能有人肉看标注图片一切对接都靠这个文本输出。6.2 用Python API封装推理函数产线集成时命令行不够灵活我一般封装成函数def predict_frame(frame): results model.predict(frame, conf0.35, verboseFalse) boxes results[0].boxes out [] for box in boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) x1, y1, x2, y2 box.xyxy[0].tolist() out.append({cls: cls_id, conf: conf, bbox: [x1, y1, x2, y2]}) return out核心是读boxes对象的cls、conf和xyxy三个属性xyxy是未归一化的像素坐标方便直接画框或换算成零件的实际尺寸。model的加载要放到循环外面只加载一次否则每帧重新加载模型推理速度慢到怀疑人生。6.3 导出ONNX脱离pytorch依赖工控机上大量部署场景不允许装完整pytorch把模型导出成ONNX格式只用onnxruntime就能跑# 导出ONNX部署端只需要onnxruntime yolo export modelruns/detect/train/weights/best.pt formatonnx opset12导出后用onnxruntime加载推理CPU上速度往往比pytorch还快一点。opset版本要和onnxruntime匹配导出前先确认工控机上要装的版本。导出成ONNX之后方案才真正脱离训练环境成为能被产线软件集成的独立模块。这是我最深的体会模型在笔记本上跑得再好不能顺利部署到产线就等于零。前面在数据和训练上花的时间最后一步没走通就全白费。导出ONNX并验证输出结果和pytorch一致是我每次交付前必做的一步也是帮合作方省掉大部分现场调试时间的关键一步。希望这份实战记录能帮你少走点弯路把YOLOv11真正用起来。本文还有配套的精品资源点击获取