资讯动态

基于YOLOv11的钢材表面缺陷检测系统:从数据集训练到UI登录注册实战

发布时间:2026/10/20 21:54:42 来源:尧图企业网站定制
钢材表面缺陷检测这几年在工业视觉里一直是个热点。传统人工质检又累又容易漏产线上千度高温的板坯表面肉眼盯久了谁也扛不住。基于深度学习YOLOv11的钢材缺陷检测系统就是把这块活儿交给模型来做输入一张钢材表面图像模型能自动框出划痕、氧化皮、夹杂这些缺陷的位置和类别然后工程上再做一套界面方便操作带个登录注册来管权限最终形成一个能跑、能看、能演示的完整Python项目。这篇文章我会把这个项目从数据集、训练、界面到部署完整盘一遍适合正在做毕业设计、竞赛项目或者刚接触工业视觉想要个完整闭环的同学参考。1. 项目整体思路与方案设计1.1 从产线痛点倒推需求先说清楚这个项目到底解决什么问题。钢材在热轧、冷轧过程中表面很容易出现各种类型的缺陷氧化铁皮压入、划痕、麻点、夹杂物、边裂、皱褶等。这些缺陷直接影响成品等级和售价所以质检环节是钢厂和下游加工厂绕不开的一步。传统做法是质检工人用肉眼在高亮灯光下看钢板表面或者在产线末端安装工业相机把图像传回中控室让人工盯屏幕。前者效率低、易疲劳后者虽然节省了跑现场的体力但本质上还是“人眼找缺陷”漏检率跟人的状态强相关。一台热轧产线一小时能跑几十吨钢卷靠人眼想做到既快又准非常困难。于是就有了用目标检测来做自动判定的需求把工业相机拍摄的钢板表面图像喂给深度学习模型让模型输出每一个缺陷的位置框和分类标签。输出结果再叠加工业逻辑比如缺陷面积超过阈值就报警、标记降级、触发喷标等。这个项目的核心就是先做一个能用的检测模型再配一个UI界面把能力包装成普通工人也能操作的工具。1.2 为什么选择YOLOv11而不是其他检测算法目标检测算法可选的范围其实很大老一代的Faster R-CNN精度高但推理速度慢SSD速度快但小目标效果一般YOLO系列则一直在速度和精度的平衡上做得很好。这个项目选YOLOv11理由很直接推理速度快单张图片使用GPU推理能到毫秒级即使只用CPU也能做到每秒处理一两张图满足产线抽检或者离线检测的节奏工程集成简单ultralytics官方库封装得非常好训练、验证、导出、推理都是几行代码的事适合快速落地模型结构在YOLOv8的基础上又做了改进C3k2模块配合注意力机制在小目标和密集缺陷上的表现比前代更稳生态成熟数据集格式、预训练权重、导出ONNX/TensorRT的工具链都齐全。有些同学会纠结是不是用更重的模型比如Faster R-CNN精度会更高其实对于钢材表面这种缺陷目标很多缺陷边缘模糊、对比度低Faster R-CNN未必有明显优势而且推理慢、显存占用高。反而YOLOv11加上合适的数据增强和调参能把mAP做到够用的水平。工业现场要的是“稳、快、准”三者平衡而不是单一指标极致这也是我推荐YOLOv11的核心原因。1.3 系统模块划分与整体架构拿到一个项目先别急着跑代码先把需求拆清。我当时给这个系统规划了四块检测核心模块YOLOv11模型加载、推理、结果解析负责把图片里的缺陷找出来数据集管理模块负责训练集、验证集的组织标签格式转换数据增强UI交互模块登录注册界面、检测主界面、结果展示窗口负责把人机交互做好模型训练与导出模块负责训练、评估、导出部署格式属于偏开发侧的辅助工具。这四块组合起来就形成了一个完整的闭环用户打开程序先登录或注册账号进入主界面选择一张钢材表面图片或打开摄像头点击检测模型推理后把缺陷框、类别、置信度、数量展示在界面上同时输出一份简单的检测报告。要注意的是这个系统本质上是一个“软件系统”而不是一个“算法脚本”。很多初学者拿到代码只跑通了训练脚本就以为完事了结果界面、账号体系、模型调用全没有最后交不了差。所以我建议在动手写代码之前就用一张架构图把数据流向、模块依赖理清楚后面开发会顺利很多。哪怕是自己做着玩也值得先把“登录到检测”这条主链路走通。2. 数据集准备与预处理实战2.1 数据集来源与类别分析钢材缺陷检测绕不开数据。目前网上可以找到公开的钢材表面缺陷数据集最常见的是收集自热轧带钢表面的图像集标注了六类典型缺陷包括氧化皮压入、划痕、夹杂物、麻点、斑块、皱褶。每类缺陷都有各自的外观特征氧化皮呈现块状或不规则片状颜色较深边缘不规整划痕是线状连续纹理麻点是密集的细小凹坑皱褶表面呈龟裂状纹路。拿到原始数据后我建议先做一次可视化分析把每一类缺陷的样本数量、图片尺寸、缺陷框大小分布统计出来。这一步非常关键能帮你判断数据是否类别不均衡。我见过一次实际项目其中“划痕”类有几千张图而“边裂”类只有几百张训练出来前者的检测精度远高于后者这就需要在数据层面做处理比如对少样本类别做过采样或针对性数据增强。这个项目的数据集格式比较规整原始标注通常是VOC的XML格式。YOLOv11训练需要的是YOLO格式的TXT标注文件每一行是“类别索引 中心点X 中心点Y 宽度 高度”所有坐标都归一化到0到1之间。所以第一步就是把XML转换成TXT。2.2 标注格式转换与目录组织转换脚本本身不复杂核心逻辑就是读取XML里每个object的bndbox坐标结合图片宽高做归一化。但这里有几个坑图片宽高必须从原图读取不能用XML里写的因为有的数据集XML和图片尺寸不一致直接换算会框偏注意坐标归一化后要限制在0~1范围内防止越界类别编号顺序必须固定比如0代表氧化皮、1代表夹杂、2代表斑块、3代表麻点、4代表划痕、5代表皱褶训练和检测时的类别名要一一对应。目录结构建议这样组织datasets/ ├── steel_defect/ │ ├── images/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ ├── labels/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ ├── classes.txt │ └── data.yamldata.yaml是ultralytics训练时用的配置内容很简单指定训练集验证集路径和类别列表即可。path: /path/to/datasets/steel_defect train: images/train val: images/val nc: 6 names: [oxide_scale, inclusion, patches, pitted_surface, scratches, crazing]这里我踩过一次坑path写的是相对路径结果换了一台电脑训练直接报数据集找不到。建议要么写绝对路径要么把数据集和项目放在固定相对目录里并用代码动态拼接当前工作目录路径。2.3 数据增强与划分策略钢材表面缺陷图像有个特点同一类缺陷在不同光照、不同钢材纹理背景下外观差异挺大。如果训练集过小模型很容易过拟合。我的做法是在ultralytics自带的增强策略基础上再叠加针对性增强随机水平翻转和旋转10度以内因为钢板方向在产线采集时可能有偏差HSV颜色空间增强模拟不同光照条件随机仿射变换模拟相机安装角度偏移Mosaic增强保留这个对提升小目标检测效果很有效。数据集划分我用的是8:1:1训练集占80%验证集和测试集各10%。划分时要注意按图片名采样避免同一张原始图片的多个切块同时出现在训练集和验证集里那样会造成数据泄漏验证指标虚高。增强不是越多越好。我做过一组对比实验把增强幅度调大之后训练集loss能降得很低但验证集mAP反而掉点。原因是钢材缺陷本身就有很多相似纹理背景过度增强会把模型带偏。比较稳妥的做法是把增强代码单独抽出来逐步调整参数以验证集mAP为唯一标准。3. YOLOv11模型训练与调优实录3.1 训练环境搭建与依赖安装这个项目我是在Windows系统上配的CUDA环境也可以直接用Linux服务器或者云GPU。先说下硬件底线如果你的显卡只有6G显存建议训练时用yolov11s.yaml这种小模型批量大小调到16如果有12G以上显存可以跑yolov11m.yaml效果会更好。安装依赖其实很简单主要就ultralytics、torch、torchvision、opencv-python、PyQt5这些。建议用Python3.10以上的版本用conda开一个独立环境避免把系统环境搞坏。安装命令如下conda create -n steel_yolo python3.10 -y conda activate steel_yolo pip install ultralytics pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install PyQt5 opencv-python如果要跟UI界面结合PyQt5建议在创建环境时一并装好。很多同学先装完ultralytics再装PyQt5结果GUI环境依赖冲突运行时可能报错我建议一次性装完。3.2 训练参数配置与启动命令训练脚本用ultralytics的YOLO类来写非常简单。下面是我整理的基础训练代码from ultralytics import YOLO # 加载预训练权重以s模型为例 model YOLO(yolov11s.pt) # 训练 model.train( datadatasets/steel_defect/data.yaml, # 数据集配置文件 epochs100, imgsz640, batch16, device0, # 0表示第一张GPUCPU训练填cpu patience20, # 连续20轮验证集指标不升则早停 projectruns/train, # 训练结果保存目录 namesteel_yolov11s, # 本次训练名称 pretrainedTrue, # 使用预训练权重迁移学习 )训练时建议重点关注几个参数patience早停参数一定要开否则训练100轮可能白跑后面30轮浪费时间imgsz默认是640如果你的输入图像分辨率比较高可以试试960甚至1280小缺陷的检测效果往往会变好但显存占用也随之上升batch需要根据显存调整显存不足时优先减小batch而不是减小图片分辨率因为分辨率对检测精度影响更大。训练过程会输出每一轮的box_loss、cls_loss、dfl_loss以及验证集的precision、recall、mAP50、mAP50-95。如果从头到尾recall都很低大概率是数据标注或类别配置有问题一定要及时终止排查不要傻等100轮跑完。3.3 训练结果评估与模型导出训练结束后ultralytics会在runs/train/steel_yolov11s目录下生成weights/best.pt和last.pt还有混淆矩阵、PR曲线、训练曲线等图。我的习惯是先看混淆矩阵如果某两个类别互相混得很严重比如“麻点”和“皱褶”纹理相似经常误判就需要检查标注质量或者考虑合并类别。再看PR曲线曲线越靠近右上角越好mAP50只是一个综合数字很多时候各类别的PR曲线差别很大一定要逐类别分析。比如氧化皮这类缺陷边缘明显检测精度高麻点这类小目标、密集目标检测效果差这时候要考虑增加小目标检测层或者做精细标注。模型导出这块我先导出ONNX再转成OpenVINO或者TensorRT。ONNX的作用是脱离PyTorch环境也能跑推理便于部署到没有深度学习环境的Windows机器上。导出命令一行就能搞定model.export(formatonnx, dynamicFalse, simplifyTrue, opset12) model.export(formatengine, halfTrue) # 转TensorRT需要GPU这里有个细节如果你的检测程序要用OpenCV读取图片并做预处理模型输入分辨率记得固定成训练时的imgsz否则推理结果会偏移。我建议导出onnx时固定输入尺寸640×640程序里把图片先等比缩放再padding到640×640。4. 登录注册与检测端UI的实现4.1 界面框架选择PyQt5还是Tkinter项目标题里明确要求UI界面和登录注册界面所以界面框架得选一个开发效率高、能拿得出手的。Tkinter优点是Python自带、轻量但控件样式老旧做登录注册和检测展示界面略显简陋。PyQt5功能更强大支持qss样式表美化界面可以做出类似现代软件的观感所以我选了PyQt5。选择PyQt5还有一个重要原因检测结果要显示图像PyQt5的QLabel配合QGraphicsView显示图像非常流畅还能支持鼠标缩放查看缺陷细节。再加上QThread解决推理阻塞界面卡死的问题整个体验会好很多。UI布局我设计了两个窗口登录注册窗口和检测主窗口。登录注册窗口提供账号密码输入、登录按钮、切换注册界面功能检测主窗口包含左侧是当前图片预览和操作按钮区右侧是检测结果列表和统计信息区底部是日志输出区。4.2 登录注册模块的设计细节登录注册这块初学者容易做成假功能点按钮直接跳转、账号密码不校验。虽然只是个Demo但项目要想拿得出手至少要做一个本地账号存储和密码校验机制。我是用SQLite数据库存储账号信息的。密码不存明文存SHA256摘要注册的时候把用户名、密码摘要、创建时间写入数据库登录的时候查询比对。这样即使数据库文件被人拖走也不会直接暴露所有密码。import hashlib import sqlite3 def hash_password(password, salt): return hashlib.sha256((password salt).encode()).hexdigest() def register(username, password): salt uuid.uuid4().hex digest hash_password(password, salt) conn sqlite3.connect(user.db) conn.execute(INSERT INTO users (username, digest, salt) VALUES (?, ?, ?), (username, digest, salt)) conn.commit() conn.close() def check_login(username, password): conn sqlite3.connect(user.db) row conn.execute(SELECT digest, salt FROM users WHERE username?, (username,)).fetchone() conn.close() if row is None: return False return row[0] hash_password(password, row[1])登录注册界面的核心逻辑就是初始化时加载数据库点击“登录”按钮读取输入校验成功则关闭登录窗口、打开主窗口失败则弹窗提示。注册时做一下用户名重复检查密码长度至少8位的限制。这些细节虽然很小但也是项目完整度的一部分。4.3 检测主界面与模型推理对接检测主界面是用户真正使用的界面也是项目最能直观体现功能的模块。我把检测流程设计成点击“打开图片”按钮从文件系统选择钢材表面图像图像显示在左侧画布上点击“开始检测”按钮程序把图片加载到YOLO模型里做推理推理结果通过模型返回的结果对象提取包括每个缺陷框的坐标、置信度、类别在原图上绘制检测框和标签更新到界面右侧表格显示检测列表底部统计缺陷总数。推理部分的核心代码如下from ultralytics import YOLO import cv2 import numpy as np class SteelDetector: def __init__(self, weights_path): self.model YOLO(weights_path) def detect(self, img_path): results self.model.predict( img_path, conf0.25, iou0.45, imgsz640, devicecpu, # 部署时无GPU则用cpu ) boxes results[0].boxes names results[0].names detections [] for box in boxes: x1, y1, x2, y2 map(int, box.xyxy[0].tolist()) conf float(box.conf[0]) cls_id int(box.cls[0]) detections.append({ class: names[cls_id], conf: conf, box: (x1, y1, x2, y2) }) return detections检测耗时的优化最直接的办法是把模型加载放在启动时完成而不是每次点检测加载一次。另外把推理图的写入数据放到线程里执行避免大图绘制时界面卡住。我平时会把检测线程封装成QThread检测完成后通过信号把结果传回主线程更新界面。界面上还可以加一个“置信度阈值”滑条用户调节后立即重新过滤结果。这个功能看着简单但很实用因为不同产线的判定标准不一样有的要求每块区域置信度超过0.5才算缺陷有的0.3就要报做成可调节可比写死好得多。5. 实战避坑与调优心得5.1 训练阶段的4个典型坑第一个坑是标签跟数据源对不上。一个朋友的项目里训练后的loss低得离谱结果画出来一看模型把整张图都框成缺陷了。检查后发现data.yaml里的类别顺序和标注文件里的索引对不上这属于低级的元数据错误但出现概率不低。我的建议是训练前写个脚本随机抽10张图把标注框画出来人工验收一遍。第二个坑是训练显存不够。yolov11s模型其实不算大但如果把batch设到32、图片尺寸用到12806G显存照样爆。报错提示一般是CUDA out of memory。解决方式很有层次先调小batch再调小图片尺寸最后考虑换轻量模型。第三个坑是验证集mAP很高但实际图片上表现差。这种情况十有八九是过拟合或者训练集分布和真实场景不一致。比如训练集里都是亮度正常的照片产线上相机有逆光模型扛不住。在训练数据里混入一部分实际场景图像效果会好很多。第四个坑是误把验证集指标当上线标准。在产线抽样测试时最关心漏检率也就是确实有缺陷但我们没检测出来的比例。mAP是全局指标不代表每个类别都好。一定要单独统计每个类别的recall对漏得多的类别补充样本重训。5.2 界面卡顿与并发问题PyQt5做的检测界面最容易遇到的问题就是点击检测按钮后窗口无响应。根因很直接推理是耗时操作如果在主线程执行界面事件循环被阻塞了自然无法刷新。解决办法是把推理放到QThread里import threading class DetectThread(QThread): result_ready pyqtSignal(object) def __init__(self, detector, img_path): super().__init__() self.detector detector self.img_path img_path def run(self): detections self.detector.detect(self.img_path) self.result_ready.emit(detections)另外绘制检测框时尽量用cv2在图片上画完再一次性转成QPixmap显示不要用QLabel的多次setPixmap更新小区域那样会很卡。图像大小超过1920时建议先把图缩放后再画框显示检测结果仍然保持在原始分辨率上计算这样界面操作更流程。5.3 从Demo到可部署产线的差距很多同学以为算法效果OK就算项目完成了但真实产线项目还需要处理几个工程问题图像接入产线相机传过来的是GigE或者CameraLink流不是一张一张的图片需要写采集模块对接相机SDK通讯上报检测结果要写入PLC或者MES系统这需要工业协议支持比如Modbus TCP或者MQTT环境适配工厂现场电脑配置通常不高可能没有GPU需要做模型裁剪、量化、ONNX Runtime推理优化标定与阈值每一条产线钢种不同、光照不同缺陷判定标准也不同需要提供参数配置界面让现场工程师调整。这个项目作为毕设或竞赛展示把UI、登录、模型推理这套闭环做出来已经很完整了。但如果你真要往工业现场落地后台服务化、相机接入、数据回传这几个坑会依次找上你。我曾经在模拟产线环境中做算法验证相机安装角度稍微偏了一两度模型表现直接掉了好几个点后来配合光照补偿和数据增强才稳住。这提醒我们算法效果是一回事系统稳定性是另一回事。5.4 模型压缩与部署扩展方向假设你想把整个系统做得更专业可以从这几个方向扩展第一是模型压缩。yolov11s导出ONNX后用OpenVINO跑CPU上推理速度比PyTorch直接跑要快不少。代码非常简单pip install openvino-dev onnx mo --input_model yolov11s.onnx --input_shape [1,3,640,640] --data_type FP16之后用OpenVINO的runtime加载IR模型就能跑推理整个过程不需要安装PyTorch环境精简很多。第二是知识蒸馏。如果你有充足的预算训练一个m或l型号的大模型再用大模型的预测结果去指导小模型训练小模型精度能提升不少。这个比较适合显存有限但精度要求高的场景。第三是类别扩展。钢材表面缺陷的种类远不止6类如果现场还需要检测气泡、结疤、辊印等只需要在数据集里增加新类别的标注修改data.yaml重新训练即可。模型结构不用改前端类别名列表同步更新就行。我在实际项目中做的最多的其实是这两件事一是针对产线实际采集的图片持续做验证、找坏例、回注训练二是根据产线不同钢种建立不同的模型配置一键切换。说实话深度学习检测做出来“能用”相对容易做“稳定”才是真正费时间的部分。写到最后的一些体会做这类带完整界面的目标检测系统最大的收获不是学会调参训练模型而是把“算法能力”包装成一个“用户拿起来就能用”的软件产品这件事。模型训练得再好卡在命令行参数里现场工人根本用不了。反过来界面做得再精致模型检测效果一塌糊涂应用方也不会买账。这个项目正好把算法训练、数据工程、界面开发、账号管理全串起来了很像一个小型工业级应用的缩影。实际动手时我强烈建议先把每个模块单独跑通再整合先跑通训练拿到模型写脚本加载模型推理验证没问题再写UI最后接登录数据库。这样分段调试出问题时能快速定位。别想着一个晚上全写完那只会把自己坑哭。最后想说做工业视觉多去留意那些真实场景里的脏数据、光照变化、钢种差异这些才是真正拉开差距的地方。模型框架更新迭代很快但找数据、清数据、调工程的那套功夫什么时候都不过时。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