尧图精选

输电线路电力金具检测数据集:YOLO训练全流程与避坑指南

🕒 发布时间:2026/10/2 8:38:03 📁 来源:尧图网络
简介面向输电线路巡检与YOLO目标检测学习者的电力金具检测数据集含10000张真实场景高质量图片经LabelImg标注后同时提供VOC(xml)、COCO(json)、YOLO(txt)三种标签格式分别存放可直接接入YOLO系列模型训练。压缩包共2000个文件以1985个xml标注文件为主并附有Python划分脚本和YOLO环境搭建、训练案例说明文档资源整体约819MB。配套脚本可自动划分训练集、验证集、测试集便于按实验需要重组数据教程覆盖Linux与Windows环境从环境安装到修改配置训练自己的数据集均有说明能有效降低上手门槛。已有210人学习下载数据场景丰富、标注框质量高既适合初学者系统完成YOLO检测实践也适用于输电线路电力金具识别课题的算法验证与模型迭代。1. 输电线路电力金具检测数据集训练前先想清楚的三件事拿到“YOLO输电线路电力金具检测数据集含10000张图片对应voc、coco和yolo三种格式标签划分脚本训练教程.rar”多数人第一反应是解压、装环境、跑训练。但我见过太多团队在这条链路上翻车YOLOv8跑完val mAP很好看换到真实巡检照片一测就露馅。问题主要不在模型而在数据处理——标签格式转错、划分脚本泄漏、类别清单没看清。这类数据集要解决的不是“把YOLO跑通”而是“让模型在航拍照片里可靠认出小尺寸、弱特征、背景杂乱的金具”。本文按“看数据→转格式→划分→训练→排错→验证”的顺序把链路拆开讲适合正在做电力巡检视觉方案的算法工程师、无人机巡检团队以及拿公开数据集练手的目标检测学习者。先把这三件事想清楚后面每一步才有据可依。2. 数据集里有什么10000张图的类别清单与VOC/COCO/YOLO三套标签怎么用2.1 电力金具不是一个类别先统计再训练电力金具是输电线路金属附件的统称常见的有悬垂线夹、耐张线夹、防振锤、均压环、间隔棒、重锤、并沟线夹、防鸟刺等。标题里只写了“电力金具检测”没有公布具体类别数所以解压后第一件事不是配环境而是打开标签文件统计类别分布。cat labels/train/*.txt labels/val/*.txt | awk {print $1} | sort | uniq -c | sort -nr这条命令把train和val下所有YOLO格式标签的第一列类别索引取出来统计每个索引的出现次数。输出类似“3456 0 / 2101 1 / 87 5”一眼就能看出哪类样本多、哪类少得离谱。类别索引本身没有意义还要与data.yaml里的names定义对照索引0对应names列表第0个类名索引5对应第5个。如果统计后发现某类只有几十个框先别急着训练。电力金具检测数据集的常见组织方式是以“缺陷检出优先”来定义类别把不同金具类型分别建模或者把同一金具的“正常/销钉缺失/破损/锈蚀”作为独立类别。类别定义不同模型输出就完全不同。比如防振锤的正常状态和销钉缺失在图像上差异极小模型要学的是细节差异而不是整体轮廓这对数据质量和增强策略的要求完全不同。这里有个判断原则如果目标是巡检消缺类别按“可执行动作”划分如果目标是部件识别类别按金具类型划分。训练前把类别定义和业务方对齐避免模型训完才发现业务上没法用。2.2 VOC/COCO/YOLO三套标签的格式差异这类数据集通常把同一份标注导出成三种格式对应三种生态。三套标签内容等价但组织方式和坐标定义都不同。训练时优先选YOLO格式因为ultralytics的YOLOv8和YOLOv5原版都直接读归一化TXT不需要训练阶段再做转换。三种格式的核心差异格式文件组织坐标定义类别索引VOCJPEGImagesAnnotations一图一XMLxmin/ymin/xmax/ymax 像素绝对值从1开始需查class-name映射COCO单个JSON含images/annotations/categories[x, y, width, height] 像素绝对值category_id可能不连续YOLOimageslabels目录一图一TXTcx, cy, w, h 归一化0-1从0开始与names顺序一致VOC的XML里包含图片尺寸和object列表适合人读COCO的JSON适合用pycocotools加载和做标准评估YOLO的TXT最简洁每行是“cls cx cy w h”。需要提醒的是三套格式互转不是简单单位换算最容易出错的点有三个——类别索引错位、XML的size和图片实际尺寸不一致、坐标越界。这三类问题在训练时都不会直接报错只会让模型默默学偏这也是为什么要专门写一章讲转换。2.3 训练前先做可视化检查把标注画到图上把标注画到图上逐张看能发现所有格式层面的“地雷”。这里给出一个可视化脚本import cv2 def draw_yolo_boxes(img_path, label_path, class_names, out_path): img cv2.imread(img_path) h, w img.shape[:2] with open(label_path) as f: for line in f: parts line.split() if len(parts) ! 5: continue cls int(parts[0]) cx, cy, bw, bh map(float, parts[1:]) 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, 255, 0), 2) cv2.putText(img, class_names[cls], (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 1) cv2.imwrite(out_path, img)这段代码读一张图和对应的TXT把归一化坐标换算回像素坐标画框。注意int(cls)这一步如果标签里混入了异常类别索引这里会直接越界报错能顺带发现脏数据。巡检原图的分辨率通常很高建议可视化时先把图片缩放到合适宽度否则框线和文字太小看不出偏移。检查时重点看三类问题框是否贴住目标、小目标框是否偏移半个身位、类别名称和框内物体是否匹配。有些数据集会把背景误标成金具这类脏标签在训练阶段会拉高cls_loss只能靠可视化发现。这一步做完再进训练流程后续排错会轻松很多。2.4 三格式数据集处理的通用思路红外和可见光都适用电力场景里除了可见光还有红外数据集很多也会整理成VOC/YOLO格式。这类数据的处理思路与可见光金具数据集完全一致先看清类别再确认格式再做可视化。红外图本质是单通道灰度信息但JPG存储格式仍是三通道RGB转换脚本不需要专门为红外改逻辑。我一般会在数据处理阶段加一个“原始图片质量检查”统计所有图片的分辨率、是否为彩色、是否带EXIF信息。金具检测对分辨率非常敏感如果数据集里混有大量长边只有640的小图和4K大图混在一起训练模型对目标尺度的适应性会变差。把图片规格列成一个CSV训练前扫一眼能避免很多“为什么这个杆塔上的金具检不出来”的疑问。3. VOC/COCO转YOLO与划分脚本坐标边界、类别映射和不泄漏的切分写法3.1 VOC XML转YOLO TXT解析、归一化和clip拿到VOC格式时需要自己写转换。核心逻辑是解析XML里的object节点把xmin/ymin/xmax/ymax换算成中心点加宽高的归一化值import xml.etree.ElementTree as ET def voc2yolo(xml_path, out_txt_path, class_name_to_id): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.findall(object): cls_name obj.find(name).text cls_id class_name_to_id[cls_name] box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h box_w (xmax - xmin) / w box_h (ymax - ymin) / h # 防止浮点误差导致坐标越界 x_center min(max(x_center, 0.0), 1.0) y_center min(max(y_center, 0.0), 1.0) box_w min(max(box_w, 0.0), 1.0) box_h min(max(box_h, 0.0), 1.0) lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines))这段代码里class_name_to_id是一个从XML类名字符串到YOLO类别索引的字典必须和最终训练data.yaml的names顺序一致。比如类别是“insulator, damper, clamp”字典应写成{insulator: 0, damper: 1, clamp: 2}。如果漏写一个类后面的索引全部错位训练后每个框的类别都是错的。框宽高的计算用了xmax-xmin再除以图片宽w。如果XML里出现xmin大于xmax的异常框box_w会是负值clip后变成0等于丢掉这个标注。处理方式是先做一次合法性判断再clip而不是直接丢弃——数据量少时每一个框都值得保留。批量转换时用shell遍历所有XMLmkdir -p labels for xml in Annotations/*.xml; do python voc2yolo.py $xml labels/$(basename $xml .xml).txt done转换后必须抽查随机挑十张图用第2章的可视化脚本画框确认位置、类别、数量都正确。这一步能省掉后续所有“模型怎么学不会”的排查时间。VOC转YOLO的坑集中在坐标换算和类别映射上可视化是唯一可靠的验收手段。3.2 COCO JSON转YOLOcategory_id不连续的处理COCO格式的JSON里categories数组的id经常不连续比如“3、7、11”。YOLO需要的是0、1、2连续索引转换时不能直接用category_id当cls要先建立映射表import json def coco2yolo(json_path, out_dir): with open(json_path) as f: coco json.load(f) # 建立 category_id 到连续索引的映射 id2idx {cat[id]: i for i, cat in enumerate(coco[categories])} img_map {img[id]: img for img in coco[images]} anns_by_img {} for ann in coco[annotations]: anns_by_img.setdefault(ann[image_id], []).append(ann) for img_id, anns in anns_by_img.items(): img img_map[img_id] w, h img[width], img[height] lines [] for ann in anns: x, y, bw, bh ann[bbox] # COCO的bbox是[x, y, width, height] cx (x bw / 2) / w cy (y bh / 2) / h lines.append(f{id2idx[ann[category_id]]} {cx:.6f} {cy:.6f} {bw/w:.6f} {bh/h:.6f}) out_name img[file_name].replace(.jpg, .txt) with open(f{out_dir}/{out_name}, w) as f: f.write(\n.join(lines))这段代码里最容易出错的是坐标换算。COCO的bbox给的是左上角坐标和宽高中心点公式是x bw/2不是VOC的(xminxmax)/2。强行用VOC的方式算框会整体偏移目标越小偏移越明显。另外如果COCO JSON里存在没有标注的图片anns_by_img里没有它的记录就不需要生成空的TXT。YOLO训练时会忽略没有标签的图片但data.yaml的train路径里最好别混入无标签图避免干扰验证。3.3 划分脚本类别均衡、组划分和三种输出形态划分脚本的目标是把图片和对应TXT同时按比例拆成train/val/test。第一个问题是类别均衡。如果随机划分样本少的类可能全部落进trainval里一个都见不到验证指标完全失真。下面这个脚本按类别分层抽样import os, random from collections import defaultdict def split_by_class(labels_dir, train_ratio0.8, val_ratio0.1, seed42): random.seed(seed) names [f[:-4] for f in os.listdir(labels_dir) if f.endswith(.txt)] class_to_files defaultdict(list) for name in names: path os.path.join(labels_dir, name .txt) with open(path) as f: classes set(line.split()[0] for line in f if line.strip()) for c in classes: class_to_files[c].append(name) train, val, test set(), set(), set() for c, files in class_to_files.items(): random.shuffle(files) n_train int(len(files) * train_ratio) n_val int(len(files) * val_ratio) train.update(files[:n_train]) val.update(files[n_train:n_train n_val]) test.update(files[n_train n_val:]) def write_list(items, path): with open(path, w) as f: f.write(\n.join(sorted(items))) write_list(train, train.txt) write_list(val, val.txt) write_list(test, test.txt)这段代码把每个类别都按同一比例拆到三段保证val里每个类都有样本。它输出的是清单文件每行一个图片名配合data.yaml使用。如果希望生成YOLO的目录结构把write_list换成shutil.copy把图片和标签分别复制到images/train、labels/train等目录即可。第二个问题是样本泄漏。同一基塔、同一杆塔的连续多张照片内容高度相似如果按单图随机划分相似图片会同时出现在train和valval mAP虚高模型换到真实新场景立刻掉点。常见做法是按“拍摄任务/杆塔ID”分组以组为单位切分。比如文件名是“tower_001_frame_012.jpg”取tower_001作为分组键先对group_id列表shuffle再把组内图片整体划入同一个集合。原则是同一场景的多张图只能出现在一个集合里。第三个问题是输出形态。YOLO训练可以吃三种目录组织一是images/train、images/val目录对应labels目录二是train.txt/val.txt清单data.yaml的path三是单目录内所有图片加一个txt声明哪些是train。第一、第二种最常用。如果用清单形式data.yaml里train指向train.txt即可。4. 用YOLOv8跑通金具检测训练预训练权重、损失曲线与必调参数4.1 data.yaml、预训练权重和第一条训练命令格式和划分都准备好后训练配置集中在data.yaml里path: /data/power_fittings train: images/train val: images/val test: images/test nc: 5 names: [insulator, damper, clamp, spacer, weight]path是数据集根目录train/val/test是相对path的路径也可以写成清单文件路径。nc是类别数names的顺序必须和YOLO标签里的类别索引完全一致这是配置里最容易翻车的两行错一个全部错位。然后跑训练yolo detect train \ datadata.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ patience15model指定yolov8s.pt第一次运行时ultralytics会自动下载预训练权重到缓存目录这就是常说的yolo预训练模型下载环节之后不会重复下载。选yolov8s而不是yolov8n是因为金具目标普遍偏小n模型的骨干网络太浅漏检明显s在速度和精度之间最均衡。显存允许的话跑完s再跑一版m对比mAP如果数据量够m的涨幅通常在0.02到0.05之间。4.2 航拍小目标场景的必调参数imgsz、增强和早停金具检测和常规目标检测最大的区别是目标尺寸占比小。一张4K航拍图里绝缘子可能只占几十个像素。默认imgsz640对整图缩放太狠小目标直接变成几个像素。参数调整优先级如下。第一优先是imgsz。先用640跑通流程确认无报错再开一轮imgsz960精调。960会让mAP明显上涨但显存占用和单轮时间都翻倍batch也要跟着减半。如果追求高召回率1280可以尝试但训练后半段要小心BN统计波动问题。第二是数据增强。YOLOv8默认开mosaic和mixup但mosaic把四张图拼在一起小目标被进一步缩小训练后期应关掉yolo detect train \ modelyolov8s.pt \ datadata.yaml \ imgsz960 \ epochs150 \ batch8 \ mosaic1.0 \ close_mosaic10 \ mixup0.2 \ copy_paste0.3close_mosaic10表示最后10轮关闭mosaic让模型回到正常尺度微调这一步对最终mAP的提升经常比多训20轮还明显。copy_paste会把样本框复制粘贴到其他图里对稀疏类别的增益很大适合金具这种类别不均衡的数据集。第三是epochs和早停。10000张图batch16时一个epoch约625次迭代yolov8s在单卡V100上imgsz640大约300到500毫秒一次迭代100轮约6到10小时。如果只有一张消费级显卡imgsz960时batch要降到8甚至4训练时间会明显拉长。显存不够时优先开AMP混合精度或者降imgsz而不是硬压batch。4.3 YOLO损失函数与训练曲线的解读YOLOv8用DFL加CIoU的组合回归分支输出坐标分布而不是直接回归坐标。训练日志里会打印box_loss、cls_loss、dfl_loss三个值。经验判断是box_loss和dfl_loss平缓下降cls_loss前期快速下降后进入平台期这都正常。如果cls_loss反复震荡优先怀疑类别不均衡而不是改损失函数。DFL对小目标边框回归更友好这也是YOLOv8系列在金具场景优于YOLOv5的原因之一。常见误解是训练完只盯着val mAP不看loss曲线。mAP是被压缩后的单点指标loss曲线能暴露震荡和发散两条都要看。5. 金具检测训练避坑记录五个让模型翻车的真实原因下面五个坑是金具数据集训练链路里最容易复现的都按“现象→原因→解决”展开覆盖格式转换、数据划分、类别平衡和训练稳定性。5.1 VOC转YOLO后框全部跑到左上角现象可视化时检测框全部贴在图片左上角或者框宽高比例完全不对训练完全学不进去。原因最常见的是归一化时宽高用反。VOC XML的 里有 和 转换时x方向坐标误用了height另一种是clip写在除以宽高之前把像素坐标先clip到0到1再除以800多得到一堆接近0的异常值。解决统一按“像素坐标算出中心点和宽高后再除以对应方向宽/高最后clip到0-1”的顺序。转换后随机挑十张图用可视化脚本画框确认框落在目标上再进训练。这类问题不会报错只会让模型一直学错特征。5.2 无人机JPG的EXIF旋转造成标注错位现象同一批图片一部分框准确一部分框整体转了90度或180度看起来像框跑到了画面另一个位置。原因无人机或手机拍的JPG带EXIF Orientation信息标注工具和训练框架的坐标系不一致。标注基于旋正后的图训练时图片被自动旋转纠正框就跟着错位。解决预处理阶段统一转正并去掉EXIFfrom PIL import Image, ImageOps img Image.open(src_path) img ImageOps.exif_transpose(img) img.save(dst_path, quality95)重新保存后三种格式标签都基于新图片重新生成再做划分和训练。这个坑的特征是“一半图对、一半图错”容易被误判成标注质量差实际是坐标系问题。5.3 划分泄漏val的mAP虚高换场景立刻掉点现象训练日志val mAP到了0.85把模型拿到另一组巡检照片上推理mAP只有0.6漏检严重。原因划分脚本按单张图片随机切分同一基塔的连续多张照片被同时拆进train和val验证集被污染。模型在验证集上见过的场景太多指标虚高真实场景的泛化能力完全没测出来。解决按拍摄任务分组划分。文件名的杆塔ID或拍摄批次作为group_id先shuffle group再把组内图片整体划入同一集合。判断是否泄漏的简单办法验证集里随机抽几张图看train里有没有同场景的相似图有就说明划分有问题。5.4 类别不均衡某类样本少cls_loss震荡现象cls_loss在训练后半段反复震荡val的各类别mAP中样本多的类很高样本少的类接近0。原因类别分布差异过大比如绝缘子占七成重锤只有几十张低频类特征学不出来。模型在每轮迭代里看到低频类的机会太少梯度信号被高频类淹没。解决优先在数据层面处理。一是按类重复采样每个epoch让低频类图片多出现几次二是给低频类加大copy_paste增强概率。如果还不行把低频类拆成独立二分类模型两步检测通常比硬训一个多类模型更可控。类别的mAP明细一定要逐行看平均值会掩盖这类问题。5.5 YOLO训练中BN崩溃loss突然变nan或猛涨现象前几十个epoch正常某一步loss突然变成nan或者val/loss猛涨但train/loss正常。原因小batch训练时BN统计失真。imgsz调到960后显存不够batch压到4甚至2BN在batch维度上估计均值方差就没有统计意义mosaic拼接出大面积空白区域也会加剧这个问题。解决用AMP混合精度训练省显存把batch拉回16以上显存还是不够就降低imgsz不要硬压batch。加cos_lrTrue让学习率按余弦曲线衰减降低后期震荡概率。BN出问题时训练日志里通常伴随warning不要忽略。如果loss已经变成nan只能从上一次保存的权重恢复重训没有后悔药。6. 训练完怎么看效果混淆矩阵、PR曲线与坏图排查习惯6.1 混淆矩阵和PR曲线先判断类别短板再调阈值训练结束后ultralytics会在runs/detect/train/下生成confusion_matrix.png、PR_curve.png、F1_curve.png等图表。只盯着val mAP就把模型拿去上线是做电力巡检最容易吃的亏因为mAP是平均值掩盖了类别层面的差异。第一步看混淆矩阵。YOLO生成的混淆矩阵通常按行归一化每行代表真实类别列代表预测类别。有些版本里矩阵每列总和明显不等于1这是正常的因为背景预测和漏检也被计入总和不为1不代表出错。关键看对角线亮不亮以及低频类是否大面积落到背景列。比如“重锤”这一行几乎全在背景列说明模型对它基本没有检出能力应返回去补数据或调阈值。第二步看PR曲线拐点确定置信度阈值。金具场景下漏检一个缺陷比多报一个正常件严重得多。默认conf0.25如果导致召回不够把阈值降到0.15试试recall会上升误检也会增加。阈值具体定多少用一批没参与训练的真实巡检图来测不能只看验证集。6.2 困难样本目录批量预测上线前的一个习惯第三步是批量预测困难样本yolo predict modelruns/detect/train/weights/best.pt \ sourcehard_cases/ \ conf0.15 \ save_txtTrue \ save_confTruesource指向一个人工收集的困难样本目录预测后把TXT叠加到图上逐张看漏检和误检的类型。我自己每训完一个版本先看50张测试图、整理10个典型漏检案例再决定是否调整阈值或补充数据。只看mAP就上线是我在金具检测项目上吃过最大的亏。这个习惯救过我几次希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →