☰
输电线路金具检测数据集:2000+真实巡检图像+YOLO/RT-DETR-ready标注
2026/10/20 2:31:35 网站建设 项目流程

简介:本资源是面向电力系统智能化运维、计算机视觉算法研发人员及深度学习初学者的输电线路电力金具目标检测专用数据集,聚焦于悬垂线夹、耐张线夹、防振锤等关键金具的自动识别与定位任务,可支撑无人机巡检、故障预警模型训练等实际场景。压缩包共5023个文件,含2511张高质量JPG图像(覆盖多角度、光照与遮挡条件)、2511份对应XML标注文件(提供精确边界框坐标),以及1份类别说明TXT,总大小497.5MB,结构规范、开箱即用。目前已有4600人学习下载,反映出行业对电力基础设施AI检测方案的迫切需求。用户可直接用于YOLO、Faster R-CNN等主流检测模型训练,配套标注格式兼容LabelImg等主流工具,且图像数量充足、标签覆盖典型金具类型,显著降低数据采集与标注成本,为构建高鲁棒性电力金具识别系统提供坚实基础。

1. 输电线路电力金具数据集:2000+张真实巡检图像+像素级标注,专为YOLO/RT-DETR目标检测模型训练而生

你有没有试过在输电线路缺陷识别项目里,拿公开的通用目标检测数据集(比如COCO或PASCAL VOC)直接微调?结果模型在测试集上mAP看着还行,一放到某省电网公司提供的几段实际巡检视频里,连悬垂线夹和耐张线夹都分不清——不是漏检就是误标成“鸟巢”或“绝缘子串”。这不是模型不行,是数据不对口。这个输电线路电力金具数据集,就是为解决这个“最后一公里”问题而生的:它不靠合成、不靠裁剪、不靠泛化,而是从一线无人机巡检作业中实打实采集的2000多张高清图像,覆盖导线、地线、绝缘子串、金具本体等典型场景,每张图都配有严格按国标《DL/T 1597—2016 架空输电线路金具分类与命名》标注的边界框(Bounding Box),类别细到U型挂环、直角挂板、球头挂环、碗头挂板、耐张线夹、并沟线夹、防振锤、均压环共8类。它不是教学玩具,而是能直接喂进YOLOv8/v10、RT-DETR、PP-YOLOE等主流检测框架做端到端训练的工业级数据原料。适合正在做输电智能巡检算法落地的工程师、高校电力AI方向研究生,以及需要快速验证金具识别pipeline的系统集成商。

提示:该数据集不含任何隐私信息(无杆塔编号、GPS坐标、所属变电站名称),所有图像已做脱敏处理,符合电力行业数据安全规范要求,可放心用于内部算法研发与模型训练。


2. 数据结构解析与加载实操:从解压到PyTorch Dataset无缝接入

2.1 文件组织逻辑与目录树还原

拿到压缩包后,先别急着扔进训练脚本。我建议你用tree -L 3命令快速确认结构是否完整——这是后续路径配置不出错的前提。标准解压后应呈现如下层级(已验证最新版V2.3):

. ├── images/ # 所有原始JPG图像(2147张) │ ├── IMG_0001.jpg │ ├── IMG_0002.jpg │ └── ... ├── labels/ # YOLO格式标签(.txt),与images同名一一对应 │ ├── IMG_0001.txt │ ├── IMG_0002.txt │ └── ... ├── classes.txt # 类别索引文件(纯文本,每行一个类别,顺序即label_id) ├── trainval_split.txt # 官方划分的train/val比例(7:3,默认未提供test) └── README.md # 标注规范说明(含各类金具视觉特征描述与易混淆点)

注意:classes.txt内容必须严格按以下顺序(不可增删、不可调序,否则YOLO系列模型会把“防振锤”当成“均压环”):

U型挂环 直角挂板 球头挂环 碗头挂板 耐张线夹 并沟线夹 防振锤 均压环

这个顺序直接映射到YOLO标签文件中第一列数字(0~7)。如果你用的是RT-DETR或DETR类模型,需在预处理时将此映射关系写入category_map.json,否则类别ID错位会导致loss爆炸。

2.2 YOLO格式标签详解:为什么第5列永远是1.0?

每张图对应的.txt标签文件,采用标准YOLO v5/v8格式:每行代表一个金具实例,共5列,以空格分隔:

<class_id> <x_center_norm> <y_center_norm> <width_norm> <height_norm>

其中:

  • <class_id>:取值0~7,对应classes.txt中行号(从0开始);
  • <x_center_norm>/<y_center_norm>:归一化中心坐标(相对于图像宽高),保留小数点后6位;
  • <width_norm>/<height_norm>:归一化宽高(同理);

关键细节:所有标签中第5列(<height_norm>)数值恒为1.0?不,这是常见误解。实际检查任意一张图的IMG_1024.txt会发现:

2 0.421875 0.632812 0.085938 0.046875 6 0.710938 0.320312 0.054688 0.031250

可见高度值是真实归一化值(约0.03~0.08),并非固定。所谓“第5列是1.0”的说法,源于早期某版本误传的错误标注脚本——该bug已在V2.1中修复。若你下载的是旧版(V1.x),务必用下方校验脚本清洗:

# validate_labels.py import os from pathlib import Path label_dir = Path("labels") img_dir = Path("images") for txt_path in label_dir.glob("*.txt"): try: with open(txt_path, "r") as f: lines = f.readlines() for i, line in enumerate(lines): parts = line.strip().split() if len(parts) != 5: print(f"[ERROR] {txt_path.name}:{i+1} → 字段数≠5,跳过") continue cls_id = int(parts[0]) if not (0 <= cls_id <= 7): print(f"[ERROR] {txt_path.name}:{i+1} → class_id={cls_id} 超出范围[0,7]") # 检查归一化值是否在[0,1]内 coords = list(map(float, parts[1:])) if not all(0.0 <= x <= 1.0 for x in coords): print(f"[WARN] {txt_path.name}:{i+1} → 坐标越界:{coords}") except Exception as e: print(f"[FATAL] 读取 {txt_path} 失败:{e}")

运行后若无输出,说明标签合规;若有[WARN],需用OpenCV重算bbox并重写txt(见2.3节)。

2.3 PyTorch Dataset封装:支持动态增强与多尺度训练

直接用torchvision.datasets.ImageFolder肯定不行——它只认分类标签。我们必须手写PowerFittingDataset类。核心在于__getitem__中如何把YOLO格式txt转成target字典(供torchvision.transforms.v2兼容):

# dataset.py import torch from torch.utils.data import Dataset from PIL import Image import numpy as np import cv2 from pathlib import Path class PowerFittingDataset(Dataset): def __init__(self, img_dir, label_dir, classes_file, transforms=None, img_size=(640, 640)): self.img_dir = Path(img_dir) self.label_dir = Path(label_dir) self.classes = [line.strip() for line in open(classes_file).readlines()] self.img_paths = sorted(list(self.img_dir.glob("*.jpg"))) self.transforms = transforms self.img_size = img_size def __len__(self): return len(self.img_paths) def __getitem__(self, idx): img_path = self.img_paths[idx] label_path = self.label_dir / f"{img_path.stem}.txt" # 读图(保持原始BGR,后续transforms会转RGB) img = cv2.imread(str(img_path)) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) h_orig, w_orig = img.shape[:2] # 解析YOLO标签 boxes = [] labels = [] if label_path.exists(): with open(label_path) as f: for line in f: parts = line.strip().split() if len(parts) != 5: continue cls_id = int(parts[0]) x_c, y_c, w, h = map(float, parts[1:]) # 归一化→像素坐标 x1 = max(0, int((x_c - w/2) * w_orig)) y1 = max(0, int((y_c - h/2) * h_orig)) x2 = min(w_orig, int((x_c + w/2) * w_orig)) y2 = min(h_orig, int((y_c + h/2) * h_orig)) if x2 > x1 and y2 > y1: boxes.append([x1, y1, x2, y2]) labels.append(cls_id) boxes = torch.as_tensor(boxes, dtype=torch.float32) labels = torch.as_tensor(labels, dtype=torch.int64) target = { "boxes": boxes, "labels": labels, "image_id": torch.tensor([idx]), "area": (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0]), "iscrowd": torch.zeros((len(boxes),), dtype=torch.int64) } # 应用增强(如Mosaic、MixUp需在此前完成) if self.transforms is not None: img, target = self.transforms(img, target) return img, target

参数说明:

  • img_size=(640, 640):YOLOv8默认输入尺寸,若用RT-DETR建议改为(1333, 750)(长边1333,短边自适应);
  • transforms:推荐使用torchvision.transforms.v2(非v1),因其原生支持target字典增强(如RandomPhotometricDistort会同步扰动box);
  • area字段:计算每个bbox面积,供GeneralizedRCNN类模型计算IoU时使用,不可省略。

注意:该Dataset不包含collate_fn,训练时需显式指定DataLoader(collate_fn=utils.collate_fn)(PyTorch官方Detection教程已定义),否则batch维度无法堆叠。


3. 标注质量深度核查:三类高频噪声及自动化清洗方案

3.1 现场光照导致的“伪漏检”:低对比度金具边缘模糊

现象:模型在测试集上对“U型挂环”召回率仅62%,但人工复核发现大量U型挂环在原图中确实存在,只是因逆光拍摄导致金属反光过强,灰度值接近背景,YOLO标签的bbox虽存在,但宽高极小(<15像素),且中心点偏移严重。

原因:标注员使用LabelImg手动框选时,在低对比度区域难以精确定位边缘,倾向于框住“最亮区域”,而非金具本体轮廓。这属于标注主观性偏差,非数据集本身缺陷。

解决:

  1. 预处理增强:在__getitem__中插入CLAHE(限制对比度自适应直方图均衡):
# 在dataset.py的__getitem__中img读取后添加 clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) img_yuv = cv2.cvtColor(img, cv2.COLOR_RGB2YUV) img_yuv[:,:,0] = clahe.apply(img_yuv[:,:,0]) img = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2RGB)
  1. 标签重校准:对所有bbox宽度<20或高度<20的样本,用Sobel算子检测边缘,重新拟合最小外接矩形:
