简介:面向高校毕设学生和深度学习初学者的YOLOv5电线绝缘子缺陷检测完整项目,基于yolov5框架实现绝缘子缺陷目标检测,涵盖数据集、训练代码、预训练模型与教程讲解,适用于毕业设计、课程设计及期末大作业等场景。压缩包内含500个文件,主要包括yaml配置、Python脚本、jpg/jpeg图像样本、pt权重模型以及txt标注、ipynb教程等,整体约354MB,目录结构完整,便于直接运行和二次开发。资源中还有用于记录训练过程的events日志、演示视频、说明文档及多种辅助脚本,能够帮助使用者理解从数据准备、模型训练到结果评估的完整流程,覆盖环境搭建、数据标注到推理部署各环节。目前已有117人学习下载,项目为作者大四高分毕设(评审99分),代码经导师指导验证可运行,即便零基础也能按讲解逐步复现,是快速上手YOLOv5缺陷检测的实用资料。
1. YOLOv5电线绝缘子缺陷检测:先别急着训练,难的是数据这一关
“YOLOv5电线绝缘子缺陷检测源码+数据集+模型+教程讲解”这类资源在毕业设计圈里流传很广,但真正跑过一遍的人会发现,模型训练反而最省事,麻烦全在前面:缺陷样本稀缺、标注格式不统一、小目标在缩放后几乎消失。你拿到的哪怕是一套整理好的代码,第一步也不是急着点开train.py,而是先弄清楚手里的数据集到底长什么样、标签对不对得上、缺陷类型全不全。下面把实践下来最短的落地路径拆成六个部分:数据集怎么整理、YOLOv5怎么配置、训练参数怎么调、哪个环节最容易翻车,以及最后怎么做验收才像一份能拿出手的毕业设计。适合正在做相关毕设的学生,也适合电力巡检方向刚接触目标检测的开发者。
2. 用YOLOv5做电线绝缘子缺陷检测:数据集的标注、划分与增强
2.1 缺陷样本构成与收集取舍:破损、掉串、自爆和闪络怎么处理
绝缘子缺陷检测的重点不是检测绝缘子本身,而是绝缘子上的破损、裂纹、掉串、自爆,以及闪络烧伤。这些缺陷有一个共同点:在整张巡检图中通常只占几十个像素,周围全是天空、杆塔、导线和复杂背景。所以收集样本时不要只看图片总数,要按缺陷类型统计标注框的数量。常见的翻车现象是图片有一千张,但“掉串”只有十几个标注框,训练出来的模型对这一类缺陷基本没有泛化能力。
我看到很多毕设第一稿的处理方式是做类别加权,给少数类把损失权重调高。但如果缺陷样本本身只有二三十个框,调权重效果极其有限。更好的做法是先把“有缺陷区域”这个粗粒度目标检测做扎实,再做缺陷子类的细粒度识别;或者专门给缺陷区域截取放大后的图像块作为训练样本。顺序上,我一般先把目标分成“绝缘子本体破损/裂纹”“掉串”“闪络烧伤”三类,少于五十框的类别直接并入“其他缺陷”,不要让模型在一个几乎没有样本的类别上浪费参数。
还有一个容易忽略的采样问题:巡检照片往往来自无人机或巡线拍摄,原图分辨率可能到4000乘3000甚至更高。如果训练直接缩放到640,一个原本只有80乘40像素的缺陷块缩到10乘8像素,检测器基本不可能稳定学习。常见做法是先把大图切成有重叠的patch,比如按1024乘1024切片,训练和推理都用切片之后的图,等小目标漏检率明显下降之后再考虑整图训练。这个决策比调任何超参都更早做,而且直接影响后续所有环节。
2.2 把VOC标注转成YOLO格式:转换脚本与四个边界坑
YOLOv5的标注文件是txt格式,每一行代表一个对象:类别id、归一化中心x、中心y、宽w、高h。很多公开电力巡检数据集提供的是VOC的XML标注,或者LabelImg导出的XML,所以写一个转换脚本是绕不开的步骤。下面是我常用的转换逻辑,直接按images/train目录里的xml批量转:
# convert_voc_to_yolo.py import os import glob import xml.etree.ElementTree as ET def convert(xml_file, class_names, out_dir): tree = ET.parse(xml_file) root = tree.getroot() fname = root.find("filename").text img_w = int(root.find("size/width").text) img_h = int(root.find("size/height").text) lines = [] for obj in root.iter("object"): cls = obj.find("name").text if cls not in class_names: print(f"{fname} 里存在未定义类别: {cls},已跳过") continue cls_id = class_names.index(cls) box = obj.find("bndbox") x1, y1 = float(box.find("xmin").text), float(box.find("ymin").text) x2, y2 = float(box.find("xmax").text), float(box.find("ymax").text) # 转成YOLO格式,并做边界裁剪,防止标注越界 cx = min(max((x1 + x2) / 2.0 / img_w, 0.0), 1.0) cy = min(max((y1 + y2) / 2.0 / img_h, 0.0), 1.0) w = min(max((x2 - x1) / img_w, 0.0), 1.0) h = min(max((y2 - y1) / img_h, 0.0), 1.0) if w < 0.01 or h < 0.01: # 过滤掉退化成点或线的框 print(f"{fname} 中有宽度/高度过小的框,建议重新标注") continue lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}") txt_name = os.path.splitext(fname)[0] + ".txt" with open(os.path.join(out_dir, txt_name), "w") as f: f.write("\n".join(lines)) if __name__ == "__main__": # 类别顺序必须和后续data.yaml中的names保持一致 class_names = ["insulator", "broken", "flashover"] os.makedirs("labels/train", exist_ok=True) for xml_path in glob.glob("images/train/*.xml"): convert(xml_path, class_names, "labels/train")这个脚本的关键在两点:一是class_names的顺序决定类别id,训练时的data.yaml如果写成别的顺序,所有标签都会错位;二是归一化后的坐标要裁到0到1之间,XML里偶尔会有超出图像边界的坐标,不处理的话训练时会产生NaN损失,或者在推理阶段输出越界框。转换完之后不要急着训练,先随便抽几个txt,把对应的框画回原图看一遍。
这一步有四个常见坑。第一个是XML文件名与图片名不一致,脚本拿fname去拼txt输出名,但有的XML里filename字段带了子目录前缀,导致txt生成到错误路径。第二个是标注框退化成一个点或者单像素线,这类框对损失扰动很大,最好直接过滤并重新标注。第三个是类别顺序改来改去,训练一半才发现data.yaml里的names和txt里的id对不上,所有模型输出都错位,白跑几十个epoch。第四个是大图没有切片就强行缩放,小缺陷在resize过程中被抹掉,转出的标注虽然没报错,但实际上模型看到的是没有细节的退化图像。
2.3 按来源划分数据集与数据增强:别让同源图片泄露进验证集
很多人在划分数据集时只用一行随机shuffle,把全部图片按8比2切分。这个做法在绝缘子检测场景有一个隐患:如果同一段视频连续抽帧出来的几十张图片被同时分进训练集和验证集,验证集指标几乎必然虚高,因为模型已经见过同一个场景几乎一模一样的背景和绝缘子角度。等拿到真实巡检视频一测,mAP立刻掉几个点。
所以我在划分数据时会先按来源分组,比如同一文件夹、同一拍摄时间段的图片算一组,整组进训练集或验证集,再在组内做轻度打散:
# 把每张图所属的“来源组”作为第一列,再按组切分 find images_src -name "*.jpg" -printf "%h/%f\n" | \ awk -F/ '{print $2"/"$3, $2}' > sample_group.txt # 对组去重后按比例切分 cut -d" " -f2 sample_group.txt | sort -u > groups.txt total=$(wc -l < groups.txt) head -n $((total * 8 / 10)) groups.txt > train_groups.txt tail -n $((total - total * 8 / 10)) groups.txt > val_groups.txt # 然后根据组名单生成图片列表这段命令的思路是:不直接切图片,而是先切“来源组”。如果样本里存在同场景连拍,这一步能把验证集水分挤掉不少。对绝缘子缺陷检测来说,验证集里至少要有一定比例的缺陷框,避免val mAP看起来很高但实际没看到几个困难样本。切完后建议用一个简单脚本统计train和val里各类别框的数量,如果val里全是正常绝缘子,要手动调整。
2.4 缺陷样本太少时的增强策略:Mosaic之外我还会加什么
YOLOv5自带Mosaic增强,它把四张图拼在一起训练,对小目标检测有正面作用,但绝缘子缺陷样本少到这个程度时,Mosaic本身不够用。我一般会在数据层面额外加三类处理:随机亮度与对比度扰动来模拟阴天和逆光,随机高斯模糊模拟雾气场景,以及CopyPaste式的缺陷合成。
CopyPaste是我在电力巡检场景里最推荐的手段。做法很简单:从标注好的缺陷图中把缺陷区域抠出来,做随机旋转和亮度调整,粘贴到一张没有缺陷的正常绝缘子图上,同时写入新标注。合成样本不需要做得特别精细,因为检测器对局部纹理更敏感,只要粘贴边界别太生硬就行。每粘贴一张,缺陷类别的有效样本就多一个,比单纯靠损失加权稳得多。手头有两百个缺陷框,用这一招扩到八百框完全可行。要注意的是粘贴位置尽量放在绝缘子附近,让上下文看起来自然,否则模型会学到“背景里出现一块奇怪纹理就是缺陷”这种错误关联。
3. YOLOv5模型选型与源码结构:从data.yaml到anchor重聚类
3.1 为什么这个场景选YOLOv5而不是Faster R-CNN
接触过电力巡检检测的人应该清楚,Faster R-CNN在学术实验里对中等尺寸目标很稳,但落地速度和工程便利都不如YOLOv5。绝缘子缺陷检测有两个硬约束:一是巡线图像量大,推理速度要在实时或近实时级别;二是缺陷目标小、背景复杂,需要快速迭代数据来试错。YOLOv5的CSPDarknet骨干加PANet多尺度融合,在速度和精度之间平衡得比较好,而且源码结构清晰,训练、验证、导出、部署链路完整。
和其他YOLO版本相比,YOLOv5在毕设场景里还有一个不可忽视的优势:参考资料和踩坑记录最多。随便搜一个训练日志报错,基本都能找到对应解决方案。YOLOv8也很好,但很多基于v5的辅助代码需要重新适配。对于“源码+数据集+模型+教程讲解”这类项目,v5的学习曲线更平缓。
选型时可以做一个简单权衡:如果论文偏向工程实现和部署演示,选YOLOv5;如果论文偏向学术对比,可以YOLOv5为主、再加一个有代表性的两阶段模型做对照实验。不要两头都铺开,毕设周期内重训两组模型的时间成本远比你想象的高。
| 模型 | 推理速度 | 小目标表现 | 部署生态 | 适合本场景程度 |
|---|---|---|---|---|
| Faster R-CNN | 慢 | 中 | 一般 | 不推荐 |
| YOLOv5 | 快 | 中上 | 高 | 推荐 |
| YOLOv8 | 快 | 中上 | 较高 | 可作为对照 |
3.2 源码目录与data.yaml配置:先跑通epochs=1的验证
YOLOv5项目跑起来之后,最常打交道的文件就几个:train.py负责训练,val.py负责评估,detect.py负责推理,data目录下放数据集配置,models目录下放网络结构。很多新手一上来就把train.py的默认参数一顿乱改,结果环境都没跑通。我建议第一个动作是只配置data.yaml,然后跑一个epoch的验证,确认数据和模型能正常结合。
# data/insulator.yaml train: datasets/insulator/images/train val: datasets/insulator/images/val nc: 3 names: 0: insulator 1: broken 2: flashovertrain和val的路径可以是相对路径,也可以写绝对路径,但要注意yaml文件所在的目录不是基准,路径是相对你执行train.py的工作目录来解析的。names的顺序必须与上一章转换脚本里的class_names顺序完全一致,这是整个项目里最容易埋雷的地方。配置写完后,执行下面这条命令来验证数据流:
python train.py --data data/insulator.yaml \ --weights yolov5s.pt \ --img 640 --batch 8 --epochs 1这条命令只跑一个epoch,目的不是训练。它会在启动阶段打印数据集加载的情况,并通过首轮前向传播生成一些可视化图。如果中间抛错,绝大多数问题集中在label路径不对、标签解析失败、图片损坏三类。其中“标签解析失败”最常见原因是txt里的坐标超出了0到1的范围,或者类别id大于nc减1。一个epoch下来翻一下runs目录里的训练截图,就能看见标注框是否贴住缺陷区域,这一步检查到位,后面几百个epoch才不是白跑。
3.3 理解特征层与anchor:小目标缺陷的检测瓶颈在哪
YOLOv5通过三个不同stride的特征层分别负责大、中、小目标,stride 8那层保留更多细节,最有可能召回像素尺寸很小的缺陷。但对应地,这层感受野小,容易出现误检。所以对小目标缺陷,关键操作是让模型在stride 8这层上有足够的监督信号。
anchor是另一个需要关注的模块。默认权重里的anchor是在COCO数据上聚类出来的,适合行人、车、动物这类宽高比,而绝缘子缺陷往往细长,比如一条裂纹宽高比可以到1比5甚至更极端。训练时YOLOv5默认会重新聚类anchor,日志里能看到autoanchor的相关输出,但这个自动过程并不总是能收敛到合理值。我一般会先跑一个epoch的日志,看它给出的最佳召回率;如果训练集里缺陷框大多数小于10像素,单纯调anchor也很难解决,还是要回到输入分辨率或者切片方案上。
锚框的宽高比匹配阈值由anchor_t控制,缺陷框形状极端时,默认的4.0可能漏掉不少正样本。这个参数我一般会放宽到4.5或5.0,具体效果要在训练日志里对比正样本匹配数量的变化。如果改了之后正样本数量没有明显提升,说明问题不在锚框,而是标签本身太小。
4. 绝缘子缺陷检测训练参数调优:从train.py到可用的mAP
4.1 迁移学习与训练命令:img、batch、epochs该怎么权衡
第一次训练绝缘子缺陷模型,我建议不要从随机初始化开始,而是从已经发布的yolov5s.pt预训练权重继续微调。COCO预训练权重里虽然有大量日常物体,但它学到的通用边缘和纹理特征对绝缘子表面的玻璃、陶瓷材质仍然有很强的迁移价值。随机初始化从头训练,在样本量不足的缺陷场景下几乎必然过拟合。
实际训练时,我用过比较稳妥的起点是:
python train.py --data data/insulator.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 150 \ --patience 30 \ --cache ram \ --project runs/insulator --name exp1这里几个参数的选择意图是:--img 640是内存和检测效果之间的折中,如果显卡显存允许,可以提到1280,代价是训练时间几乎翻倍;--batch 16对单卡12G显存是安全值,显存不足时优先降batch,不要降img,否则小目标会更难。--epochs 150搭配--patience 30做早停,绝缘子缺陷训练中后期mAP会反复波动,patience太小容易把最优权重提前丢掉。--cache ram把图片一次性加载进内存,能明显减少数据读取瓶颈,但如果内存不够会直接OOM,可以改成--cache disk。
提示:显存不足时优先降batch,不要降img。640输入尺寸已经是小目标检测的下限,再低会让缺陷区域彻底消失。
训练过程中不要只盯train loss。train loss降到很低不代表模型可用,它可能只是把训练集背下来了。真正要观察的是每一轮结束后val上的P、R、mAP50和mAP50-95。尤其是mAP50-95,它对框的定位精度更敏感,如果它一直很低而mAP50很高,说明标注框质量不齐,比如有的标了整体绝缘子,有的只标了破损局部。
4.2 超参数怎么调:cls、obj和anchor_t的真实影响
默认hyp.yaml是一组在COCO上表现不错的值,但绝缘子缺陷场景样本不平衡,直接套用往往让模型对缺陷类别不够敏感。我一般会单独写一个hyp文件覆盖少量参数:
# hyp.insulator.yaml lr0: 0.01 lrf: 0.2 cls: 0.8 obj: 1.0 anchor_t: 4.5 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4cls从默认0.5提到0.8,目的是让分类损失的权重更大。什么时候需要动它?当模型能框住缺陷区域但经常把broken判成insulator,说明分类决策边界太粗糙,可以往上调。obj损失控制“这里有没有目标”的置信度,对背景复杂的杆塔场景,保持1.0左右比较稳。anchor_t从默认4.0放宽到4.5,是为了让细长的裂纹框更容易匹配到正样本。
不是所有超参都值得乱动。lr0和lrf一个是初始学习率,一个是最终学习率衰减比例,对收敛稳定性影响极大,默认0.01和0.2能覆盖大多数情况。如果一上来就把lr0改成0.1,训练大概率前几个batch就变成NaN。我的习惯是先只改cls、obj、anchor_t这三个,跑完整一轮训练再决定要不要动别的。调参时每次只改一个变量,否则翻车了都不知道是哪一项引起的。
4.3 用val.py评估模型:混淆矩阵与PR曲线怎么读
训练完成后,用val.py做一次正式评估,而不是只看训练日志里的val指标:
python val.py --data data/insulator.yaml \ --weights runs/insulator/exp1/weights/best.pt \ --conf 0.25 --iou 0.45 \ --project runs/insulator/val评估结束后会生成confusion_matrix.png、PR_curve.png、labels.jpg等文件。labels.jpg会把训练集和验证集里所有标注框按尺寸和位置统计出来,能直接看出数据分布是否合理。如果broken大量被模型分到insulator,说明缺陷样本的类内差异太大或标注边界不统一,先别急着加损失权重,回去检查标注框到底标的是“破损区域”还是“整个绝缘子”。标注逻辑不一致,任何损失权重都救不回来。
PR曲线的尾部形状也值得看。如果曲线在低召回率端下降很陡,说明存在相当一部分怎么调阈值都召不回的困难样本,通常是遮挡严重、目标过小或缺陷不明显。此时要补的不是超参数,而是数据增强和样本多样性。我一般还会把val集里置信度最低的几十个预测框单独导出成图看一眼,比只看曲线更能定位问题。
5. 避坑:绝缘子缺陷检测里5个高频翻车现场与排查方法
5.1 训练时报“labels not found”:文件名与标签路径没对上
现象:训练一启动就提示找不到对应标签文件,或者图片文件和txt名称完全对不上。
原因:多数是转换脚本写得不严谨,xml里filename字段带了路径后缀,或者jpg文件批量重命名后图片和label名字不再一致。
解决:先对比两个目录的文件名,命令就能快速定位:
find datasets/insulator/images/train -name "*.jpg" | xargs -I {} basename {} .jpg | sort > /tmp/img_list.txt find datasets/insulator/labels/train -name "*.txt" | xargs -I {} basename {} .txt | sort > /tmp/lab_list.txt diff /tmp/img_list.txt /tmp/lab_list.txtdiff的输出就是所有名称不匹配的样本。处理方式一是对图片重命名,二是把标签重新生成一遍。不需要手工改,写一个脚本按图片目录的basename统一生成txt即可。这个坑会导致前期数据整理全部做无用功,所以每次新增数据集后我都先跑这条diff,再进训练。
5.2 loss在降但mAP一直是0:归一化标签或类别序出了问题
现象:训练日志里loss稳步下降,但P和R一直是0,val集上完全没检测结果。
原因:最常见有两种。一是data.yaml中的names顺序和txt里的类别id对不上;二是转换脚本忘了归一化,txt里写的是像素坐标。这两种错误都不会在训练时报错,因为模型看到的是“合法”的数字,只是语义完全错乱。
解决:不要盲调超参,直接写个检查脚本把label画回原图。
# draw_label_check.py import cv2 def draw_label(img_path, txt_path, names): img = cv2.imread(img_path) h, w = img.shape[:2] with open(txt_path) as f: for line in f: cid, cx, cy, bw, bh = map(float, line.split()) x1 = int((cx - bw / 2) * w) y1 = int((cy - bh / 2) * h) x2 = int((cx + bw / 2) * w) y2 = int((cy + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(img, names[int(cid)], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 1) cv2.imwrite("check.jpg", img) # 用法:传入图片路径、对应txt路径、类别名列表 draw_label("images/train/001.jpg", "labels/train/001.txt", ["insulator", "broken", "flashover"])这段代码的输入是图片路径、txt路径和类别名列表,输出一张check.jpg。如果画出来的框明显没有包住目标,或者类别名是乱序的,优先修数据和yaml,而不是继续训练。这个脚本我几乎每个项目都要用一次,时间成本很低但能避免跑完几十个epoch才发现数据有问题。
5.3 小目标缺陷漏检严重:640分辨率不够,怎么办
现象:正常绝缘子都能框出来,但破损、掉串这类小缺陷大量漏检,置信度普遍低于0.3。
原因:缺陷在原始大图里可能只有几十像素,缩放到640后只剩几个像素,特征层下采样后信息基本丢失。
解决:最直接的办法是把--img提到1280重新训练,同时评估batch是否要减小。如果显存实在不够,就用大图切patch训练,比如把原图切成1024乘1024,有重叠区域,推理时同样切patch再合并结果。还有一个小技巧是训练和验证时开启测试增强,但测试增强会拖慢推理速度,毕设演示够用,工程落地不太推荐。
注意,提高分辨率并不等于一定能提升mAP。如果标注框中包含大量远处小目标,分辨率提升的同时标注精度要跟上,否则模型学到的反而是一堆模糊的错误监督信号。我在实际训练时通常会同时观察“每个epoch的标注框像素尺寸分布”,如果大部分缺陷框在输入图上仍小于20乘20像素,就要继续考虑切片。
5.4 val指标很好,真实巡检图片却翻车:数据分布偏移的问题
现象:在验证集上mAP50超过0.85,但拿一段全新的真实巡检视频试跑,漏检率明显上升。
原因:这是典型的数据分布偏移。公开数据集或自己收集的样本如果背景单一,比如全是晴天的杆塔、同一种拍摄角度,模型会把背景纹理和绝缘子特征一起记住,换到阴天、雾天、夜间就失效。
解决:往训练集里加入拍摄场景差异更大的图片,而不是只加绝缘子缺陷特写。用CopyPaste把缺陷合成到各种背景上,训练时开启随机亮度和模糊增强。我特别建议在训练过程中就留出几段完全没见过的视频,每训练几十个epoch用来做一次快速抽测,不要等到全部结束才发现泛化问题。答辩演示时最容易暴露的就是这一点,评审老师放一段现场视频,模型表现如何一眼就能看出差距。
5.5 GPU利用率只有30%:数据加载拖慢了整个训练
现象:训练时nvidia-smi显示GPU利用率在20%到40%之间波动,明显没跑满。
原因:图片解码、Mosaic拼接、数据增强都在CPU上完成,CPU处理不过来,GPU只能空转等待。机械硬盘读取慢、num_workers太小、内存不足都会加剧这个瓶颈。
解决:先加上--workers 8,再考虑--cache ram。如果数据集总大小不超过可用内存,cache ram效果立竿见影。还有两个细节:一是把数据集放在SSD上,机械硬盘下肉眼感觉不明显,训练却明显变慢;二是Windows下num_workers设置过高可能适得其反,甚至报DataLoader worker进程崩溃,可以先从4开始试。GPU利用率这个指标很能说明问题,它低于60%时不要盲目加batch,先解决数据管道的瓶颈。
6. 从模型到交付:绝缘子缺陷检测的进阶验证与推理加速
6.1 用一段真实巡检视频替代单张图片做验收
我习惯在第一版权重训练完之后,不先看val报告,而是找一段没剪过的真正巡检视频,直接跑批量推理并统计每一帧的输出框数和最高置信度。
python detect.py --weights runs/insulator/exp1/weights/best.pt \ --source video.avi \ --conf 0.25 --iou 0.45 \ --project runs/insulator/demo视频验证比单张图片更能暴露问题:连续帧中同一缺陷的置信度是否抖动、相邻帧边框是否跳动、有没有断续的漏检。这些现象在评估报告里看不出来,但答辩演示时非常明显。如果视频中“掉串”类缺陷有超过三分之一帧没有被检出,我会直接返回去补样本,而不是靠调阈值硬撑。
6.2 导出ONNX并跑一次边缘推理,验证落地可行性
毕业设计只做到训练完成其实有点站不住脚,导出一个ONNX模型成本很低,却能让整个项目显得完整。执行下面的命令即可:
python export.py --weights runs/insulator/exp1/weights/best.pt --include onnx导出后在CPU上也能推理,方便演示。如果要再进一步,可以考虑TensorRT加速,但边缘设备上的步骤更繁琐,建议作为加分项而不是必选项。导出后先在detect.py里指定onnx文件跑一张图,确认输出和pt权重一致,再做后续部署。
最后说一点我反复强调的话:堆高单张图片的mAP相对容易,但模型真正能不能用在电力巡检场景,最终要看它在没有见过的视频里的表现。我的习惯是每走一小步就抽测一次新场景,把真实样本暴露的问题往前放,而不是等所有训练都结束后再回头补数据。这个顺序比反复刷验证集指标高效得多。希望帮到你。
本文还有配套的精品资源,点击获取