YOLOv5焊缝缺陷检测实战:从数据集标注到PyQt界面与RK3568边缘部署 简介本资源面向工业质检与计算机视觉方向的开发者、学生及研究人员提供一套基于YOLOv5的焊缝质量好坏检测完整方案可用于钢材缺陷检测场景的算法验证与二次开发。压缩包共约2000个文件包含1134张jpg图像、1134个xml标签与1135个txt标签分别对应LabelImg标注的原始数据与YOLO训练格式另附已训练好的检测模型及PR曲线、loss曲线等评估结果整体约222.96MB。界面部分基于PyQt开发支持图片、视频与摄像头三种输入方式并提供相应选择项便于直观演示检测效果。目前已有987人学习下载读者可借此快速复现焊缝缺陷检测流程理解数据集组织方式、模型训练指标含义与推理界面搭建思路适合作为课程设计、毕业设计或工业检测项目的参考模板。1. 焊缝质检的现场困局为什么YOLOv5成了小团队的首选在钢结构车间待过的人都知道焊缝质检这件事长期靠老师傅拿放大镜看一条两米长的角焊缝气孔、咬边、焊瘤混在一起肉眼判断一致性极差。更现实的问题是一条产线每天几百个工件全检根本排不过来抽检又容易漏掉致命缺陷。YOLOv5焊缝质量好坏检测这套方案本质上就是拿一个轻量目标检测模型把焊缝区域里的缺陷框出来并分类再配一个PyQt界面让质检员在工控机上直接操作。它适合的是有几百到几千张标注图、算力在单张消费级显卡或边缘盒子级别的小团队不需要自建深度学习平台也不需要标注团队从头搭流程。权重、数据集、界面三件套齐了剩下的就是调参和踩坑。2. 焊缝缺陷数据集怎么攒从拍图到YOLO格式的完整链路2.1 焊缝缺陷的类别定义与拍摄规范焊缝质量好坏检测的第一步不是写代码是定义清楚你要检测什么。常见做法是把缺陷分成五类气孔porosity、咬边undercut、焊瘤overlap、裂纹crack、未熔合lack of fusion。但我不建议一上来就五类全上原因很简单——裂纹和未熔合的样本量通常极少强行五类训练会让模型在这两类上几乎学不到东西。我一般会先把气孔、咬边、焊瘤三类做扎实等样本量上来了再合并裂纹类。拍摄环节有几个硬约束。光源用条形LED从侧面打角度控制在30到45度正面打光会让气孔和咬边的阴影消失模型根本分不出来。相机离焊缝距离固定在300到400毫米太近景深不够太远缺陷像素太少。每张图里焊缝要占画面宽度的60%以上背景里不要出现其他焊缝干扰。拍的时候同一工件至少换两个角度因为咬边在某个角度下可能完全看不见。提示拍图阶段就要按缺陷类别分文件夹存放后面标注和划分数据集会省掉大量返工时间。2.2 标注工具选型与YOLO格式转换标注工具用LabelImg或者AnyLabeling都行导出VOC格式的XML。但YOLOv5吃的是txt格式每行是类别索引 中心x 中心y 宽 高全部归一化到0到1。转换脚本我一般自己写一个因为网上找的经常在边界框超出图像时不做裁剪导致训练时报坐标越界。import os import xml.etree.ElementTree as ET # 类别映射顺序必须和训练时的data.yaml一致 CLASS_MAP {porosity: 0, undercut: 1, overlap: 2} def voc_to_yolo(xml_path, img_w, img_h, out_path): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): cls_name obj.find(name).text.strip() if cls_name not in CLASS_MAP: continue bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 边界裁剪防止标注框超出图像范围 xmin max(0, min(xmin, img_w)) xmax max(0, min(xmax, img_w)) ymin max(0, min(ymin, img_h)) ymax max(0, min(ymax, img_h)) if xmax xmin or ymax ymin: continue cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{CLASS_MAP[cls_name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))这段脚本的核心逻辑是坐标归一化和边界裁剪。CLASS_MAP的索引顺序必须和后面data.yaml里的names列表严格一致否则模型学出来的类别全是错的。裁剪那两行是血泪经验标注时手抖把框拉到图像外面不裁剪的话YOLOv5训练直接报错退出。:.6f保留六位小数是YOLOv5官方推荐精度少了会在小目标上产生明显偏移。2.3 数据集划分与data.yaml配置图片和标签按8:1:1划分训练集、验证集、测试集。划分时要注意同一个工件的不同角度图不能跨集否则验证集精度会虚高。目录结构长这样weld_dataset/ images/ train/ val/ test/ labels/ train/ val/ test/data.yaml的写法path: /home/user/weld_dataset train: images/train val: images/val test: images/test nc: 3 names: [porosity, undercut, overlap]nc是类别数改了类别一定要同步改这里和转换脚本里的CLASS_MAP。我见过有人只改了一边训练loss正常下降但mAP一直是零排查了半天才发现是索引对不上。3. YOLOv5训练焊缝检测模型超参数怎么设才不翻车3.1 环境搭建与预训练权重选择环境用PyTorch加YOLOv5官方仓库就行。CUDA版本根据显卡驱动选30系卡用CUDA 11.x比较稳。预训练权重选yolov5s.pt焊缝检测这种场景不需要yolov5xs版本在单张RTX 3060上batch size能开到16训练速度快一倍以上精度差距在焊缝缺陷这种纹理明显的任务上通常不到2个点。git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt # 下载yolov5s预训练权重放到weights目录 python train.py --img 640 --batch 16 --epochs 150 \ --data ../weld_dataset/data.yaml \ --weights weights/yolov5s.pt \ --cfg models/yolov5s.yaml--img 640是输入分辨率焊缝缺陷里气孔可能只有十几个像素640是底线再低小目标就丢了。--batch 16在8G显存下比较安全显存不够就降到8但batch太小BN层统计不准精度会掉。--epochs 150配合默认的余弦退火学习率焊缝数据集通常100轮左右收敛150轮留足余量。3.2 焊缝场景下的关键超参数调整YOLOv5默认超参数是给COCO调的焊缝检测有几个必须改的地方。第一个是--hyp里的mosaic概率默认1.0但焊缝图拼接后会出现不自然的焊缝走向我一般降到0.5。第二个是anchors默认anchor是基于COCO的焊缝缺陷的宽高比偏极端咬边又细又长气孔接近方形重新聚类anchor能提2到3个点。# 用k-means重新聚类anchor python utils/autoanchor.py --data ../weld_dataset/data.yaml \ --weights weights/yolov5s.pt --img 640聚类完把输出的anchor写回models/yolov5s.yaml里的anchors字段。第三个是学习率默认lr00.01对焊缝这种小数据集偏大我一般降到0.005配合--cos-lr余弦退火loss曲线会平滑很多。注意改完anchor一定要重新从头训练不要在旧权重上继续训否则anchor和权重不匹配mAP会先掉再涨浪费大量时间。3.3 训练过程监控与早停策略训练时开TensorBoard看三个指标train/box_loss、val/box_loss、metrics/mAP_0.5。正常情况box_loss在前20轮快速下降之后缓慢收敛。如果val_loss在30轮后开始上升而train_loss还在降就是过拟合了要么加数据增强要么减模型容量。早停用--patience 3030轮mAP不涨就停。但焊缝检测有个坑——mAP可能在某个epoch突然跳一下又回落这是验证集太小导致的波动。我一般把patience设到50宁可多训一会儿也不错过真正的收敛点。# 断点续训意外中断后不用从头来 python train.py --resume runs/train/exp/weights/last.pt--resume会恢复优化器状态和epoch计数比重新加载权重再训要正确得多。我见过有人直接--weights last.pt接着训学习率调度器重置了结果loss直接炸掉。4. PyQt界面集成把模型塞进质检工位的落地细节4.1 界面布局与推理线程分离PyQt界面最容易翻车的地方是把推理放在主线程里点一下检测按钮界面就卡死。正确做法是QThread开子线程跑推理主线程只管刷新界面。from PyQt5.QtCore import QThread, pyqtSignal import cv2 import torch class InferThread(QThread): result_ready pyqtSignal(object, list) def __init__(self, model, img_path): super().__init__() self.model model self.img_path img_path def run(self): img cv2.imread(self.img_path) # YOLOv5推理size和训练时保持一致 results self.model(img, size640) boxes results.xyxy[0].cpu().numpy() self.result_ready.emit(img, boxes)pyqtSignal用来跨线程传结果object传图像数组list传检测框。推理时的size640必须和训练时一致改了会导致精度下降。results.xyxy[0]取的是第一张图的检测结果格式是[x1, y1, x2, y2, conf, cls]。4.2 检测结果可视化与置信度阈值调节界面上要留一个滑动条调置信度阈值因为不同产线的光照条件不一样固定阈值要么漏检要么误报。可视化时按类别给不同颜色气孔红色、咬边黄色、焊瘤蓝色质检员一眼就能分辨。def draw_boxes(img, boxes, conf_thres0.4): colors {0: (0, 0, 255), 1: (0, 255, 255), 2: (255, 0, 0)} names {0: porosity, 1: undercut, 2: overlap} for box in boxes: x1, y1, x2, y2, conf, cls box if conf conf_thres: continue c int(cls) cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), colors[c], 2) label f{names[c]} {conf:.2f} cv2.putText(img, label, (int(x1), int(y1) - 8), cv2.FONT_HERSHEY_SIMPLEX, 0.6, colors[c], 2) return imgconf_thres默认0.4是焊缝场景的经验值低于0.3误报会明显增多高于0.6漏检率上升。colors字典的键要和CLASS_MAP一致否则颜色和类别对不上质检员会看懵。4.3 模型加载与打包部署的注意事项模型加载用torch.hub.load指定本地路径不要让它去联网下载。model torch.hub.load(./yolov5, custom, pathweights/best.pt, sourcelocal) model.conf 0.4 model.iou 0.45sourcelocal是关键不写的话每次启动都尝试联网车间断网环境直接卡住。model.iou是NMS的IoU阈值焊缝缺陷密集时调到0.5以上避免相邻缺陷被合并。打包用PyInstaller时要把yolov5目录和权重文件一起打进去--add-data参数指定路径。打包后第一次运行会慢因为要解压临时文件这是正常现象。5. 焊缝检测落地避坑五条血泪经验5.1 现象训练mAP很高但现场漏检严重原因通常是训练集和现场光照条件不一致。数据集是在实验室打的条形光现场是车间顶灯焊缝反光特性完全不同。解决办法是现场补拍200张图加入训练集或者在推理前做直方图均衡化把光照差异拉平。5.2 现象模型把焊缝本身的纹理误判为缺陷原因是标注时把焊缝鱼鳞纹也框进去了。焊缝的鱼鳞纹在低分辨率下和气孔纹理接近标注必须严格只框缺陷区域不能把周围焊缝带进去。已经标错的要返工没有捷径。5.3 现象PyQt界面在工控机上闪退多半是OpenCV和PyQt的版本冲突。工控机通常装的是老版本Ubuntuopencv-python要降到4.5.xPyQt5用5.15.x这两个版本组合最稳。闪退时在终端跑一遍看报错通常是libGL.so.1找不到装libgl1-mesa-glx就行。5.4 现象推理速度只有几帧质检员嫌慢检查是不是用了yolov5x权重换成yolov5s速度能翻三倍。另外推理时开model.half()用FP1630系卡上还能再快30%。如果还慢把输入尺寸从640降到512精度掉1个点左右但速度提升明显。5.5 现象换了一批工件后模型完全失效焊缝检测模型对工件材质和厚度敏感。碳钢上训的模型直接用到不锈钢上反光差异会让mAP掉20个点以上。换材质必须补拍数据重新微调至少50张图冻结主干只训检测头20轮就能恢复。6. 把焊缝检测模型压到边缘盒子RK3568量化部署的实操技巧焊缝质检的最终形态往往不是工控机加显卡而是产线边上放一个RK3568这类边缘盒子成本低、功耗小、不用风扇。但YOLOv5直接往RK3568上搬会碰到算子不支持的问题必须走ONNX转RKNN的量化路线。第一步是导出ONNX。YOLOv5仓库自带export.py但要注意输出节点。RKNN对动态shape支持不好导出时固定batch为1。python export.py --weights weights/best.pt --include onnx \ --img 640 --batch 1 --opset 12--opset 12是关键opset 11在RKNN转换时Slice算子会报错opset 13又太新12是实测最稳的版本。第二步是量化校准。RK3568的NPU是INT8推理需要一批校准图来统计激活值范围。校准图从训练集里随机抽200张覆盖各种光照和缺陷类型。from rknn.api import RKNN rknn RKNN() rknn.config(mean_values[[0, 0, 0]], std_values[[255, 255, 255]], target_platformrk3568) rknn.load_onnx(modelbest.onnx) rknn.build(do_quantizationTrue, datasetcalib.txt) rknn.export_rknn(best.rknn)mean_values和std_values要和训练时的归一化参数一致YOLOv5默认是除以255所以std填255。calib.txt每行是一张校准图的路径。量化后mAP通常会掉1到3个点如果掉超过5个点说明校准集代表性不够要补一些极端光照的图。第三步是板上推理。RK3568的NPU推理YOLOv5s 640输入大概能到15到20帧够产线节拍用。后处理里的NMS建议放在CPU上做NPU做NMS效率反而低。# 板上推理核心调用 outputs rknn.inference(inputs[img]) # outputs是三个尺度的特征图需要自己写decode和NMS boxes decode_outputs(outputs, anchors, img_shape) keep nms(boxes, iou_thres0.45)decode_outputs要把三个尺度的特征图还原成边界框这部分代码YOLOv5的utils/general.py里有参考实现移植时注意anchor顺序要和导出ONNX时一致。NMS的iou_thres在焊缝密集场景下调到0.5避免相邻气孔被误合并。量化部署这条路我走过好几次最大的教训是不要等模型在PC上调到完美再上板因为量化本身会改变精度分布。正确做法是PC上训到mAP 0.85左右就导出量化板上实测看哪些类别掉点严重再针对性补数据微调。这样迭代两三轮板上精度能追到PC的95%以上。焊缝检测这种工业场景稳定比极致精度重要一个能在边缘盒子上7x24小时跑的0.82 mAP模型比一个需要水冷显卡的0.90 mAP模型有价值得多。希望帮到你。本文还有配套的精品资源点击获取