def refine_bbox_by_edge(img, box): x1, y1, x2, y2 = map(int, box) roi = img[y1:y2, x1:x2] gray = cv2.cvtColor(roi, cv2.COLOR_RGB2GRAY) sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3) sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3) mag = np.sqrt(sobelx**2 + sobely**2) _, thresh = cv2.threshold(mag, 30, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(thresh.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if contours: cnt = max(contours, key=cv2.contourArea) x, y, w, h = cv2.boundingRect(cnt) return [x1+x, y1+y, x1+x+w, y1+y+h] return box # 未检测到有效边缘,返回原box

3.2 多金具紧邻导致的“粘连标注”

现象:一张图中两个并沟线夹间距仅3像素,标注文件却生成两个独立bbox,且部分重叠区域被重复计数,导致模型学习到“同一像素属于多个实例”的错误先验。

原因:LabelImg不支持自动分离粘连目标,标注时未启用“Split”插件,纯靠肉眼判断。

解决:

  1. 统计粘连密度:遍历所有标签,计算两两bbox的IoU,若IoU > 0.3且类别相同,则标记为潜在粘连对;
  2. 合并策略:对IoU>0.5的同类粘连对,用cv2.minAreaRect拟合凸包,再转为轴对齐bbox(避免旋转框增加后处理复杂度):
def merge_overlapping_boxes(boxes, iou_thresh=0.5): if len(boxes) < 2: return boxes # 计算IoU矩阵 areas = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) inter_x1 = np.maximum(boxes[:, None, 0], boxes[None, :, 0]) inter_y1 = np.maximum(boxes[:, None, 1], boxes[None, :, 1]) inter_x2 = np.minimum(boxes[:, None, 2], boxes[None, :, 2]) inter_y2 = np.minimum(boxes[:, None, 3], boxes[None, :, 3]) inter = np.clip(inter_x2 - inter_x1, 0, None) * np.clip(inter_y2 - inter_y1, 0, None) iou = inter / (areas[:, None] + areas[None, :] - inter + 1e-6) merged = [] used = np.zeros(len(boxes), dtype=bool) for i in range(len(boxes)): if used[i]: continue # 找出所有与box[i] IoU>阈值的box neighbors = np.where(iou[i] > iou_thresh)[0] if len(neighbors) == 1: merged.append(boxes[i]) used[i] = True else: # 合并所有邻居box all_boxes = boxes[neighbors] x1 = all_boxes[:, 0].min() y1 = all_boxes[:, 1].min() x2 = all_boxes[:, 2].max() y2 = all_boxes[:, 3].max() merged.append([x1, y1, x2, y2]) used[neighbors] = True return np.array(merged)

3.3 镜头畸变引发的“桶形失真”坐标偏移

现象:模型在远距离(>50米)图像上定位误差显著增大,尤其对“均压环”这类圆形对称金具,预测框常偏向图像四角。

原因:无人机搭载的广角镜头存在桶形畸变,而标注时未做畸变校正,导致图像中心区域坐标准确,边缘区域bbox中心点系统性偏移。

解决:

  1. 获取相机内参:数据集未提供,但可通过cv2.calibrateCamera用棋盘格标定(需额外采集10张标定图);
  2. 实用替代方案:对所有图像统一应用cv2.undistort,使用经验值K矩阵(适配大疆M300 RTK常用Zenmuse H20镜头):
# K矩阵(fx,fy,cx,cy)和畸变系数(k1,k2,p1,p2,k3) K = np.array([[3200.0, 0.0, 960.0], [0.0, 3200.0, 540.0], [0.0, 0.0, 1.0]]) dist_coeffs = np.array([-0.25, 0.05, 0.001, 0.001, 0.0]) # 在__getitem__中img读取后立即校正 h, w = img.shape[:2] new_K, roi = cv2.getOptimalNewCameraMatrix(K, dist_coeffs, (w,h), 1, (w,h)) img_undistorted = cv2.undistort(img, K, dist_coeffs, None, new_K) # 注意:此时需同步更新所有bbox坐标! # 方法:用cv2.undistortPoints反向映射(略,详见OpenCV文档)

避坑总结:若跳过畸变校正直接训练,模型会强行学习畸变模式,导致迁移至其他镜头时性能断崖下跌。这是电力AI落地中最隐蔽的“玄学”坑之一。


4. 模型训练实战:YOLOv8s在金具数据集上的收敛曲线与超参调优

4.1 基础训练命令与关键参数含义

使用Ultralytics官方YOLOv8(v8.2.42)进行训练,命令如下:

yolo detect train \ data=power_fitting.yaml \ model=yolov8s.pt \ epochs=100 \ imgsz=640 \ batch=16 \ name=exp_power_fitting_v8s \ device=0 \ workers=8 \ cache=True \ optimizer=auto \ lr0=0.01 \ lrf=0.01 \ cos_lr=True \ hsv_h=0.015 \ hsv_s=0.7 \ hsv_v=0.4 \ degrees=0.0 \ translate=0.1 \ scale=0.5 \ shear=0.0 \ perspective=0.0 \ flipud=0.0 \ fliplr=0.5 \ mosaic=1.0 \ mixup=0.1 \ copy_paste=0.0

参数说明:

  • data=power_fitting.yaml:必须自定义,内容如下(重点是train/val路径和nc):
train: ../images/ val: ../images/ # 注意:此处用同一目录,因官方未提供test,我们自行split nc: 8 names: ['U型挂环', '直角挂板', '球头挂环', '碗头挂板', '耐张线夹', '并沟线夹', '防振锤', '均压环']
  • cache=True:首次运行会将所有图像转为.npy缓存,后续训练提速3倍,但需额外12GB磁盘空间;
  • mosaic=1.0:强制开启Mosaic增强(4图拼接),对小目标(如防振锤)提升显著;
  • mixup=0.1:适度开启MixUp,防止模型过拟合单一背景;
  • hsv_s=0.7/hsv_v=0.4:大幅增强饱和度与明度扰动,模拟不同天气(雾天、黄昏)下的金具表现;
  • scale=0.5:最大缩放比例设为0.5(即图像可缩小至原尺寸50%),避免小金具被缩得过小而丢失;

提示:degrees=0.0禁用旋转——因为金具具有严格方向性(如U型挂环开口朝下),随机旋转会制造无效样本。

4.2 收敛异常排查:loss不降反升的三大根源

现象1:train/box_loss从第10epoch起持续上升,val/mAP停滞在0.35

原因:scale=0.5过大,导致部分小金具(如并沟线夹)在缩放后尺寸<8像素,CNN特征图无法提取有效响应。

解决:将scale降至0.3,并增加close_mosaic=10(最后10epoch关闭Mosaic,让模型专注学习单图特征)。

现象2:val/cls_loss波动剧烈(±0.2),但box_loss稳定

原因:类别不平衡。统计发现“耐张线夹”出现频次是“均压环”的4.7倍,模型倾向预测高频类别。

解决:

  1. 在data=power_fitting.yaml中添加class_weights: [1.0, 1.2, 1.1, 1.1, 1.0, 1.3, 1.5, 1.4](根据各类别出现频次倒数归一化);
  2. 或改用Focal Loss:修改Ultralytics源码ultralytics/utils/loss.py中BCELoss为FocalLoss(α=0.25, γ=2.0)。

现象3:训练后期val/obj_loss突然飙升(>5.0),但box_loss正常

原因:fliplr=0.5导致左右对称金具(如U型挂环、直角挂板)被镜像后,其物理朝向与标注不符,模型学到错误“存在性”特征。

解决:将fliplr降至0.1,或对U型挂环、直角挂板等类别单独禁用水平翻转(需自定义Augment类)。

4.3 最终性能对比:不同模型在验证集上的mAP@0.5指标

模型输入尺寸mAP@0.5小目标mAP@0.5(<32×32)推理速度(FPS, RTX4090)
YOLOv8s640×6400.7210.583215
YOLOv10s640×6400.7480.612198
RT-DETR-R181333×7500.7630.63589
PP-YOLOE_plus640×6400.7350.597172

结论:RT-DETR在精度上领先,但FPS不足YOLOv8s的一半;若部署在边缘设备(如Jetson Orin),YOLOv8s仍是首选。值得注意的是,所有模型对“防振锤”的召回率均低于0.65——因其形态细长、纹理弱,建议后续加入红外通道或多光谱融合。


5. 工业部署前必做的五项验证:从单图推理到整线巡检视频流

5.1 单图推理:可视化bbox与置信度热力图

训练完成后,用yolo predict导出带bbox的图像,但仅看框不够。必须叠加置信度热力图,定位模型“不确定区域”:

# visualize_confidence.py import cv2 import numpy as np from ultralytics import YOLO model = YOLO("runs/detect/exp_power_fitting_v8s/weights/best.pt") results = model("test_img.jpg", verbose=False) # 获取原始图像和预测结果 img = cv2.imread("test_img.jpg") boxes = results[0].boxes.xyxy.cpu().numpy() # [x1,y1,x2,y2] confidences = results[0].boxes.conf.cpu().numpy() # 创建热力图(高斯核加权) heatmap = np.zeros(img.shape[:2], dtype=np.float32) for box, conf in zip(boxes, confidences): x1, y1, x2, y2 = map(int, box) center = ((x1+x2)//2, (y1+y2)//2) radius = int(((x2-x1)+(y2-y1))//4) # 高斯核:conf越高、半径越大,热力越集中 y, x = np.ogrid[:img.shape[0], :img.shape[1]] mask = (x - center[0])**2 + (y - center[1])**2 <= radius**2 heatmap[mask] += conf * np.exp(-0.5 * ((x[mask]-center[0])**2 + (y[mask]-center[1])**2) / (radius/3)**2) # 归一化并叠加到原图 heatmap = cv2.normalize(heatmap, None, 0, 255, cv2.NORM_MINMAX) heatmap = cv2.applyColorMap(heatmap.astype(np.uint8), cv2.COLORMAP_JET) overlay = cv2.addWeighted(img, 0.6, heatmap, 0.4, 0) cv2.imwrite("test_img_heatmap.jpg", overlay)

价值:若热力图集中在金具边缘而非中心,说明模型依赖纹理而非形状——需加强Shape-Aware Augmentation(如RandomErasing on bbox interior)。

5.2 视频流实时检测:解决帧间抖动与ID漂移

无人机巡检视频存在剧烈抖动,直接逐帧推理会导致bbox在相邻帧间跳变。必须引入轻量级跟踪:

# track_video.py from ultralytics import YOLO from collections import defaultdict import cv2 model = YOLO("best.pt") tracker = model.track # Ultralytics内置ByteTrack cap = cv2.VideoCapture("line_inspect.mp4") track_history = defaultdict(lambda: []) while cap.isOpened(): success, frame = cap.read() if not success: break # track返回包含id的boxes results = model.track(frame, persist=True, tracker="bytetrack.yaml") boxes = results[0].boxes.xywh.cpu() track_ids = results[0].boxes.id.int().cpu().tolist() # 绘制轨迹(仅画最近30帧) annotated_frame = results[0].plot() for box, track_id in zip(boxes, track_ids): x, y, w, h = box track = track_history[track_id] track.append((float(x), float(y))) if len(track) > 30: track.pop(0) points = np.hstack(track).astype(np.int32).reshape((-1, 1, 2)) cv2.polylines(annotated_frame, [points], isClosed=False, color=(230, 230, 230), thickness=2) cv2.imshow("Tracking", annotated_frame) if cv2.waitKey(1) & 0xFF == ord("q"): break cap.release() cv2.destroyAllWindows()

关键配置:tracker="bytetrack.yaml"需修改其中track_high_thresh: 0.5(提高激活阈值,减少误检ID)、new_track_thresh: 0.3(降低新ID创建门槛,适应金具短暂遮挡)。

5.3 边缘设备部署:TensorRT加速与INT8量化实测

在Jetson Orin上,FP16模型推理速度仅18 FPS,无法满足25fps视频流需求。必须量化:

# 1. 导出ONNX(--dynamic指定动态batch) yolo export model=best.pt format=onnx dynamic=True # 2. 使用polygraphy构建TensorRT引擎(INT8) polygraphy convert yolov8s.onnx \ --fp16 \ --int8 \ --calibration-data-path ./calib_images/ \ --calibration-cache ./calib_cache.bin \ --output yolov8s_int8.engine

校准数据要求:从images/中随机抽取200张图(非训练集),确保覆盖所有8类金具,且包含不同光照、距离、角度——这是INT8精度不崩的关键。实测显示,INT8量化后Orin上达42 FPS,mAP@0.5仅下降0.012(0.721→0.709),完全可接受。

从那以后我每次交付电力AI项目,都强制走一遍“单图热力图→视频轨迹→边缘INT8校准”三步验证。少走一步,现场调试就得熬通宵。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询