简介这份输电线路金具数据集面向电力行业机器视觉研究者、算法工程师及高校相关专业学生用于训练和验证金具检测与分类模型解决输电线路运维中人工巡检效率低、危险性高的问题。压缩包内共2000个文件全部为xml格式的标注文件整体约497.28MB每份xml对应一张金具图像中目标的位置与类别信息覆盖绝缘子、螺栓销钉、防振锤、耐张线夹等典型部件。数据采集时以蓝色垫子为统一背景并从多个角度拍摄有效降低环境干扰、提升目标辨识度为算法训练提供稳定输入。目前已有342人学习下载适合作为目标检测、图像分类等任务的实验素材。使用者可基于标注文件构建分类模型区分金具类型或开发定位算法精确框出金具位置也可用于远程监控与状态评估等场景为电力系统智能化运维提供数据支撑。1. 输电线路金具数据集-zip从一堆航拍图到可训练标注的完整路径拿到「输电线路金具数据集-zip」这个标题的人多半正卡在同一个地方手头有一批无人机巡检拍回来的绝缘子、防振锤、线夹、均压环照片想训一个金具缺陷检测模型却不知道标注该怎么组织、类别该怎么定、zip 解压之后那堆文件夹到底怎么喂给 YOLO 或 MMDetection。这个数据集方向解决的不是「有没有数据」而是「数据能不能直接进训练管线」。它适合两类人一类是做电力巡检算法、需要快速搭起 baseline 的工程师另一类是接手了别人标注成果、要判断这批金具标注值不值得投入训练的学生和初级算法岗。金具本身目标小、背景杂、遮挡多数据集的组织方式直接决定后面模型是能收敛还是全程玄学。这一章先把「金具数据集到底长什么样、为什么值得单独做」讲清楚后面几章再落到解压、清洗、转换、训练和排错。2. 金具数据集的类别体系与标注格式选型2.1 金具类别怎么定才不会被返工输电线路金具的种类比很多人想的多常见的有悬垂线夹、耐张线夹、防振锤、间隔棒、均压环、重锤片、接续金具、联板等。数据集里如果一开始就把类别定得太细比如把「防振锤」拆成「音叉式防振锤」「扭绞式防振锤」「预绞式防振锤」标注成本会翻倍而且不同电压等级、不同厂家的金具外形差异大标注员很容易标错。我一般建议第一版数据集按「功能 外形」粗分控制在 8 到 12 类把容易混的合并比如所有线夹先归到「线夹」大类等模型能稳定检出后再做子类拆分。另一个坑是缺陷类别和金具类别混在一起。有些数据集把「金具」和「金具锈蚀」「金具破损」放在同一层级这会让检测头很困惑一个防振锤既属于「防振锤」又属于「锈蚀」多标签还是单标签常见做法是分两套标签体系一套做金具定位一套做缺陷分类或者用「金具_缺陷」的复合类别但复合类别数量会爆炸。我的血泪经验是第一版只做金具定位缺陷交给后续分类模型这样标注一致性和训练稳定性都好很多。2.2 VOC、COCO、YOLO 三种格式的取舍金具数据集 zip 解压后标注格式常见三种Pascal VOC 的 XML、COCO 的 JSON、YOLO 的 txt。选哪种取决于你后面用什么框架。如果打算用 MMDetection 或 Detectron2COCO JSON 最省事如果直接用 Ultralytics 的 YOLO 系列YOLO txt 最直接如果数据集原始标注是 LabelImg 出的 XML那大概率是 VOC 格式需要转换。下面是一个把 VOC XML 转成 YOLO txt 的脚本处理金具数据集时经常用到import os import xml.etree.ElementTree as ET # 类别映射必须和 data.yaml 里的 names 顺序一致 CLASS_MAP { insulator: 0, vibration_damper: 1, clamp: 2, grading_ring: 3, spacer: 4, } def voc_to_yolo(xml_path, img_w, img_h, out_txt_path): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in CLASS_MAP: continue # 跳过未定义类别避免训练时报 index 越界 cls_id CLASS_MAP[name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # YOLO 格式要求归一化到 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 # 裁剪到 [0,1]防止标注越界导致训练异常 x_center min(max(x_center, 0.0), 1.0) y_center min(max(y_center, 0.0), 1.0) w min(max(w, 0.0), 1.0) h min(max(h, 0.0), 1.0) lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_txt_path, w, encodingutf-8) as f: f.write(\n.join(lines)) # 批量处理图片尺寸从 PIL 读取避免 XML 里尺寸字段缺失 from PIL import Image def batch_convert(xml_dir, img_dir, out_dir): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue stem os.path.splitext(xml_file)[0] img_path os.path.join(img_dir, stem .jpg) if not os.path.exists(img_path): print(fmissing image: {stem}) continue with Image.open(img_path) as im: img_w, img_h im.size voc_to_yolo( os.path.join(xml_dir, xml_file), img_w, img_h, os.path.join(out_dir, stem .txt) )这段脚本的关键点有三个。第一CLASS_MAP必须和训练配置里的类别顺序完全一致否则模型学到的类别会整体错位这种错误在验证集上表现为「所有框都偏到另一个类」很难排查。第二归一化前一定要用真实图片尺寸不能信 XML 里的size字段很多金具数据集在裁剪或缩放后没有同步更新 XML 尺寸直接用会得到一堆越界框。第三越界裁剪是必要的金具标注里经常出现框超出图像边界的情况不裁剪会让 YOLO 训练时 loss 直接 NaN。2.3 数据集划分别让同一基杆塔的图同时进训练和验证金具数据集有一个很隐蔽的泄漏同一基杆塔、同一拍摄架次的多张图如果随机划分训练集和验证集会包含几乎相同的背景和光照验证指标虚高。正确做法是按杆塔 ID 或拍摄架次分组划分确保验证集里的杆塔在训练集中没出现过。如果 zip 里没有杆塔 ID 字段至少按文件名前缀或拍摄日期分组。常见比例是训练 7、验证 2、测试 1金具这种小目标场景验证集不能太小否则 mAP 波动大到没法判断模型好坏。3. 从 zip 解压到可训练目录目录结构与清洗步骤3.1 解压后先别急着训练先做完整性检查金具数据集 zip 解压后最常见的目录结构是images/和annotations/两个文件夹或者按类别分文件夹。不管哪种第一步都是检查图片和标注是否一一对应。缺失标注的图片如果直接进训练YOLO 会把它当负样本导致模型对金具的响应被压制。下面这段检查脚本我几乎每个数据集都会跑一遍import os def check_pairs(img_dir, label_dir, img_ext.jpg, label_ext.txt): imgs {os.path.splitext(f)[0] for f in os.listdir(img_dir) if f.endswith(img_ext)} labels {os.path.splitext(f)[0] for f in os.listdir(label_dir) if f.endswith(label_ext)} only_img imgs - labels only_label labels - imgs print(fimages: {len(imgs)}, labels: {len(labels)}) print(fimage without label: {len(only_img)}) print(flabel without image: {len(only_label)}) # 输出前 20 个方便人工核查 for name in list(only_img)[:20]: print( missing label:, name) for name in list(only_label)[:20]: print( missing image:, name) check_pairs(dataset/images, dataset/labels)参数说明img_ext和label_ext按实际格式改有些数据集图片是.png或.JPG大小写敏感在 Linux 上会直接导致漏检。only_img里的图片要么补标注要么移到background/目录当负样本不能留在训练集里当无标注正样本。only_label里的标注直接删掉没有对应图片的标注文件会让训练脚本报错。3.2 金具小目标的清洗剔除无效框和极端尺寸金具在航拍图里往往只占几十个像素标注质量参差不齐。清洗时要重点处理三类框宽或高小于 4 像素的框、宽高比超过 10:1 的框、以及面积占整图超过 80% 的框。前两类多半是标注员手抖或把一条线当成了金具第三类通常是把整张图框成了「线路」。这些框不清理训练时 anchor 匹配会非常混乱。import os def clean_labels(label_dir, min_size4, max_ratio10.0, max_area_ratio0.8): removed 0 for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue path os.path.join(label_dir, fname) kept [] with open(path, r, encodingutf-8) as f: for line in f: parts line.strip().split() if len(parts) ! 5: removed 1 continue cls_id, x, y, w, h parts x, y, w, h map(float, (x, y, w, h)) # 还原到像素尺度做判断这里假设输入图约 1920x1080 pw, ph w * 1920, h * 1080 if pw min_size or ph min_size: removed 1 continue ratio max(pw / max(ph, 1e-6), ph / max(pw, 1e-6)) if ratio max_ratio: removed 1 continue if w * h max_area_ratio: removed 1 continue kept.append(f{cls_id} {x:.6f} {y:.6f} {w:.6f} {h:.6f}) with open(path, w, encodingutf-8) as f: f.write(\n.join(kept)) print(fremoved {removed} invalid boxes) clean_labels(dataset/labels)这里的min_size、max_ratio、max_area_ratio要根据你的图像分辨率调整。如果图片是 4K 的min_size可以放到 8如果是 640 裁剪图4 已经偏大。清洗完一定要重新跑一遍 3.1 的配对检查因为有些标注文件被清空后变成空文件YOLO 会把空 txt 当负样本这本身没问题但你要知道哪些图变成了负样本。3.3 生成 data.yaml 和目录软链接YOLO 训练需要标准的images/train、images/val、labels/train、labels/val结构。如果原始数据已经分好直接写data.yaml如果没分用软链接避免复制大文件# 假设原始结构是 dataset/images 和 dataset/labels mkdir -p yolo_dataset/images/train yolo_dataset/images/val mkdir -p yolo_dataset/labels/train yolo_dataset/labels/val # 按 8:2 划分这里用文件名列表控制实际按杆塔分组更稳 ls dataset/images | head -n 800 | while read f; do ln -s $(pwd)/dataset/images/$f yolo_dataset/images/train/$f ln -s $(pwd)/dataset/labels/${f%.jpg}.txt yolo_dataset/labels/train/${f%.jpg}.txt done ls dataset/images | tail -n 200 | while read f; do ln -s $(pwd)/dataset/images/$f yolo_dataset/images/val/$f ln -s $(pwd)/dataset/labels/${f%.jpg}.txt yolo_dataset/labels/val/${f%.jpg}.txt done对应的data.yamlpath: /abs/path/to/yolo_dataset train: images/train val: images/val nc: 5 names: - insulator - vibration_damper - clamp - grading_ring - spacerpath必须是绝对路径YOLO 对相对路径的处理在不同版本里不一致用绝对路径最稳。nc和names的顺序必须和转换脚本里的CLASS_MAP完全一致这是金具数据集训练翻车最常见的原因之一。4. 用 YOLOv8 在金具数据集上跑通第一个 baseline4.1 环境与训练命令金具检测属于小目标密集场景YOLOv8 的m或l版本比较合适n版本在防振锤这种小目标上召回率会明显偏低。环境用 PyTorch Ultralytics 即可训练命令yolo detect train \ data/abs/path/to/data.yaml \ modelyolov8m.pt \ epochs150 \ imgsz1280 \ batch8 \ device0 \ workers4 \ patience30 \ projectruns/jinju \ namebaseline参数说明imgsz1280是关键金具目标小640 下很多防振锤只剩几个像素mAP 会低得没法看1280 显存不够就降到 1024但不要再低。batch8是 1280 下 24G 显存的保守值显存够可以上 16。patience30表示 30 轮没提升就早停金具数据集容易过拟合早停能省时间。workers在 Windows 上设 0 或 2设大了容易卡死。4.2 训练中要盯的三个指标第一个是cls_loss如果它一直不降大概率是类别映射错了或标注里有大量错类。第二个是box_loss金具小目标的 box_loss 通常比常规 COCO 任务高但如果在 50 轮后还在 1.5 以上检查 anchor 和 imgsz。第三个是验证集的mAP50-95金具场景 mAP50 能到 0.6 以上就算可用mAP50-95 通常只有 0.3 到 0.4不要拿 COCO 的标准来要求。4.3 推理和可视化验证训练完先用yolo detect predict在验证集上跑一遍把预测框和原图叠出来看yolo detect predict \ modelruns/jinju/baseline/weights/best.pt \ source/abs/path/to/yolo_dataset/images/val \ imgsz1280 \ conf0.25 \ saveTrue \ projectruns/jinju \ nameval_predconf0.25是金具检测的常用起点漏检多就降到 0.15误检多就升到 0.4。重点看两类错误把间隔棒和防振锤混检以及把背景里的螺栓、塔材误检成金具。前者靠增加这两类的区分性样本后者靠加负样本。5. 金具数据集训练避坑5 个真实踩坑记录5.1 现象训练 loss 正常但 mAP 一直是 0原因data.yaml里的names顺序和标注文件里的类别 ID 不一致模型学到的类别和验证时的类别对不上。解决用脚本统计标注文件里出现的所有类别 ID和names逐一对齐确保没有 ID 超出nc范围。5.2 现象验证集 mAP 很高实际巡检图上几乎检不出金具原因数据集划分时同一杆塔的图同时进了训练和验证验证集本质是「见过的背景」。解决按杆塔 ID 或拍摄架次分组划分验证集杆塔不出现在训练集。如果 zip 里没有杆塔信息至少按文件名前缀分组。5.3 现象训练到一半 loss 突然变 NaN原因标注里有越界框或宽高为 0 的框归一化后出现非法值。解决跑 3.2 的清洗脚本重点检查w或h为 0 的行以及x_center加减w/2超出 [0,1] 的框。5.4 现象小目标金具召回率极低大金具正常原因imgsz太小或 anchor 不匹配。解决把imgsz提到 1280YOLOv8 会自动调整 anchor但如果还不行检查是不是把imgsz设成了 640 却在data.yaml里写了 1280 的路径混淆。另外确认没有在预处理里把图缩放到 640 再送进模型。5.5 现象模型把整张图检成一个金具框原因标注里存在面积占比超过 80% 的框通常是标注员把整张图框成了「线路」。解决跑 3.2 的清洗把max_area_ratio设到 0.5 甚至更低金具不可能占半张图。6. 进阶用切片推理和类别平衡把金具召回再提一截金具检测的难点在小目标和长尾类别。如果 baseline 已经跑通下一步可以试两个技巧。第一个是 SAHI 切片推理把 1280 的图切成 640 的块分别推理再合并对小目标召回提升明显代价是推理时间翻倍。用法很简单from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathruns/jinju/baseline/weights/best.pt, confidence_threshold0.25, devicecuda:0, ) result get_sliced_prediction( test.jpg, model, slice_height640, slice_width640, overlap_height_ratio0.2, overlap_width_ratio0.2, ) result.export_visuals(export_dirsahi_pred)overlap设 0.2 是为了避免金具正好落在切片边界被切断设太小会漏设太大推理变慢。第二个技巧是类别平衡采样金具数据集里绝缘子数量往往是均压环的十几倍训练时对稀有类别过采样或者用copy_paste增强把稀有金具贴到不同背景上。我一般会先统计每个类别的框数量低于 500 的类别就要考虑增强。验证改进是否有效不能只看整体 mAP要按类别看 AP。如果整体 mAP 涨了但稀有类别 AP 没动说明涨的是头部类别实际巡检里该漏的还是漏。我自己的习惯是每次改完只认稀有类别的 AP整体指标当参考。金具数据集这个方向值得做但前提是标注体系和划分方式从一开始就立住否则后面调参全是白费功夫。希望帮到你。本文还有配套的精品资源点击获取