
简介面向焊缝质检、工业视觉及YOLOv5目标检测学习者提供一套可直接落地的焊缝质量好坏检测整体方案可用于焊缝缺陷判别与质量监测等场景。资源内涵盖训练完毕的检测模型附带PR曲线、loss曲线等训练过程记录便于评估模型性能并配套1134张钢材缺陷jpg图像及经LabelImg标注的对应标签标签同时提供xml与txt两种格式按类型分文件夹存放可适配YOLOv5等主流目标检测框架省去自行采集与标注数据的时间。PyQt图形界面支持对静态图片、本地视频和摄像头实时画面进行检测用户可选择不同检测源操作直观适合快速验证检测效果、展示算法演示或进行二次开发。压缩包共2000个文件总大小约222.96MB已有986人学习是学习焊缝缺陷识别及基于YOLOv5搭建检测系统的实用资源。1. 用YOLOv5做焊缝质量检测先解决的不是模型而是数据与界面边界质检员盯着焊接件拍回来的几十张照片焊缝表面泛着金属反光飞溅和焊渣混在一起气孔和未熔合藏在纹路里。你如果只把这当成一个目标检测任务去训练YOLOv5多半会卡在精度忽高忽低、界面上点一次检测卡三秒这类烂尾环节。像YOLOv5焊缝质量好坏检测权重数据集pyqt界面这种标题组合本质是两件事一是训练一套能区分合格与缺陷焊缝的模型二是把权重装进一个让车间工人能直接上手用的PyQt界面。前者的难点在数据集标注的一致性后者难点在推理的并发处理和阈值设定。你会看到很多教程只讲其中一半但真正跑通流程的人知道权重和数据集是模型的输入与输出界面是工程的收口三者的排列顺序决定了这个项目是否交付得了。下面按一条能落地的路径展开先定模型配置再做数据最后用PyQt把模型包成一个完整的检测工具。2. YOLOv5焊缝检测的模型选型与训练配置YOLOv5在工业质检场景出现频率高一个现实原因是它的训练和部署链路短适合在普通工作站上跑而不是必须依赖高配服务器。在动手写训练命令之前先想清楚模型尺寸的选择依据。2.1 焊缝检测任务对YOLOv5系列的选型依据YOLOv5根据网络深度和宽度分成n/s/m/l/x几个版本它们的主要差别不在算法结构上而在于特征提取层的重复次数和通道数。焊缝缺陷在图像里的面积占比往往很小比如气孔可能只有十几个像素直径未熔合可能是一条细线这对小目标检测能力提出了要求。如果直接用n或s版本骨干网络提取的特征不够精细细微缺陷容易在深层特征图里被忽略掉如果一上来就选x版本训练时间和显存消耗会明显增加而在实际产线上一张图只包含两三个缺陷目标过大的网络反而是浪费。我在做类似项目时的经验是以YOLOv5s作为基线起步如果气孔这类小缺陷的召回率上不去再切换到m版本。因为s版本的权重体积在14MB左右推理速度快便于在PyQt里做实时预览m版本大约40MB精度提升明显但需要看你的部署机器有没有独立显卡。你可以在训练前用一张包含典型焊缝缺陷的图跑一次detect.py简单判断缺陷目标与整图的尺寸比例。2.2 搭建YOLOv5训练环境的最小配置训练环境推荐用conda管理Python版本YOLOv5官方代码在Python 3.8到3.10上都验证过。下面这套步骤是我常用的最小环境配置conda create -n weld_yolo python3.9 conda activate weld_yolo cd yolov5-master # 官方仓库或者你本地维护的fork pip install -r requirements.txt pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118安装结束后用python train.py --help确认训练入口是否正常。这里需要注意requirements.txt里已经包含了pyyaml、matplotlib、opencv-python等基础依赖但如果你后续要做PyQt界面建议先把PyQt5也装好避免环境反复切换。如果显存不够8GB我建议你在train.py中优先看--batch-size和--workers两个参数而不是马上换小模型因为语义分割和目标检测的batch size对收敛曲线的影响是直接的减少batch size往往比换模型更省事。2.3 焊缝质量检测的训练命令与参数调优数据准备好之后训练命令需要重点关注--img、--batch、--epochs和--data四个参数。焊缝表面的细微缺陷需要较高分辨率来保留--img 640对大多数焊接图够用如果发现小缺陷漏检可以尝试--img 1280但训练时间会翻倍。下面是我在分两阶段训练时常用的一组参数python train.py \ --img 640 \ --batch 16 \ --epochs 150 \ --data weld.yaml \ --cfg models/yolov5s.yaml \ --weights yolov5s.pt \ --name weld_experiment \ --cache--weights yolov5s.pt表示用COCO预训练权重做迁移学习。--cache会把图像加载进内存训练速度提升明显但需要你有足够的内存空间。另一个关键参数是--hypYOLOv5默认的hyp.scratch-low.yaml适合一般检测场景而焊缝图像的光照不均匀和反光干扰比较常见可以把hsv_h从0.015降到0.005防止颜色抖动改变金属纹理的真实特征。训练完成后权重文件保存在runs/train/weld_experiment/weights/下best.pt和last.pt的区别要记牢best.pt是验证集上mAP最高的一次权重而last.pt是训练结束时保存的权重。在PyQt界面中默认加载best.pt如果需要继续训练用last.pt做起点更合理。参数建议值说明--img640或1280与推理尺寸保持一致训练和推理尺寸不一致会掉点--batch8到32受显存限制16是通用起步值--epochs100到200关注验证集mAP是否在epoch 120后继续上升--weightsyolov5s.pt迁移学习能大幅缩短收敛时间--patience50连续50个epoch没有提升就早停3. 构建焊缝缺陷数据集采集、标注与格式转换数据集是整个焊缝检测项目的地基。你可能会在网上找到公开的钢材表面缺陷数据集但焊缝缺陷的形态与钢材表面的区分度并不一样尤其是气孔、夹渣、未熔合、咬边和裂纹这五类常见缺陷各自在不同光照、不同焊接工艺下的表现差异很大。自己采集标注是不可避免的一步。3.1 焊缝图像采集的覆盖策略采集时要注意覆盖面同一个焊缝在不同角度、不同距离、不同光照条件下缺陷的视觉特征会有较大变化。我建议一个缺陷样本至少覆盖3个角度、2种距离和2种光照条件。如果是固定的自动焊接产线相机位置通常是固定的那么角度变化可以压缩但光照变化必须保留因为金属表面的反光会直接影响模型对气孔和未熔合的判断。如果条焊缝长度很长应该等间隔截取多个片段而不是只拍起弧和收弧位置。起弧和收弧处的缺陷密度高容易导致模型对正常焊缝区域的过拟合判断。一个合理的起步规模是5个缺陷类别加1个合格类别每类样本量在300到500张之间。如果其中某类缺陷本身就少先不要急着采集足够数量用数据增强来补充后面会讲。3.2 YOLO标注格式与两类标注工具的选择YOLOv5的训练标注格式是每张图对应一个同名txt文件每一行记录类别id和归一化位置信息格式为class_id x_center y_center width height。这里的坐标值都是相对于图像宽高的比例范围在0到1之间。标注工具我常用两种。LabelImg是老牌工具按VOC格式标注后可以导出为YOLO格式适合快速上手。X-AnyLabeling这类新一代标注工具支持半自动辅助标注但需要额外加载一个预训练模型。对于焊缝这种对比度不高、缺陷边界模糊的图像半自动标注的收益有限手动画框反而是更可靠的方式。在标注焊缝缺陷时有两条边界规则必须统一一是当两个缺陷距离很近但轮廓接触时分别画框还是一个框框住两者我倾向于一个框包含整体因为这更符合目标检测中以最小外接矩形表达目标的原则二是只把明显可见的缺陷标出来不要把正常焊缝的鱼鳞纹当作未熔合来标这种主观偏差是训练集噪声的主要来源。3.3 数据集划分与目录结构YOLOv5要求的数据集目录结构如下weld_dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/训练集与验证集的划分比例建议是8:2而且划分时不要让同一张原始图像的裁剪块同时出现在训练集和验证集中否则验证集mAP会虚高。在焊缝场景中一长条焊缝的连续截图往往高度相似应该在焊缝片段层面划分而不是在单张图层面划分。下面这段脚本能把标注好的图像和txt文件按8:2比例随机划分到训练集和验证集import os import random import shutil image_dir weld_all/images label_dir weld_all/labels train_img_dir weld_dataset/images/train val_img_dir weld_dataset/images/val train_lbl_dir weld_dataset/labels/train val_lbl_dir weld_dataset/labels/val for d in [train_img_dir, val_img_dir, train_lbl_dir, val_lbl_dir]: os.makedirs(d, exist_okTrue) images [f for f in os.listdir(image_dir) if f.endswith((.jpg, .png))] random.seed(42) # 固定随机种子保证每次划分结果一致 random.shuffle(images) val_count int(len(images) * 0.2) val_set set(images[:val_count]) for img_name in images: label_name img_name.rsplit(., 1)[0] .txt if img_name in val_set: shutil.copy(os.path.join(image_dir, img_name), val_img_dir) shutil.copy(os.path.join(label_dir, label_name), val_lbl_dir) else: shutil.copy(os.path.join(image_dir, img_name), train_img_dir) shutil.copy(os.path.join(label_dir, label_name), train_lbl_dir)这段脚本的核心在于random.seed(42)如果你在划分后做数据增强之前先训练一版之后再次划分还能保持完全一致的分布便于追踪数据变更对模型效果的影响。annotations目录用不到因为YOLO格式不需要单独的标注XML或JSON文件。3.4 类别不平衡与数据增强的取舍焊接缺陷天然存在类别不平衡问题。气孔出现频次远高于裂纹如果你有500张气孔图和120张裂纹图模型会倾向于把所有不确定区域都预测成气孔。解决这个问题的常用方法是在训练前把少数类样本通过离线增强复制一份而不是直接依赖在线增强。Mosaic增强对图像做了大量拼接连续进行多轮训练时少数类特征反而会被稀释。离线增强建议只做有限变换上下翻转、左右翻转、90度旋转、亮度变化和轻微模糊不要做形变和随机擦除因为焊缝图像的几何结构对缺陷判定有决定性影响。增强后的图像应该重新检查标注坐标是否正确尤其是旋转后的翻转操作很多标注脚本在这种地方出错。4. PyQt5焊缝检测界面的落地实现训练完权重拿到best.pt之后接下来就是把这个模型嵌入到PyQt5界面里。实际使用中界面并不只是打开图片——显示结果这么简单你还要处理摄像头实时采集、批量图片检测、参数保存和结果导出这些用同步逻辑写死会导致界面卡死。这一章围绕「如何在PyQt5里加载YOLOv5权重并保持界面流畅」展开。4.1 界面功能划分与线程设计PyQt界面默认跑在主线程里而YOLOv5推理是计算密集型操作如果在按钮回调里同步执行model()方法界面会在推理期间完全无响应。常见做法是把推理放到QThread子线程里主线程只负责接收信号和更新UI。一个完整的焊缝检测界面应该包含以下功能模块图像加载或摄像头捕获、推理结果显示、检测阈值调节、权重选择、检测结果统计表和结果导出。在这些模块中权重选择和检测阈值调节是直接影响模型输出的模块需要优先设计得灵活。工人在现场不会去修改代码你要把conf_thres和iou_thres暴露成滑块控件。下面是一个可运行的QThread推理线程模板import cv2 import torch from PyQt5.QtCore import QThread, pyqtSignal class DetectThread(QThread): result_ready pyqtSignal(dict) def __init__(self): super().__init__() self.model None self.image_path None self.conf_thres 0.25 self.iou_thres 0.45 def load_model(self, weights_path): # 在启动线程前先加载模型 self.model torch.hub.load(., custom, pathweights_path, sourcelocal) def run(self): if self.model is None or self.image_path is None: return img cv2.imread(self.image_path) results self.model(img, size640, conf_thresself.conf_thres, iou_thresself.iou_thres) detections results.pandas().xyxy[0] boxes detections[[xmin, ymin, xmax, ymax]].values.tolist() scores detections[confidence].values.tolist() labels detections[name].values.tolist() self.result_ready.emit({boxes: boxes, scores: scores, labels: labels}) def stop(self): self.is_running False这个线程类的核心是result_ready信号它把检测结果从子线程传回主线程。torch.hub.load第一次加载会检查模型代码的一致性所以它并不适合放在run()里反复执行否则每次检测都会比较权重文件和当前代码的一致性校验造成明显延迟。4.2 在界面中加载权重并绘制检测框加载权重和绘制检测框是PyQt界面落地中比较繁琐的环节。QImage和OpenCV的BGR格式转换容易出错我一般把转换函数单独封装出来。torch.hub.load加载的模型在推理时接收BGR格式的numpy数组但显示时需要用QImage的RGB888格式才能在QLabel上正常展示。from PyQt5.QtGui import QImage, QPixmap import numpy as np def cv2_to_qpixmap(cv_img): rgb_image cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) h, w, ch rgb_image.shape bytes_per_line ch * w qimage QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888) return QPixmap.fromImage(qimage)检测到的目标框用Matplotlib或OpenCV绘制都可以。在界面场景中OpenCV的rectangle更直接因为坐标可以从pandas().xyxy里直接取。绘制结果要画在原始图像副本上不要修改传入模型的原图否则连续检测时会把上一次的框叠加进去。界面上还应该显示当前加载的数据集类别名称和对应颜色YOLOv5的result.names属性会以列表形式返回类别名比如[good, porosity, slag]。在绘制时给每个类别固定一个颜色这样工人在识别结果时能凭颜色快速判断缺陷类型。4.3 实时摄像头检测与帧率控制如果需要在界面上做实时摄像头检测不能每帧都做全尺寸推理。摄像头采集的画面分辨率一般是1920x1080直接缩放到640会损失大量小缺陷细节但直接按原始分辨率推理又会让帧率掉到个位数。一个折中方案是在界面上提供分辨率切换让用户选择640还是1280。帧率控制也是必须考虑的摄像头每秒钟输入30帧而YOLOv5s在CPU上推理一帧可能需要几百毫秒处理不过来是必然的。我建议把检测线程设置为由新帧触发即上一帧推理完成后才发送新帧不要按固定帧率发送这样界面显示的是当前能处理的最新帧而不是堆积旧帧。class CameraWorker(QThread): frame_ready pyqtSignal(np.ndarray) def __init__(self): super().__init__() self.cap cv2.VideoCapture(0) self.is_running True def run(self): while self.is_running: ret, frame self.cap.read() if ret: self.frame_ready.emit(frame) self.cap.release()这个线程只负责采集图像推理由独立的DetectThread来控制两者通过队列衔接。如果你把采集和推理放在同一个线程里采集到一帧后推理耗时过长队列里的帧就会堆积到几百帧内存持续增长。分离线程后采集线程天然丢弃未被推理的帧显存和内存占用都稳定在一个水平。5. 权重优化与界面联调的三个关键参数权重训练好了、界面能跑通了剩下的收尾工作比想象中更影响交付。三个参数值得在界面联调阶段反复验证conf_thres下限、iou_thres上限和输入尺寸imgsz。这三个参数直接决定了界面上检测结果是否可信值得单独调一轮。conf_thres指的是目标置信度的判定阈值在界面上做成滑块从0.05到0.95可调。焊缝检测的直觉是阈值越高越准但气孔这类小目标的置信度通常集中在0.3到0.5左右如果把阈值设到0.6以上界面上会出现大量漏报。在产线上检验操作工的接受度时我会把阈值默认值设到0.25让操作工根据误报情况自行往上调。iou_thres控制的是重叠检测框的合并程度如果同一道焊缝上的两个气孔距离很近在特征图上可能产生重叠框iou_thres越高相似框越容易被合并。但是焊缝检查场景里两个独立缺陷如果被强行合并成一个框在统计缺陷数量的时候就会少算这点尤其要提醒做数据集标注的同事。在界面中我给iou_thres建议范围是0.4到0.5低于0.4会出现同一个缺陷被重复画框高于0.5则容易把相邻缺陷合掉。第三个参数是推理时的输入尺寸imgsz。训练时用640界面里也保持640一致性是最重要的。我见过不少项目在训练时用640推理解析图片时却按原始尺寸送入模型导致检测结果严重劣化。如果要在界面里提供高清检测模式建议直接把imgsz设为1280并把conf_thres适当降低0.05作为补偿因为高分辨率下模型会输出更多候选框置信度分布也会发生变化。最后在权重的交付文件上best.pt和last.pt不要混用界面上显示当前加载的权重名称和训练时的验证mAP这样现场反馈问题的时候能快速定位是哪个版本。best.pt可以直接被PyQt加载但如果需要在没有PyTorch的机器上部署用export.py导出成.engine或ONNX格式再通过onnxruntime在界面上推理推理耗时能降低30%以上。我一般把导出步骤留在权重文件确认无问题之后再做避免反复导出浪费排障时间。界面右上角放权重切换下拉框时把best.pt和last.pt都列出来标注好各自的验证集mAP辅助现场人员理解为什么看起来差不多的两个文件结果会不一样。本文还有配套的精品资源点击获取