简介面向计算机专业毕业设计及深度学习实战人群这份YOLOv5电线绝缘子缺陷检测项目集源码、数据集、模型与教程于一体解决输电线路巡检中绝缘子破损、缺失等缺陷的自动识别问题适合作为毕设、课程设计或期末大作业。压缩包共500个文件包含51个py源码文件、63个yaml配置、7个pt预训练模型、53个jpg与21个png图像样本以及ipynb教程和mp4讲解视频整体约354MB目录结构完整可对照配置直接运行。项目经导师指导并获得99分评审代码已验证可跑通初学者也能按教程完成环境搭建、模型训练与推理测试。目前已有117人学习使用下载后能获得完整工程文件、标注数据集、模型权重及分步讲解覆盖数据准备、模型训练、评估和检测全流程便于快速复现并在此基础上开展改进。1. 把YOLOv5用在绝缘子缺陷检测这不是通用目标检测的简单搬运电力巡检无人机拍回来的绝缘子图像绝大多数是完好的真正带破损、掉串、闪络痕迹的样本往往只占个位数百分比。人工翻一遍一天能看几百张眼睛先受不了用YOLOv5做一个自动检测模型是这类毕设最常见的落脚点。YOLOV5电线绝缘子缺陷检测这个组合把源码、数据集、训练好的模型和教程绑在一起恰好解决了大多数同学卡在三件事上的问题环境起不来、数据集格式错、训练出来框乱飘。这篇笔记按我自己的落地顺序讲从为什么选YOLOv5开始到数据准备、训练调参、踩坑记录最后收在怎么把答辩讲出深度。适合正被毕设卡住、手里有标注数据或想重新组织数据的同学如果你已经跑通过别的一阶段检测器直接看第4章和第5章也能省下不少时间。2. 绝缘子缺陷检测任务的底层逻辑为什么是YOLOv5而不是先换算法2.1 绝缘子缺陷检测的三个难点决定了模型基线绝缘子检测不是通用目标检测的简单搬运它的输入和场景有三个明显特点。第一目标尺寸分布悬殊。一架无人机在安全距离拍的巡检图常见尺寸是几千乘几千像素绝缘子本身占据的区域很小缺陷部位就更小。YOLOv5 在三个尺度上做预测其中更浅层的那一级特征图保留更多小目标空间信息这对绝缘子裂纹、缺片这类几十个像素的小目标比较友好。第二前景和背景严重不平衡。绝缘子串挂在铁塔横担、导线、树木、山体前面形状细长边缘特征弱。有些场景下模型真正学会的不是“绝缘子坏了”而是“这一片纹理和背景不一样”导致换一组照片就失效。第三正负样本极度不平衡。完好的绝缘子永远占大多数破损样本经常只有几百张。这种情况下模型选型反而不能一味求“强”一个结构复杂度适中的一阶段检测器加预训练权重通常比二阶段检测器更容易在小样本上调稳。选型上我的结论很直白YOLOv5 是当前一阶段检测器里资料最全、调参成本最低的基线。更新的版本虽然框架更现代但对于一个毕业设计来说可参考的社区经验、现成脚本和踩坑记录远不如 YOLOv5 丰富。你遇到一个诡异报错时能找到的答案数量是完全不同的。2.2 数据集的构成边界先看统计再定类别这个标题背后的数据集往往包含两类东西一类是无人机拍摄的现场图另一类是从公开渠道整理或自己拍补的样本。拿到手里先不要急着标。我的习惯是先写一个小脚本做数据体检统计图片尺寸、标注框数量、框面积占比。import os from PIL import Image img_dir data/insulator/images/train label_dir data/insulator/labels/train for name in os.listdir(img_dir): img_path os.path.join(img_dir, name) label_path os.path.join(label_dir, name.replace(.jpg, .txt)) if not os.path.exists(label_path): print(f[缺标签] {name}) continue img Image.open(img_path) w, h img.size with open(label_path) as f: lines [line.split() for line in f.read().strip().splitlines() if line.strip()] for line in lines: cls, cx, cy, bw, bh [float(x) for x in line] print(f类别{int(cls)}: bbox 面积占全图 {bw*bh*100:.2f}%) img.close()这段代码做了两件事检查有没有“有图无标注”的脏数据粗略计算每个标注框在整张图里的面积占比。框面积占比非常重要如果大多数框都小于 0.5%说明这组数据是小目标为主的场景训练时输入尺寸就不能随便降到 320anchor 参数也要重点关注。类别怎么定是另一个容易被忽视的问题。我的建议是不要只分“完好/缺陷”两个类按实际缺陷形态分“破损、掉串、污秽/异物”再加“完好绝缘子”这样能避免把多种差异巨大的目标塞进一个类别导致模型内部特征冲突。配置文件里的 nc 写到几names 列表顺序是什么决定了训练时怎么读取 labels 下的 txt 文件这两个地方错一个就全乱。2.3 模型尺度的选择v5s 是毕设理智选择m 是备选YOLOv5 同源码下有 s/m/l/x 四档模型对毕设来说选择范围其实很窄。我给一个常见的对比表模型尺度特点训练显存参考适用场景yolov5s最小、速度最快精度合理约 4-6 GBbatch 16 时数据几百张、显存吃紧的电脑yolov5m精度高一个档次速度略慢约 8-10 GBbatch 16 时数据上千张、有中端显卡yolov5l精度更高不适合小样本约 12-16 GBbatch 16 时数据量很大时才值得yolov5x最大几乎不做毕设首选约 20 GB仅当你有充足数据和显存这个表里的显存是相对参考不是绝对数值实际以你运行环境的 batch 和 img 参数为准。我的原则是先选 s 跑通全流程论文里所有实验曲线都用 s 生成之后如果数据量和时间还够再用 m 做一组对比实验。这样既能保证毕设按时完成又能多出一个“模型尺度对精度影响”的讨论点比一上来就冲 l/x 实在得多。3. 把源码跑通的最小闭环权重、数据集、配置文件3.1 权重文件是怎么一回事预训练权重是你的后悔药拿到项目压缩包或从上游仓库下载 YOLOv5 源码后第一件事不是直接跑训练而是把权重文件搞明白。yolov5s.pt 是官方提供的预训练权重它是在大规模通用数据集上训练出来的模型参数。你自己的缺陷检测数据集往往只有几百到几千张如果从随机初始化开始训练网络连最基础的纹理、边缘、形状特征都要从头学收敛慢最终精度也差很多。所以我们一般用预训练权重做迁移学习在自己的数据集上微调。操作上就是训练命令里指定 --weights yolov5s.pt这个 pt 文件会初始化大部分层的参数只有类别输出层会按你的 nc 重新调整。有一点要注意不要以为下载了新版本的权重就能直接给这份源码用权重和源码的模型结构必须匹配否则加载时会报 key 不匹配或直接报错。毕设场景下最稳妥的做法是用与源码配套的官方权重文件。3.2 目录布局与 YAML 配置训练前先过这两关数据集的目录组织是翻车重灾区。YOLOv5 期望的布局是 images 和 labels 两个平行目录每张图片对应一个同名的 txt 标注文件。我一般会这样放data/insulator/ ├── images/ │ ├── train/ # 训练图片 │ └── val/ # 验证图片 ├── labels/ │ ├── train/ # 训练标注 │ └── val/ # 验证标注 └── insulator.yaml # 数据配置文件labels 里每个 txt 的一行格式是类别id x_center y_center width height四个坐标都是归一化到 0~1 的小数不是像素值。XML 或 JSON 转换时最容易错的就是这里很多人把左上角和右下角坐标直接填进去模型会拿一整张图当背景去学。然后写数据配置文件 data/insulator.yaml# 数据配置文件 path: data/insulator # 数据根目录 train: images/train # 训练图片目录相对于 path val: images/val # 验证图片目录 nc: 3 # 类别数量 names: [完好的绝缘子, 破损, 掉串] # 与标签里的 id 一一对应这个 yaml 文件是不是放在 data/ 下不影响训练关键是 path 和 train/val 的拼接方式。YOLOv5 在加载数据时会按“path 下的 train/val 字段”去拼接路径写成 images/train 而不是绝对路径重命名或换机器后迁移性更好。配好后可以用预训练权重在数据上快速跑一遍确认图片路径能正常读取同时直观感受原图里的绝缘子大概长什么样。看到标注框和物体大致对得上再进入训练阶段。3.3 用一条训练命令跑通正常需要多久我习惯的训练命令是这样的python train.py \ --data data/insulator.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0 \ --name insulator_v5s参数含义如下表参数作用毕设建议--data数据配置文件路径指到 insulator.yaml--weights初始化权重yolov5s.pt 即可--img训练输入尺寸640 是平衡点小目标多才升 1280--batch批量大小能开多大开多大OOM 就降到 8 或 4--epochs训练轮数100 起步看曲线再决定加不加--deviceGPU 编号0 是第一张卡正常跑起来后训练日志里每个 epoch 会打印 loss 和 mAP跑完后 runs/train/insulator_v5s/ 下会有 weights/best.pt、last.pt 和 results.png。best.pt 是验证集 mAP 最高的权重答辩演示、后续推理都用它last.pt 只是最后一轮的现场存档。如果训练到一半发现 loss 震荡不降不要马上加 epochs先回第 3.2 节检查数据。数据不对训练多久都是白搭这是我带同学做毕设时最常说的一句话。4. 训练与调参把 mAP 从 0.3 拉到 0.8 的实操路线4.1 毕设里最值得动的四个训练参数很多人拿到源码第一件事是去改网络结构我比较现实先看四个直接影响结果的参数有没有设对。第一个是学习率 lr0。YOLOv5 默认配合余弦衰减用小数据集时初始 lr0 按默认 0.01 通常没问题但如果发现 loss 在前几个 epoch 就震荡甚至飞掉把 lr0 调到 0.005 或 0.001。这个参数别看小它决定了一开始每一轮更新能走多远。第二个是 batch-size。它影响两个东西梯度更新的稳定性和 BN 层的统计量。毕设数据集小batch 16 和 batch 8 的效果差距往往不大但 batch 保持 8~16 是安全区太小比如 2 时 BN 会产生很大的噪声。如果显存不够优先保持 batch 8而不是硬降到 2。第三个是 img 尺寸。同样是 640 和 1280对小目标的效果差距非常大。如果绝缘子在原图上只有几十像素建议直接用 1280。代价是训练和推理时间成倍增加。还有一个折中方案训练用 640推理时把原图切成 patch 再送进去。第四个是 epochs。看清楚过拟合曲线比盲目追求 300 轮更重要。小数据集上常见的情况是训练到 80 轮之后 loss 还在缓慢下降但验证集的 mAP 已经稳住不动继续跑只是在加剧过拟合。我通常给出一组保守的推荐值lr00.01batch16img640epochs100然后单独拎出学习率和 img 做两组对比其他参数不变。这样训练结果有可比性论文也好写。4.2 数据增强的取舍mosaic 对长条形目标是把双刃剑YOLOv5 默认开启 mosaic 增强把 4 张图的随机区域拼成一张意图是丰富上下文、缓解小目标不足。这个增强在通用目标检测上很有效但在绝缘子这种长条形目标上有个明显的副作用绝缘子串经常被拼接边界切成两半标签框也跟着被裁掉大半模型学到的是“半截绝缘子”对完整目标的预测反而抖动。我的做法是分两段训练前 70% 轮次开启 mosaic让网络充分见各种拼接背景后 30% 轮次关闭它集中适应原图分布。YOLOv5 在超参数文件里通过 mosaic 字段控制0 是关闭1.0 是每张都做0.5 是 50% 概率。小样本场景我会把它设成 0.5 而不是默认 1.0同时把颜色增强相关参数稍微调大一点因为电力巡检图片的颜色变化比想象中大阴天、逆光、黄昏都会有影响。另外label_smoothing 这种小技巧我也会顺手开一点点一般 0.05~0.1 就够太大反而把类别概率压平导致检测框置信度整体下滑。4.3 从 results.png 定位翻车点训练结束后runs/train/xxx/results.png 汇聚了 train_loss、val_loss、precision、recall、mAP 五条曲线。这是一个很好的查看黑匣子内部运行情况的窗口比只看一闪而过的终端日志靠谱。你还可以直接读 results.csv 自己画图import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/train/insulator_v5s/results.csv) plt.plot(df[epoch], df[metrics/mAP_0.5], labelmAP0.5) plt.plot(df[epoch], df[metrics/mAP_0.5:0.95], labelmAP0.5:0.95) plt.legend() plt.savefig(my_map_curve.png)不同版本 results.csv 的列名可能有差异跑之前先打印 df.columns 确认一下。如何判断问题出在哪儿train_loss 降val_loss 不降且两者差距越拉越大过拟合。优先减少 epochs或者检查数据集是否需要扩充。loss 曲线横盘不动很可能数据标注有错比如某个类别混入了大量背景框。precision 高、recall 低模型偏保守漏检多调低置信度阈值或增加正样本。recall 高、precision 低误检多模型把背景当成缺陷检查类别定义是否过宽。有一条经验如果曲线里 mAP0.5 已经到 0.7 以上但 mAP0.5:0.95 很低比如 0.3说明模型能框住目标但对框位置的精确定位不足。这在绝缘子这种长条目标上很常见重点是检查标注框是否都紧密贴合了目标边界而不是留了一圈背景。5. 避坑排查绝缘子缺陷检测的 5 个常见坑5.1 坑一loss 正常下降但 mAP 始终上不去现象训练日志里 loss 一路下降看起来很正常但 mAP0.5 始终在 0.4 上下徘徊验证集检测框东一个西一个。原因90% 的情况是标注文件与图片错位labels 里的 txt 行坐标是归一化坐标但类别 id 超界或者数据划分时同一目标的标注混进了另一张图。解决不要直接看 mAP 数字先可视化一批验证图把真实标注画出来和原图对齐import os from PIL import Image, ImageDraw img_dir data/insulator/images/val label_dir data/insulator/labels/val save_dir visual_check os.makedirs(save_dir, exist_okTrue) for idx, name in enumerate(os.listdir(img_dir)): if idx 10: break img Image.open(os.path.join(img_dir, name)).convert(RGB) draw ImageDraw.Draw(img) txt_path os.path.join(label_dir, name.replace(.jpg, .txt)) if not os.path.exists(txt_path): continue with open(txt_path) as f: for line in f.read().strip().splitlines(): cls, cx, cy, bw, bh [float(x) for x in line.split()] w, h img.size x1 int(cx * w - bw * w / 2) y1 int(cy * h - bh * h / 2) x2 int(cx * w bw * w / 2) y2 int(cy * h bh * h / 2) draw.rectangle([x1, y1, x2, y2], outlinered, width3) img.save(os.path.join(save_dir, name))代码循环前 10 张验证图读取同名 txt把每个归一化坐标换算回像素坐标并画框。如果画出来的框完全没有包住目标说明标注与图片错位优先修数据如果框包住了目标再查 YAML 里的 names 顺序是否和标注 id 对齐。这一步是过滤掉大量假问题的通用方法。5.2 坑二batch-size 调大就显存爆掉现象按推荐参数训练到一半出现 CUDA out of memory只能把 batch 降到 2 甚至 1但小 batch 下 loss 震荡明显最终效果上不去。原因输入尺寸 1280 或模型从 s 升级到 m 后单张图占用的显存变大batch 16 所需显存是 batch 8 的近两倍。解决我的优先级是先保持 batch 8 左右用梯度累积模拟更大的批量可以看训练脚本里关于 accumulated batch 的实现。对不熟悉框架的同学最直接的办法是把 img 从 1280 降到 640换回 yolov5s然后再考虑 m 模型。不要在显存边缘反复试探省下的时间值得多跑两组实验。5.3 坑三测试集上成绩很好换一组实拍图就翻车现象训练时验证集 mAP 到了 0.85答辩演示时跑到另一组无人机拍摄的图置信度低且方框乱跳。原因这是典型的分布泄漏——训练集和验证集来自同一条飞行路线背景、光照、机型都高度一致模型学到的是“这组图的背景纹理规律”。解决划分数据集时不要随机 shuffle 单张图而是按拍摄任务来划分。比如某次航拍任务的所有帧归入训练集另一次航拍任务归入验证集这样验证结果更接近真实场景。同时加入一些不含绝缘子的负样本图让模型有机会学到“这是背景、不是目标”能有效拉高 precision。5.4 坑四VOC 或其他格式标注转完 txt 后 loss 飞掉现象转换脚本跑完没有报错但训练时 loss 直接冲到 20 以上然后慢慢掉下来反正不像正常训练。原因转换时 bbox 没有正确地从左上右下角坐标转成中心点加宽高的格式或者坐标没有除以图片宽高归一化更常见的是空标注文件造成 label 维度错乱。解决养成一个固定习惯转换后写一个脚本统计每一行坐标是否都在 0~1 之间是否有 width 或 height 为 0 的框这类框直接过滤。如果能画一张带检测框的图就顺手把 5.1 的检查也做了别攒到训练时才来后悔。5.5 坑五一个绝缘子被检测出多个重叠的框漏检和误检同时存在现象一张图上同一个破损区域叠了四五个框而旁边一个有明显掉串的绝缘子反而没框出来。原因推理时置信度阈值太低加上密集目标场景下 NMS 的 IOU 阈值没有调好。绝缘子串形态细长缺陷和本体又离得近重叠框就会大量出现。解决用 detect.py 推理时把置信度阈值从默认 0.25 提到 0.4~0.5IOU 阈值从 0.45 调到 0.3~0.35让 NMS 更激进地合并重叠框。命令大致是python detect.py \ --source test_images/ \ --weights runs/train/insulator_v5s/weights/best.pt \ --conf-thres 0.4 \ --iou-thres 0.35如果还要更精细可以按检测框长宽比做二次过滤。绝缘子外框基本都是长条形把长宽比明显偏离这个范围的框去掉能少很多误报。6. 验证与进阶把 Demo 变成能讲的技术深度毕设6.1 用测试集跑一次像样的推理评估训练完先不要急着写大段论文结论。用训练时没用过的测试集跑一次正式评估得到的是答辩时最有力的数字。python val.py \ --data data/insulator.yaml \ --weights runs/train/insulator_v5s/weights/best.pt \ --conf-thres 0.25 \ --iou-thres 0.45val.py 会在输出目录生成分类混淆矩阵、PR 曲线和每类精度。注意如果数据集结构里没有 test 目录就不要额外指定测试集相关参数否则会找不到测试图片而报错。评估数字跑出来后记得记住一个关键量每类召回率。答辩时评委大概率会问“哪一类最难检测”你如果能直接说出“掉串类召回率最低、因为样本最少”就比泛泛而谈有说服力得多。6.2 用两张图让答辩“有深度”高分毕设和普通毕设的区别并不只是 mAP 从 0.7 涨到 0.9而是能不能解释清楚 mAP 高在什么地方。最有效的两份材料是PR 曲线和失败案例图。挑一张漏检或误检的图解释“为什么模型在这里认不出破损”比十张漂亮的检测图更能说明你理解这个任务。如果还有余力可以对模型做一次可视化热力图看看网络究竟在关注哪些区域。这类输出在毕设答辩里被问到的概率极高几乎每个评委都会问“模型是凭什么判断出来的”。我自己试下来的效果是热力图能显著减少“你这个是不是玄学”这类问题。6.3 给检测脚本加一个可复用的入口想让整套代码更像作品而不是作业最后加一个输入图片路径、输出结构化检测结果的封装函数。我常用的是这段import torch def detect_one(img_path, conf0.4, iou0.35): model torch.hub.load(./yolov5, custom, pathruns/train/insulator_v5s/weights/best.pt, sourcelocal) results model(img_path, conf_thresconf, iou_thresiou) return results.pandas().xyxy[0].to_dict(records)这个函数返回每个检测框的坐标、类别、置信度可以接到后续的可视化脚本或统计脚本里。配上一段批量处理文件夹的调用整套系统演示部分就有了完整闭环。从 0.3 到 0.8我可以负责任地说模型结构的故事只占其中一小部分数据才是最后的底气。我自己踩偏的一条路就是先调参后洗数据最后发现把标注重新整理一遍比调一周超参数带来的提升都大。希望你从这篇笔记开始先检查数据再谈训练这样最省时间。希望帮到你。本文还有配套的精品资源点击获取