YOLOv5实现电力绝缘子缺陷检测:从数据准备到训练调参全流程
简介一份面向毕业设计与深度学习实战的YOLOv5电线绝缘子缺陷检测完整方案源自导师指导下评审99分的高分毕业设计项目适合计算机相关专业学生作为毕设参考、课程设计或期末大作业。压缩包共500个文件主要包括yaml模型配置、Python训练/推理脚本、pt权重文件、jpg样例图像、ipynb教程文档以及sh辅助脚本、csv标注表和md说明笔记整体大小约354MB目录结构清晰便于按模块查阅。已有117人学习下载。资源内含完整数据集与标注信息、可直接加载运行的训练权重、详细讲解与操作录屏并附带TensorBoard事件日志与训练过程记录覆盖从数据准备、模型训练到缺陷检测效果展示的全流程能够帮助初学者快速复现项目并理解YOLOv5在电力巡检场景下的实际应用思路对论文撰写与答辩演示也有直接参考价值。1. 为什么拿 YOLOv5 做电线绝缘子缺陷检测能撑起一个高分毕设电线绝缘子缺陷检测这个标题本质是“目标检测算法在电力巡检场景的一个硬核落地”。绝缘子串在输电线路里承担电气绝缘和机械支撑常年风吹日晒最容易出现自爆、破损、掉串这类缺陷人工巡检效率低、危险高无人机巡检拍回来的海量图片靠人眼看又慢又漏所以用 YOLOv5 做自动检测就成了电力视觉里非常典型的一个课题。它麻雀虽小五脏俱全有数据集、有标注、有训练、有评价、有部署论文和答辩的素材全是现成的。这个方向适合两类人一是毕业设计选了目标检测、想找一个既不难又不水的题目的学生二是电力行业里想用开源方案先验证可行性的工程师。下面把这条路完整走一遍从数据到训练到排错照着复现就能跑跑通了就是一套能演示的完整项目。2. 任务拆解与模型选型绝缘子缺陷检测到底检测什么为什么是 YOLOv52.1 先看懂任务本身绝缘子缺陷不是“找绝缘子”这么简单绝缘子缺陷检测的第一层是“检测绝缘子本体”第二层才是“判断有没有缺陷”。常见缺陷包括自爆玻璃/陶瓷绝缘子炸裂导致绝缘子片缺失、破损、裂纹和闪络痕迹。在图像上自爆通常表现为一串绝缘子中间明显少了一片破损表现为边缘不完整、有碎茬这两类是缺陷检测里最常作为正样本的缺陷类型。从目标检测的角度看标签设计一般有两种思路单类别检测只标insulator然后用分类分支去分正常/缺陷或者用异常检测思路做。多类别检测同时标注insulator-normal和insulator-defect让模型直接输出缺陷框。这是毕设里最常用、最稳妥的做法缺陷框直接作为检测结果直观且好答辩。数据标注的粒度要注意缺陷框通常只框破碎或缺损的那一片或那一片区域不要框整串绝缘子。如果框了整串正常串和缺陷串在视觉上极其相似模型会不知所措mAP 很难看。这一点在第 3 章还会结合脚本再强调一遍。2.2 为什么这个任务选 YOLOv5与其他方案的对比做绝缘子检测摆在你面前的有传统图像处理、两阶段检测器和 YOLO 系列三条路。传统方法阈值分割、边缘检测、HOGSVM在实验室的几张图上可能看着不错换一组光照、换一个角度的巡检图片就崩了电网巡检图片光照、背景、拍摄距离变化非常大传统特征根本扛不住。两阶段检测器如 Faster R-CNN 精度高但推理慢而且对新手来说配置和调参门槛高显存占用也大。YOLOv5 在这类“背景复杂、目标尺度相对固定、需要快速验证”的任务上是性价比最高的选择单阶段推理快训练资源和时间都可以接受官方仓库把数据加载、增强、训练、验证的流程全部封装好了一套命令就能跑通社区资料还特别多出问题搜一下就有答案。如果你做的是“无人机巡线视频实时检测”这类偏工程的方向YOLOv5 的推理速度优势还会进一步放大。有一种说法是“既然要高分为什么不干脆用 YOLOv8”。我的看法是不要为了追新而追新YOLOv5 的生态积累更深网上针对绝缘子、安全帽、工地围挡这类电力/基建场景的开箱教程基本都是基于 YOLOv5 写的答辩时老师也可能更熟 v5 的网络结构和参数。v5 换成 v8 在数据准备和训练命令上差别不大但如果你现在拿到的数据、标注或者教程是围绕 v5 整理的直接用 v5 能少踩很多版本适配的坑。2.3 从网络结构图看 YOLOv5 怎么做检测YOLOv5 的网络结构图可以从官方仓库的models/yolov5s.yaml里读出来核心是三个部分Backbone 用 CSPDarknet53 提取特征Neck 用 PANet 做多尺度特征融合Head 用三个不同尺度通常对应 8、16、32 倍下采样的输出特征图做检测。CSP 结构把特征图分成两部分一部分经过残差块一部分直接拼接好处是在减少计算量的同时保留梯度信息训练时不容易梯度消失。PANet 的作用是让大目标的高层语义信息向下传播让小目标的低层纹理信息向上传播这样对“小尺寸缺陷”更有优势——绝缘子缺陷往往只占整张巡检图很小的一块区域尺度小、纹理弱靠低层特征里的边缘信息才能捕捉到。训练时推理逻辑也要理解一些才好调参每个特征图上的每个网格会预置 3 个不同大小的锚框anchor预测的是“锚框到目标框的偏移量、宽高缩放、目标置信度、类别概率”四部分。这意味着锚框设置是否贴近你的数据分布直接影响收敛速度和最终精度。YOLOv5 在训练时会自动用 k-means 重新计算数据集的锚框--noautoanchor可以关掉这个行为所以即使默认锚框不太适合绝缘子这种长条形目标训练脚本也会帮你矫正。这是 YOLOv5 对新手最友好的一点也是我在 4.2 里建议你务必保留的默认行为。3. 数据集准备从公开数据到 VOC 转 YOLO四个边界坑一次讲清3.1 起步用公开数据集别一上来就自己拍绝缘子缺陷检测的公开数据集最常见的是 CPLIDChinese Power Line Insulator Dataset在公开渠道能搜到里面包含正常绝缘子和自爆/破损绝缘子的图片已经带标注下载后解压就是图片和 XML/VOC 格式的标注文件。假设你手头拿到的是 VOC 格式文件夹里通常是JPEGImages和Annotations第一步就要把它转成 YOLOv5 能读的 TXT 格式。为什么 YOLOv5 用 TXT因为每个图像对应一个同名.txt每一行是“类别id x_center y_center width height”这种纯文本格式读取开销最小也方便做训练集/验证集划分时直接按文件名操作。我不建议一上来就自己拍照片标注。第一自己采集的数据量通常只有几百张类别不均衡严重正常样本远多于缺陷样本模型很容易学成“只认正常、不认缺陷”。第二标注质量没人校验框偏了一个像素训练出来的模型边界就是歪的。正确做法是用公开数据集把整个流程先跑通拿到一个能用的基线和一套可复用的数据处理脚本再根据自己的场景补充数据。3.2 VOC 转 YOLO 的转换脚本坐标换算与类别映射假设你的标注文件是 Pascal VOC 的 XML结构大概是nameinsulator-normal/name、bndbox里有xmin ymin xmax ymax。你需要写一个脚本把它转成 YOLOv5 要求的归一化中心点坐标格式。下面的脚本是常见做法我在不同项目里反复用过可以直接抄import xml.etree.ElementTree as ET import os # 类别映射按你的 labels 顺序排列YOLOv5 的类别 id 从 0 开始 CLASSES [insulator-normal, insulator-defect] def voc_to_yolo(xml_file, out_txt, img_w, img_h): tree ET.parse(xml_file) root tree.getroot() lines [] for obj in root.iter(object): name obj.find(name).text if name not in CLASSES: continue # 跳过不在类别表里的目标 cls_id CLASSES.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) # 转成中心点 宽高并归一化到 0~1 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h # 边界值裁剪防止标注越界导致训练报错 x_center max(0.0, min(1.0, x_center)) y_center max(0.0, min(1.0, y_center)) w max(0.0, min(1.0, w)) h max(0.0, min(1.0, h)) lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines)) # 批量转换遍历 Annotations 目录下所有 XML ann_dir Annotations txt_dir labels img_dir JPEGImages for xml_name in os.listdir(ann_dir): if not xml_name.endswith(.xml): continue img_name xml_name.replace(.xml, .jpg) img_path os.path.join(img_dir, img_name) # 实际项目里用 cv2 或 PIL 读图片拿宽高这里省略见下方说明 img_w, img_h 1920, 1080 voc_to_yolo( os.path.join(ann_dir, xml_name), os.path.join(txt_dir, xml_name.replace(.xml, .txt)), img_w, img_h, )逻辑说明脚本核心是把(xmin, ymin, xmax, ymax)换算成(x_center, y_center, width, height)再把所有数值除以图片宽高归一到 0~1YOLOv5 在 dataloader 里会自动乘回原图尺寸去匹配特征图。类别 id 必须和配置文件里的names顺序一致顺序错了模型会把“缺陷”当成“正常”来学这属于最隐蔽的一类低级错误。参数说明CLASSES的顺序不能随便排训练时的data.yaml里names列表要和这里完全一致裁剪那四行是保险部分公开数据集的标注框会超出图像边界不裁剪的话部分版本的 dataloader 会直接报警告甚至报错。需要注意真实项目里图片宽高不是写死的建议用cv2.imread或PIL.Image.open读取后动态获取上面写死只是为了示例清晰。3.3 划分数据集train/val/test 的规矩与增强策略转换完格式后做数据划分YOLOv5 的习惯是建三个目录图片放images/train、images/val、images/test对应标签放labels/train、labels/val、labels/test。划分比例我一般用 8:1:1并保证同一张绝缘子串的不同裁剪图不要同时进训练集和验证集——如果验证集图片和训练集图片太相似指标会虚高答辩时如果被追问数据泄露会很尴尬。用下面的脚本一次性划分# 把图片和对应标签按 train/val/test 划分到对应目录 python - EOF import os, random, shutil random.seed(42) img_files [f for f in os.listdir(JPEGImages) if f.endswith(.jpg)] random.shuffle(img_files) n len(img_files) train_imgs img_files[: int(n * 0.8)] val_imgs img_files[int(n * 0.8): int(n * 0.9)] test_imgs img_files[int(n * 0.9):] for split, files in [(train, train_imgs), (val, val_imgs), (test, test_imgs)]: os.makedirs(fimages/{split}, exist_okTrue) os.makedirs(flabels/{split}, exist_okTrue) for img in files: shutil.copy(fJPEGImages/{img}, fimages/{split}/{img}) txt img.replace(.jpg, .txt) if os.path.exists(flabels/{txt}): shutil.copy(flabels/{txt}, flabels/{split}/{txt}) EOF划分完先数一下缺陷类的框在训练集里有多少个。如果缺陷框数量不到正常框数量的十分之一模型大概率把缺陷学成噪声。这时候有两个补救方向一是对缺陷样本做过采样让缺陷图片在训练集里重复出现二是靠 YOLOv5 内置的增强策略硬扛。YOLOv5 默认开启了 mosaic、随机仿射变换、HSV 扰动、水平翻转其中 mosaic 把四张图拼成一张训练对绝缘子这种小目标密集场景很有帮助。但有个细节绝缘子缺陷有时只有几个像素宽mosaic 会进一步缩小目标尺寸导致缺陷更容易被当成背景。遇到这种情况我一般会在hyp.yaml里把mosaic的概率调低到 0.5 左右或者干脆关掉用随机裁剪和复制粘贴增强去补充。哪种效果好在你的数据上要实测对比不用盲信默认值。4. 从零训练YOLOv5 源码准备、参数设置与结果判读4.1 环境与源码准备版本锁定比“装最新”更重要先把环境装稳。YOLOv5 官方仓库在 GitHub 上可以直接拉取推荐用一个干净的 conda 环境Python 3.8~3.10PyTorch 版本按官方requirements.txt装。这里踩过一次坑不要用最新的 PyTorch 2.x 配合很旧的 YOLOv5 commit有些版本的torchvision和 YOLOv5 的 NMS 算子不兼容训练能跑、验证时报错。常见做法是固定一个版本组合然后把requirements.txt里的核心依赖装齐conda create -n yolov5 python3.9 -y conda activate yolov5 pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cu118 git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt逻辑说明torch和torchvision的版本号要配套上面这对是经过验证的稳定组合CUDA 版本按你自己的显卡驱动来选cu118对应 CUDA 11.8。requirements.txt里包含了 numpy、opencv、matplotlib、seaborn 等依赖一次装齐能省很多后续报错。如果显卡显存只有 6G 甚至更小建议直接用yolov5s权重起步别用yolov5l或yolov5x否则一开训练就 OOM。完善目录结构把你的数据和标注按上一章的样子放进yolov5目录外的一个数据目录然后在yolov5/data/下新建一个insulator.yaml配置文件是训练脚本识别人、类别和路径的唯一入口务必先写好# insulator.yaml train: /data/insulator/images/train val: /data/insulator/images/val test: /data/insulator/images/test nc: 2 names: [insulator-normal, insulator-defect]YAML 里的train、val路径可以是绝对路径也可以是yolov5目录下的相对路径。需要注意路径写错时 YOLOv5 不会立刻报错而是会在第一次读数据时打印一堆警告“找不到图片”然后训练出来的模型 mAP 是 0。这种错误很隐蔽我第一次跑的时候足足排查了半天。建议训练前先手动ls一下这几个路径确认图片数量不为零再启动训练。4.2 训练启动与关键超参数一次讲清四个必调的参数启动训练的命令如下这是我在多个项目里验证过的“起步配置”cd yolov5 python train.py \ --data data/insulator.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --workers 4 \ --device 0 \ --project runs/insulator \ --name exp1逻辑说明--weights yolov5s.pt表示加载 COCO 预训练权重做迁移学习这对绝缘子这类目标极其关键——预训练模型已经学会了通用的边缘、纹理、形状特征新任务只需要微调100 个 epoch 就能收敛。如果你从零随机初始化训练同样的数据至少要 300 个 epoch 效果才勉强能看。--img 640是训练时输入图片的边长YOLOv5 会自动做 letterbox 缩放不会强行拉伸变形。--batch 16在 8G 显存上配合yolov5s是安全值显存不够就降到 8显存够就升到 32batch 太小小于 8会导致 BN 层统计量不稳loss 波动大。参数说明四个必调参数是--img、--batch、--epochs和--weights。--img直接决定了小目标的可检测性如果巡线图片里绝缘子串占整张图的比例很小把--img从 640 提高到 1280 通常能显著提升召回但显存和训练时间会成倍上涨。--epochs不建议一上来就设 300先设 100 看收敛曲线如果 val mAP 在后 20 个 epoch 还在涨再续训。--weights务必要用 COCO 预训练权重第一次跑就用--weights 属于浪费算力。还有一个容易被忽略的参数是--hyp训练脚本默认读data/hyps/hyp.scratch-low.yaml。里面lr0初始学习率默认 0.01配合--batch 16是合理搭配如果你把 batch 调到 32 或 64可以同步把lr0调到 0.02 甚至 0.04否则在大 batch 下学习率偏低收敛变慢。这个规律我在换显卡时反复验证过batch 翻倍、学习率跟着翻倍是常见做法但不要超过 0.05否则前几个 epoch loss 直接起飞。4.3 训练结果判读mAP、PR 曲线和 loss 曲线怎么看出问题训练结束后在runs/insulator/exp1/下会生成一系列文件最重要的三个是results.png、confusion_matrix.png和val_batch0_pred.jpg。不要只看 mAP 数值先把results.png打开里面画了训练/验证的 box loss、cls loss、obj loss 和 mAP 曲线。诊断方法我总结为三条如果三行 loss 在后 20 个 epoch 仍然显著下降但没有收敛迹象说明 epoch 不够续训练。如果验证集 mAP 在某个 epoch 后开始掉头往下而训练 loss 还在降这是过拟合信号下一步是加数据增强、加 dropout 或减小模型容量。如果 mAP 一直在 0.2 附近上不去先别调模型回头检查confusion_matrix.png如果正常类与缺陷类互相混淆严重多半是缺陷样本太少去做类别平衡如果大量的缺陷被分到了背景类多半是标注框太小或--img分辨率不够调大--img再试。val_batch0_pred.jpg是验证集第一张图的可视化结果框的置信度阈值默认 0.25。以我的经验拿到这个图先看两件事缺陷框有没有套在真正的破损位置上以及同一个缺陷有没有被重复框两三次。如果重复框很多说明 NMS 阈值或置信度阈值需要调整这属于后处理问题放到最后一章再说。答辩时这张图就是最好的讲解素材把预测结果图和原图并排贴在论文里比任何公式都有说服力。5. 避坑与排错训练绝缘子的五个高频问题5.1 训练 loss 是 NaN 或突然变成超大值现象前几个 epoch 正常某一步 loss 变成nan之后训练直接崩掉TensorBoard 里的曲线掉坑里爬不出来。原因最常见的是学习率设置太大叠加 mosaic 增强里某些样本的标注框在仿射变换后坐标越界导致 loss 计算出现无穷大其次是数据里有损坏的图片或除数为零的异常尺寸。解决把hyp.scratch-low.yaml里的lr0降到 0.005并把box损失权重稍微降低同时在数据预处理脚本里过滤掉宽高小于 5 像素的标注框这类超小框对检测没有意义还容易让 loss 不稳。再不行就把--img调小一档从 640 降到 512问题基本能消失。5.2 mAP 很高但实际图片上一塌糊涂现象验证集 mAP 0.85看起来很美但拿一张网上找的巡检照片去测试模型要么什么都框不出来要么满图乱框。原因最常见的是验证集和训练集划分不当造成的数据泄露比如同一个绝缘子串的不同拍摄角度被同时分到了两边模型其实是“背题”而不是“学会了”。解决按图像来源拍摄时间或文件名前缀分组划分数据集而不是按文件随机划分另外把测试图换成没有出现在训练集里的新图。这个坑在毕设答辩里被问到的概率很高提前想好解释比临时圆场强。5.3 缺陷类别全是漏检召回率惨不忍睹现象正常绝缘子全部正确缺陷框漏掉一半以上PR 曲线里缺陷类的召回率只有 0.3 左右。原因类别不均衡是第一嫌疑——公开数据集里缺陷框可能只占全部框的 10%模型天然对少数类不敏感第二个嫌疑是缺陷目标太小640 输入下缺陷区域可能只占十几二十个像素特征图下采样后信息几乎没了。解决先做样本过采样或复制粘贴增强把缺陷框占比提到 30% 以上然后把--img提到 1280 配合--batch减半mAP 通常能涨 5 个点以上。如果还不行就增加一个“裁剪放大”的数据增强把含缺陷的图片按缺陷位置裁出来放大后重新参与训练这是我在实际项目里效果最显著的一招。5.4 训练时显存溢出OOM或训练到一半被系统杀死现象启动训练几分钟后报CUDA out of memory或电脑直接黑屏/卡死。原因--img 1280--batch 16yolov5l组合下显存需求超过 12G很多人忽略了一个隐藏开销YOLOv5 在训练时会同时缓存了 mosaic 增强后的多张原图和标注这部分临时显存占用比模型本身还大。解决三步降显存按顺序执行——把 batch 降到 8把--img从 1280 降到 960 或 640换成yolov5s.pt。如果还想继续用大图在train.py里加--cache ram可以省去磁盘 IO 但会增加内存占用反而可能触发 CPU 内存不足不如直接降分辨率。我个人的血泪经验是一台 8G 显存的笔记本老老实实 640 batch 8 yolov5s速度和质量最平衡。5.5 第一次跑通一切正常换数据后 mAP 骤降现象用公开数据集训练 mAP 0.9换上自己拍的照片重新训练mAP 掉到 0.5。原因领域差距domain gap公开数据集的拍摄距离、光照、绝缘子型号和你自己的数据差别很大另一个潜在原因是自拍数据的标注质量参差不齐比如缺陷框画得过大或过小。解决先用公开数据集的权重当预训练再在自己的数据上微调 50 个 epoch比从 COCO 权重直接开训收敛快很多同时对自建数据做一轮标注质量抽检随机抽 30 张图给标注框打层叠显示肉眼检查框和目标的贴合度。这种方法能稳定把 mAP 找回来 10 个点以上不用怀疑模型能力先怀疑数据和标注。6. 往高分再走一步模型轻量化部署与现场演示验证毕设拿到“能跑”不是终点拿到“能演示、能解释、能扩展”才是高分的关键。我建议最后做三件事导出模型、做一次小目标增强的消融实验、写一个简单的推理脚本。先从轻量化说起用 YOLOv5s 训练好的best.pt可以转成 ONNX 格式并量化为 FP16推理速度提升且显存占用减半。命令是官方自带的cd yolov5 python export.py \ --weights runs/insulator/exp1/weights/best.pt \ --include onnx \ --half导出后写一个十行左右的推理脚本读单张图片、跑推理、把结果保存并打印每类的置信度。演示的时候用这个脚本跑三张图一张正常、一张自爆、一张含多个小目标比在论文里贴截图更有冲击力。如果你想解释“为什么调参”就做一组对比实验默认参数一组关闭 mosaic 一组--img 1280一组每组训 100 epoch把三组的 mAP 画在一张图里。这个消融实验成本不高却是答辩里最能体现工程思维的加分项。我习惯把这三组结果和对应的训练日志一起放进项目仓库每次被问“你怎么确定这个参数是有效的”直接把图打开就行。最后提醒一句不要用过大的--img和过深的模型去硬撑精度而不考虑演示机器毕设演示现场往往是几年前的笔记本或集成显卡跑不动 FP32 大模型是常事。把best.pt量化成 FP16 或 INT8既能保住演示流畅度又能展示你对工程部署的理解。做这个项目时我把跑通的模型、导出脚本和消融实验记录整理在一个目录里答辩完老师还专门拷走了我的结果图去做参考。希望帮到你。本文还有配套的精品资源点击获取