简介面向电力巡检与计算机视觉场景的YOLO输电线路数据集提供3334张图像对应的标注信息适合需要训练输电线路目标检测模型的算法工程师与研究者使用可帮助识别电线、绝缘子、铁塔等关键部件。压缩包内共2000个XML标注文件整体约366.78MBXML中记录了目标类别、边界框坐标等关键字段可直接用于YOLO训练前的标签转换或按VOC格式读取。资源面向真实巡检场景覆盖常见线路组件和异常状态能够支持绝缘子损坏、铁塔倾斜、电线断落等检测任务的模型开发也适合用于无人机巡检、移动监控车辆等实时识别场景。已有508人学习或下载数据规模适合作为中小型目标检测项目的基础数据集配合YOLO系列模型进行训练、验证与调优可帮助减少数据采集和人工标注的时间成本。1. 输电线路检测就这么落地先把3334张带标签图像用对像3334张带标签这种数据包真正的价值不在数量而在于帮你跳过了最耗时的打标环节。输电线路巡检要覆盖绝缘子破损、防震锤移位、鸟巢、异物悬挂这类缺陷如果自己用LabelImg从零标一个熟练工一天也就处理两三百张还得面对小目标带来的疲劳误标。数据到手之后真正决定模型能不能成的是目录怎么组织、标签是否干净、训练划分有没有泄漏这三件事。这篇笔记按整理数据→校验标签→训练调参→绕开翻车点→上线前验证的顺序把一条可以直接照走的YOLO训练路径讲清楚。适合目标是用现成数据集快速出第一版可跑模型、后续还要迭代的算法工程师和学生。2. 把3334张带标签图像变成可训练的YOLO数据集目录结构、标签校验与数据划分解压之后第一件事不是急着训练而是把目录结构理清楚。YOLO训练器以Ultralytics的YOLOv8接口为例对数据目录有固定约定images和labels两个同级目录各自包含train、val可再加test而且同名图片与同名txt标签一一配对。换句话说images/train/IMG_0001.jpg必须对应labels/train/IMG_0001.txt后缀可以不同主文件名必须严格一致。拿到zip先是解压看一眼如果已经排成这个结构就直接复用如果文件平铺在一个大文件夹里建议花十分钟重建结构免得训练时因为路径问题反复报错。另一件必须早期确认的事是类别清单。常见数据包会在根目录放一个classes.txt或data.yaml里面写明每个类别ID对应的名称有的包则只在标签文件里用数字ID表示类别。无论如何动手训练前要把各类别出现的次数统计一遍确认是否出现某个类只有几十张样本的情况。输电线路缺陷里绝缘子破损常常是主要类别鸟巢、异物这类目标数量少且外观差异大如果样本量悬殊后面要单独做类别加权或数据增强不能指望模型自己学会长尾类。注意类别ID从0开始计数标签txt第一列写的是类别ID不是类别名。排序错位会直接导致模型把绝缘子破损学成鸟巢这类错误在训练早期极难发现越往后排查成本越高。2.1 先摸清楚数据长什么样目录、文件名与类别清单解压后建议先打印一次目录树确认压缩包的真实结构再决定是直接用还是重新整理。一个能被标准流程直接吃下的结构长这样power_line_dataset/ ├── images/ │ ├── train/ │ │ ├── tower_001_01.jpg │ │ ├── tower_001_02.jpg │ │ └── ... │ └── val/ │ ├── tower_032_01.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── tower_001_01.txt │ │ ├── tower_001_02.txt │ │ └── ... │ └── val/ │ └── ... └── classes.txt这里labels目录里的每个txt文件记录的是该图片中所有目标的类别和位置。文件名前缀tower_001这类信息特别重要它通常代表杆塔编号后面做数据划分时用得上。如果发现压缩包里图片和标签混放在同一文件夹用下面这个命令按扩展名拆开mkdir -p images/labels mv *.jpg images/ mv *.txt labels/拆完以后立即核对两边文件数是否一致。3334张图像对应的标签文件数量应该也是3334允许少数空标签文件存在但数量不应多。文件数都对不上的话先解决缺失再往下走否则训练时Ultralytics会自动跳过没有标签的图片你不一定能及时发现却会悄悄影响评估指标。接下来统计类别分布。没有现成统计脚本时可以临时用一条shell命令把所有标签的第一列数字汇总cat labels/train/*.txt labels/val/*.txt | awk {print $1} | sort | uniq -c输出会类似3260 0、1184 1对应每个类别ID出现的标注框总数。看一眼就知道哪个类别是绝对多数哪个类别是稀缺样本。这个数字直接决定后续要不要做类别重采样如果某个类别占比低于5%训练时大概率学不好需要额外处理不要指望模型自动均衡。2.2 校验YOLO格式标签一个脚本过滤越界、负值与错位坐标LabelImg这类标注工具导出的YOLO格式每一行是五个数值class_id x_center y_center width height其中坐标全部做了归一化值域在0到1之间。真实项目里标签出错的方式远比想象中多有人标完忘了保存类别、有人用错了归一化基准、有人把左上角坐标当成了中心点。这些错误不会让训练直接崩但会让损失函数在一个错误的目标上反复震荡。我一般会先跑一遍标签校验脚本把异常行全部揪出来再训练。import os from pathlib import Path labels_dir Path(labels/train) max_class_id 4 # 按数据包实际类别数减一调整 for label_file in sorted(labels_dir.glob(*.txt)): with open(label_file, r, encodingutf-8) as f: lines f.readlines() for idx, line in enumerate(lines, 1): line line.strip() if not line: continue parts line.split() if len(parts) ! 5: print(f{label_file.name} 第{idx}行字段数不为5: {line}) continue try: cat, x, y, w, h int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) except ValueError: print(f{label_file.name} 第{idx}行存在非数值字段: {line}) continue if cat 0 or cat max_class_id: print(f{label_file.name} 第{idx}行类别ID越界: {cat}) if not (0.0 x 1.0) or not (0.0 y 1.0): print(f{label_file.name} 第{idx}行中心点越界: ({x}, {y})) if w 0.0 or h 0.0 or w 1.0 or h 1.0: print(f{label_file.name} 第{idx}行宽高异常: ({w}, {h})) # 框超出图像边界是允许的但如果超出超过20%基本就是标注错误 if x w / 2 1.2 or y h / 2 1.2: print(f{label_file.name} 第{idx}行超出图像边界过多: {line})脚本的逻辑分四层第一层检查字段数多字段少字段都会让YOLO在读取时解析错位第二层检查数值类型文本编辑器里混入不可见字符是常见的事故源第三层检查取值区间类别ID越界的典型原因是有人在标签文件顶部写了注释行第四层是经验性检查允许框略微越出图像边界因为目标被截断是常见情况但如果框的中心点加上半宽远超1.0基本都是标注基准错了。运行后如果打印为空说明这批标签基本干净可以放心进入下一步。2.3 按杆塔分组做数据划分避免同源图片泄漏到验证集数据划分是最容易被低估的一步。许多人直接随机切分train和val这对自然场景数据集通常问题不大但输电线路图像有一个特殊性同一个杆塔往往拍了多张不同角度、不同焦段的照片它们内容高度相似。如果同一个杆塔的图同时出现在训练集和验证集验证指标会虚高——模型见过这个杆塔的纹理和背景评估时相当于开卷考试。等部署到新杆塔上实际效果立刻回落这就是典型的验证集过好、现场翻车。一个更稳的做法是按文件名里的杆塔ID分组整组划入训练集或验证集保证同一个杆塔的照片不会跨界。文件名形如tower_001_01.jpg时前缀tower_001就是分组依据import random import shutil from pathlib import Path src_images Path(images_all) src_labels Path(labels_all) train_images Path(images/train) val_images Path(images/val) train_labels Path(labels/train) val_labels Path(labels/val) for d in [train_images, val_images, train_labels, val_labels]: d.mkdir(parentsTrue, exist_okTrue) groups {} for img_path in src_images.glob(*.jpg): group_key img_path.name.rsplit(_, 2)[0] # 提取 tower_001 前缀 groups.setdefault(group_key, []).append(img_path.stem) group_keys list(groups.keys()) random.seed(42) random.shuffle(group_keys) split_idx int(len(group_keys) * 0.85) train_groups set(group_keys[:split_idx]) val_groups set(group_keys[split_idx:]) for group in train_groups: for stem in groups[group]: shutil.copy(src_images / f{stem}.jpg, train_images / f{stem}.jpg) shutil.copy(src_labels / f{stem}.txt, train_labels / f{stem}.txt) for group in val_groups: for stem in groups[group]: shutil.copy(src_images / f{stem}.jpg, val_images / f{stem}.jpg) shutil.copy(src_labels / f{stem}.txt, val_labels / f{stem}.txt) print(train图片数:, len(list(train_images.glob(*.jpg)))) print(val图片数:, len(list(val_images.glob(*.jpg))))rsplit(_, 2)[0]的含义是从右往左拆两次取最左边的部分。文件名tower_001_01.jpg拆完得到tower_001这个作为分组键如果你的文件名没有规律就只能退而求其次按连续帧分组——拍摄时间相近的画面默认同源。划分之后顺手统计一下每个类别在训练集和验证集的占比如果某个稀缺类别恰好全被分进训练集验证集里它的AP会变成0看起来像模型完全没学会其实是划分造成的不必慌张重新切分即可。3. 训练输电线路缺陷检测模型环境搭建、数据集配置与训练参数怎么给数据整理干净之后就进入核心环节把YOLO跑起来。对一个刚接触目标检测的团队来说最大的认知门槛不是模型结构而是环境依赖和数据配置。输电线路检测任务本身不算复杂单类缺陷多类目标背景相对固定训练链路跑通之后迭代速度很快。下面以Ultralytics YOLOv8为例把从环境搭建到拿到第一个权重的完整过程拆开讲命令都是可以直接复制的写法。3.1 yolo环境搭建conda创建环境与ultralytics安装环境搭建这一步我建议用conda单独建一个虚拟环境别直接装在系统Python里。输电线路项目通常还要跑图像处理、报表生成、部署到边缘设备等多个流程依赖互相污染是后期最头疼的问题之一。按下面的命令就能完成基本安装conda create -n yolo python3.10 -y conda activate yolo pip install ultralytics装完以后先验证两件事第一yolo命令是否可用第二GPU是否能被框架识别。在终端里依次执行yolo help python -c import torch; print(torch.cuda.is_available())如果第二行输出True说明CUDA环境正常。输出False则先别急着训练检查NVIDIA驱动和CUDA Toolkit版本是否匹配。常见问题是驱动装了但CUDA版本太老PyTorch版本要求更高。这里有一个实用习惯安装后执行pip show ultralytics记下版本号写在项目README里。YOLO系列迭代很快你今天训完的模型半年后同一条命令可能因为框架升级产生不同结果记下版本是给未来的自己留后悔药。对于公司内网或下载受限的环境离线安装也没问题在一台联网机器上pip download ultralytics -d ./offline_pkg再将整个目录拷入内网pip install --no-index --find-links./offline_pkg ultralytics。数据集训练多半会在带GPU的服务器上执行环境一致性能免去大量本地能跑服务器不能跑的玄学问题。3.2 写数据集描述文件与训练命令关键参数和它们为什么这么设Ultralytics框架通过一个YAML文件描述数据集训练命令通过dataxxx.yaml引用它。该文件里的类别列表顺序必须与标签文件里的ID严格一致——ID 0对应第一个名字ID 1对应第二个依次类推。path: /data/power_line_dataset train: images/train val: images/val names: 0: insulator_break 1: damper_shift 2: bird_nest 3: foreign_bodypath建议写绝对路径避免相对路径在不同工作目录下产生歧义。train和val相对于path填写。如果类别清单与数据包内classes.txt不一致以标签txt里实际出现的ID分布为准必要时回到2.2节的统计结果逐一核对。YAML写好后训练命令本体如下yolo detect train \ datapower_line.yaml \ modelyolov8n.pt \ epochs200 \ imgsz1280 \ batch16 \ lr00.01 \ cos_lrTrue \ mosaic0.5 \ patience50 \ seed42 \ projectruns/train \ nameinsulator_run01modelyolov8n.pt表示从头开始训练的话框架会先下载这个预训练权重作为初始化yolov8n是最小版本显存有限时优先选它。imgsz1280是输电线路任务里最重要的参数之一——绝缘子上的破损、销钉缺失这类目标在原始图像里往往只有几十个像素默认的640分辨率会让小目标在下采样后直接消失。batch16按显存调整12GB显存跑1280分辨率时保险起见降到8。mosaic0.5表示马赛克增强的概率这种增强对丰富背景有帮助但会切碎小目标所以没有调到默认的1.0而是给了一半概率。patience50是早停耐心值连续50轮验证指标不提升就自动停止。输电线路数据集规模不大200轮上限搭配早停实际通常100轮左右就收敛。训练完成后会在runs/train/insulator_run01/weights/下生成best.pt和last.pt前者是验证集指标最优的权重后者是最后一轮的权重一般用best.pt。3.3 训练日志怎么读从loss到权重选择训练开始后终端会持续滚动输出日志核心指标是box_loss、cls_loss、dfl_loss和对应的验证集指标。刚开始几轮loss快速下降是正常的真正需要关注的是两条曲线是否平滑收敛训练loss持续下降、验证loss不再下降甚至回升说明开始过拟合。输电线路缺陷类别的样本差异不算大过拟合比欠拟合更常见。如果训练过程中发现验证集mAP长时间在某个低位震荡先别急着调模型结构回到数据上找原因。用训练日志里每个类别的AP分布作为诊断入口如果某一类的AP远低于平均线大概率是样本量太少或标注不一致。YOLOv8的日志里会在验证阶段打印每个类别的mAP50-95类别ID对应YAML里names的顺序能精确定位到是哪个缺陷学不好。显存占用也是一个重要信号。batch16但训练中途出现CUDA Out of Memory说明分辨率或batch对大显卡来说还是大了。这时优先降batch到8若仍溢出再降imgsz到960。别为了大batch硬上YOLO在小数据集上对batch没有那么敏感稳定训练比极限吞吐重要。4. 输电线路训练避坑5个最常翻车的问题与排查思路下面五条是从数据整理到训练结束几乎一定会遇到的坑每条按现象→原因→解决来写。这些经验大多不是算法层面的高深问题而是工程习惯问题但它们对结果的影响比模型结构改动更直接。4.1 loss在降但mAP不涨类别ID从1开始的经典错位现象训练loss曲线一路向下但验证集mAP一直在低位徘徊PR曲线形状非常奇怪混淆矩阵里几乎所有类都往同一类偏移。原因标注阶段有人习惯把标签导出成从1开始计数而YOLO的类别ID从0开始。于是全局所有目标都被当成类别1模型把整个数据集的分布都学偏了。另一种变体是YAML里names顺义和标签文件的ID对应不上比如标签是0代表绝缘子破损YAML里把0写成了鸟巢。解决训练前用2.2节的校验脚本检查标签ID的取值范围确认它确实落在0到类别数减1之间。如果发现ID整体偏大写一个脚本对所有标签文件做cat - 1的批量修正改完重新校验一次。这个坑之所以隐蔽是因为loss照样下降指标也不是完全为零——模型在认真学习一个错答案肉眼很难分辨。4.2 白天图效果不错逆光和阴天场景漏检严重现象训练集里大多是光线充足、背景干净的样本验证测试也表现正常。一换到实际巡检拍的逆光、雾天、阴影遮挡图像检测框数量骤减。原因可见光数据集里高质量样本占绝对多数模型学到了亮度正常这个先验而不是真正学到缺陷的形状特征。对输电线路来说逆光下的绝缘子串和顺光下的外观差异巨大但模型没有见过足够多的亮度扰动样本。解决训练时打开Ultralytics内置的颜色增强参数。hsv_h、hsv_s、hsv_v控制色相、饱和度和明度的随机扰动区间将hsv_v从默认的0.4调到0.6以上相当于给训练集强行扩展了明暗范围。如果手头有少量逆光现场图全部丢进训练集即使只有几十张也比单纯调参数管用。模型过拟合到亮度分布是一玄学但用数据把分布撑开是实打实的物理外挂。4.3 验证指标很好一到新塔位就翻车数据划分泄漏现象验证集mAP 0.9现场跑新杆塔的视频漏检率和误检率都高得离谱前后指标对不上。原因随机划分数据时同一个杆塔不同角度的图像被分到了训练集和验证集。验证集里出现的是见过的塔评估成绩虚高部署到新塔时背景、角度、光照全部是新的模型立刻回归真实水平。解决像2.3节那样按文件名前缀分组划分保证同塔图片不跨集合。如果原始文件名没有塔位信息退而求其次的做法是把连续编号的帧按时间窗口切块再按窗口划分。判断是否泄漏还有一个笨办法从验证集里随机挑几张图在训练集里用图像相似度搜索如果高度相似的图一抓一大把说明划分不干净重做。4.4 同一个目标时检时不检置信度门限没有校准现象模型权重没变同一张图多测几次结果稳定但换了不同拍摄距离的图同一个目标有时拿高分、有时低于阈值被过滤掉。误检率一高就提高置信度门限结果漏检率又上来来回拉锯。原因conf设得太高或太低都会让系统的查全率和查准率失衡。目标检测模型天然有召回和精度的取舍输电线路缺陷检测里漏检的代价远高于误检——漏一次就是真实的安全隐患误检顶多多花人工复核时间。很多人直接沿用默认conf0.25但没有针对自己的验证集看过置信度分布。解决训练完成后跑一次验证集画出F1值与置信度门限的关系曲线。曲线峰值对应的置信度就是当前模型最均衡的工作点。对输电线路场景我通常取F1峰值略低一些的置信度比如峰值在0.42实际部署取0.30左右换一点误检率来换漏检率的下降。4.5 销钉、破损绝缘子这类小目标基本检不到现象大尺寸缺陷能稳定检出一到销钉缺失、绝缘子细小裂纹这种目标就完全沉默precison和recall几乎为零。原因YOLO的下采样倍数决定了小目标的特征映射层分辨率不足。大目标在深层特征图里信息充足小目标经过多次下采样后只剩几个像素特征已经被稀释到无法分类的程度。imgsz640时一个原始图像里10像素宽的目标在特征图上不到一个格子。解决把imgsz提升到1280或1536小目标在输入端的像素规模直接翻了4倍以上效果立竿见影。显存不够就配合降batch。更高的分辨率还不够时采用滑窗切图推理把原图切成上下两块或四块分别检测再把检测结果按坐标合并回原图缺陷通常只占图像很小区域切图后它就变成了大目标。这个手段推理时用训练时保持整图输入即可。5. 用mAP、PR曲线和置信度门限做上线前最后一次验证训练完成后别急着把权重拷到设备上。先用官方验证命令对模型做一次全面体检确认它在哪个类别上偏弱再决定要不要调门限或补数据。yolo detect val \ modelruns/train/insulator_run01/weights/best.pt \ datapower_line.yaml \ imgsz1280 \ conf0.25 \ iou0.6 \ projectruns/val \ namefinal_check运行结束后重点看三个输出mAP50是对定位宽松程度的评估适合判断模型整体有没有学出来正常情况应该超过0.85mAP50-95更严格对框的精确度敏感数字低也不必过于担心它受小目标影响很大只要超过0.5就算可用按类别打印的AP列表才是真正要盯的东西它直接告诉你哪一个缺陷在拖后腿。验证目录里会生成PR曲线和混淆矩阵图片。PR曲线的右上角越接近(1,1)模型越理想曲线明显偏向坐标轴说明该类别的召回或精度有问题。混淆矩阵里如果目标类之间出现成片的互相混淆多半是标注边界不清晰比如防震锤移位和异物悬挂在某些角度下本来就难区分。这种问题靠调参解决不了只能回去翻数据集修正标签或补充边界样本。最后一件事是定部署用的conf阈值。验证输出的F1-confidence曲线会给出最佳平衡点。我的习惯是取比F1峰值低0.1左右的置信度作为部署门限——输电线路缺陷漏检要背安全责任宁可多给后台推送几条误检框让人工复核也不能让真实缺陷溜过去。把选定的置信度写进部署配置后用十几张没有参与训练的真实巡检照片再跑一遍推理确认整体效果符合预期。这步走完权重才算真正达到上线状态。每次完成一个新的训练迭代我会把best.pt连同当时的YAML和版本号一起归档下次调整参数时有个可溯源的基线。希望帮到你。本文还有配套的精品资源点击获取