基于yolo11与yolov8的输电线路红外过热检测系统:从数据集到RK3588部署 简介这份资源面向电力巡检与目标检测方向的开发者、学生及科研人员提供一套基于YOLO11与YOLOv8的输电线路过热检测完整方案可用于课程大作业、毕业设计或电力智能巡检原型验证。压缩包共2000个文件约407.5MB包含1331个txt标注与说明、194个Python源码、93个yaml配置、356个md文档以及少量xml、cpp、sh、pdf等辅助文件覆盖数据处理、模型训练、推理部署全流程。资源内含已处理好的2000张输电线路过热图像数据类别为overheat并附带训练与测试源代码、已训练好的YOLO11和YOLOv8权重以及基于PySide的图形化界面和基于Gradio的Web界面方便直接运行与二次开发。目前已有277人学习适合希望快速掌握电力设备过热检测、对比两种YOLO版本性能并落地可视化交互的读者参考。1. 输电线路过热检测为什么 yolo11 和 yolov8 要放在同一套系统里输电线路接头、线夹、耐张线夹这些部位一旦接触电阻变大温度就会异常升高红外巡检时表现为明显的亮斑。传统做法是人工看红外图逐张判断一条 220kV 线路几百个杆塔看下来眼睛都花了漏检率还高。基于 yolo11 和 yolov8 的输电线路过热检测系统本质是把红外热成像图里的过热区域当成目标检测问题来做用 yolov8 快速跑通基线、验证数据集质量再用 yolo11 做精度和部署上的迭代最后落到边缘设备上做实时告警。这套方案适合三类人一是做电力巡检方向的大作业或毕设需要一套能跑通、能写进论文的完整流程二是想把 YOLO 系列真正部署到 RK3588 这类边缘盒子上的工程师三是手里已经有红外数据集但不确定该用哪个版本、怎么调参的从业者。下面按数据集准备、yolov8 基线、yolo11 迭代、部署验证、避坑的顺序讲清楚。2. 数据集与标注红外过热区域怎么变成 YOLO 能吃的格式2.1 红外过热检测的数据特点与类别设计输电线路红外图有几个和普通可见光数据集不一样的地方。第一背景极其单调天空和杆塔占了大半画面目标只占很小一块正负样本极度不平衡。第二过热区域边界模糊红外图上亮斑是渐变的标注时到底框到哪一圈不同人标出来能差十几个像素。第三同一张图里可能有多个过热接头也可能一个都没有负样本比例高。类别设计上我一般不建议一上来就分「一般过热、严重过热、危急过热」三级。原因是红外图的绝对温度受环境温度、发射率、拍摄距离影响很大同一温度在不同季节可能对应不同等级模型学不到稳定特征。更稳的做法是先做二分类overheat和背景把分级交给后处理里的温度阈值去判。等数据量上到几千张、标注一致性有保证之后再考虑加overheat_mild、overheat_severe两个类。数据集目录按 YOLO 标准结构组织datasets/transmission_ir/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamldata.yaml内容path: /home/user/datasets/transmission_ir train: images/train val: images/val test: images/test nc: 1 names: [overheat]这里nc是类别数二分类就是 1。names的顺序必须和标注文件里 class_id 对应标错了模型会学反。划分比例上输电线路场景我建议 train:val:test 7:2:1验证集要保证每个杆塔类型、每种拍摄角度都有覆盖不能随机切完发现验证集全是晴天拍的。2.2 从 VOC/COCO 转 YOLO 格式的脚本与边界处理很多电力数据集原始标注是 VOC 的 XML 或者 COCO 的 JSON转 YOLO 格式时最容易翻车的是坐标归一化和越界裁剪。下面这个脚本处理 VOC 转 YOLOimport os import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_dir, img_dir, out_dir, classes): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() img_name root.find(filename).text img_path os.path.join(img_dir, img_name) # 用真实图片尺寸不要信 XML 里的 size标注工具经常写错 w, h Image.open(img_path).size lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in classes: continue cls_id classes.index(cls_name) bbox obj.find(bndbox) x1 float(bbox.find(xmin).text) y1 float(bbox.find(ymin).text) x2 float(bbox.find(xmax).text) y2 float(bbox.find(ymax).text) # 裁剪到图像范围内防止标注越界导致归一化后出负数 x1, y1 max(0, x1), max(0, y1) x2, y2 min(w, x2), min(h, y2) if x2 x1 or y2 y1: continue # 裁剪后无效框直接丢 cx (x1 x2) / 2.0 / w cy (y1 y2) / 2.0 / h bw (x2 - x1) / w bh (y2 - y1) / h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) out_file os.path.join(out_dir, xml_file.replace(.xml, .txt)) with open(out_file, w) as f: f.write(\n.join(lines)) voc_to_yolo(annotations/xml, images/all, labels/all, [overheat])逻辑说明YOLO 格式要求class_id cx cy w h全部归一化到 0~1。关键点是图片宽高必须从真实图片读XML 里的size字段经常和实际不符用错了整批标注都会偏。裁剪那两行是后悔药标注工具画框时手一抖超出边界很常见不裁的话归一化后出现负数或大于 1训练时 loss 直接 NaN。参数说明classes列表顺序决定 class_id必须和data.yaml的names完全一致。:.6f保留六位小数YOLO 官方推荐至少六位位数太少小目标坐标会丢精度。2.3 数据增强策略红外图不能照搬可见光的配方可见光那套 Mosaic、HSV 增强直接搬到红外图上会出问题。HSV 里的 H 色调对红外图没意义红外图基本是伪彩色或灰度调色调等于制造不存在的样本。我一般这样配增强方式参数是否启用原因mosaic1.0启用提升小目标召回红外目标小fliplr0.5启用左右翻转符合巡检视角变化flipud0.0关闭杆塔上下翻转不符合物理hsv_h0.0关闭红外无色调概念hsv_s0.3弱启用模拟不同红外增益hsv_v0.4启用模拟环境温度变化scale0.5启用模拟不同拍摄距离Mosaic 对小目标帮助很大但要注意红外图拼接后亮斑可能被切到边缘训练后期建议最后 10 个 epoch 关掉 mosaic让模型在真实分布上收敛。这个技巧在 yolov8 和 yolo11 上都适用。3. yolov8 基线先把环境配通再谈精度3.1 yolov8 环境配置与最小训练命令yolov8 环境配置是新手最容易卡住的地方。CUDA 版本、PyTorch 版本、ultralytics 版本三者要对上。我一般用 conda 隔离conda create -n yolo8 python3.10 -y conda activate yolo8 # 根据显卡驱动选 CUDA 版本30 系 40 系一般 cu118 或 cu121 pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics8.1.0装完先验证python -c import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))输出True和显卡型号才算通。如果显示False八成是 CUDA 版本和驱动不匹配别急着改代码先解决环境。最小训练命令yolo detect train \ datadatasets/transmission_ir/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectruns/ir_detect \ nameyolov8n_baseline参数说明modelyolov8n.pt是 nano 版本先用小模型跑通流程确认数据没问题再换 s/m。imgsz640是输入尺寸红外小目标如果特别小可以上到 1280但显存翻倍。batch16在 8G 显存上跑 640 尺寸基本够GTX1660Ti 这种 6G 卡建议降到 8。device0指定第一块 GPU多卡用0,1。3.2 用损失曲线判断训练是否真的在收敛训练跑起来不代表在收敛。yolov8 训练完会在runs/ir_detect/yolov8n_baseline/下生成results.csv画损失曲线import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/ir_detect/yolov8n_baseline/results.csv) df.columns df.columns.str.strip() # 列名有空格必须去 fig, axes plt.subplots(1, 2, figsize(12, 4)) axes[0].plot(df[epoch], df[train/box_loss], labeltrain box) axes[0].plot(df[epoch], df[val/box_loss], labelval box) axes[0].set_xlabel(epoch); axes[0].set_ylabel(box loss); axes[0].legend() axes[1].plot(df[epoch], df[metrics/mAP50(B)], labelmAP50) axes[1].plot(df[epoch], df[metrics/mAP50-95(B)], labelmAP50-95) axes[1].set_xlabel(epoch); axes[1].set_ylabel(mAP); axes[1].legend() plt.tight_layout() plt.savefig(loss_curve.png, dpi150)逻辑说明results.csv的列名带前后空格不 strip 会 KeyError这是血泪经验。看曲线重点看三条train box loss 是否稳定下降、val box loss 是否跟着降、mAP50 是否在涨。如果 train 降 val 不降甚至涨是过拟合加数据或加增强如果两个都不降是学习率太大或数据标注有问题。参数说明metrics/mAP50(B)是 IoU0.5 的 mAP红外过热检测主要看这个mAP50-95更严格小目标场景一般会低不少别拿它当唯一指标。3.3 可视化热力图定位模型到底在看哪模型 mAP 高不代表它学对了。红外图里如果过热区域旁边有个杆塔螺栓特别亮模型可能学的是螺栓而不是过热。用热力图验证from ultralytics import YOLO import cv2 import numpy as np model YOLO(runs/ir_detect/yolov8n_baseline/weights/best.pt) img cv2.imread(test_ir.jpg) results model(img, imgsz640) # 取第一个检测框的梯度热力图 for r in results: if r.boxes is None or len(r.boxes) 0: continue for box in r.boxes: x1, y1, x2, y2 map(int, box.xyxy[0].tolist()) roi img[y1:y2, x1:x2] gray cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) heatmap cv2.applyColorMap(gray, cv2.COLORMAP_JET) overlay cv2.addWeighted(roi, 0.6, heatmap, 0.4, 0) cv2.imwrite(fheat_{x1}_{y1}.jpg, overlay)逻辑说明这里用 ROI 灰度做伪热力图快速看模型关注区域和真实过热亮斑是否重合。更严谨的做法是 Grad-CAM但对红外图来说过热区域本身就是高亮灰度伪彩已经够用。如果发现模型框的位置和亮斑中心偏了说明标注框画大了回去修标注。参数说明imgsz640要和训练时一致否则检测框坐标会偏。addWeighted的 0.6/0.4 是叠加比例想让热力图更明显就调成 0.4/0.6。4. yolo11 迭代结构变化带来哪些实际收益4.1 yolo11 网络结构里值得关注的两个改动yolo11 相比 yolov8在 backbone 和 head 上都有调整。对输电线路过热检测这种小目标场景值得关注两点。一是 yolo11 在 neck 部分用了更高效的特征融合结构小目标的语义信息保留得更好实测在 640 输入下小亮斑召回比 yolov8n 高几个点。二是 head 的解耦方式有变化分类和回归分支的独立性更强对边界模糊的红外目标回归框更稳。但别指望换个版本就起飞。yolo11 的收益建立在数据集质量过关的基础上如果标注本身框得歪换什么版本都白搭。我一般先用 yolov8 跑出基线 mAP再换 yolo11 同规模模型对比涨点超过 2 个点才值得切。4.2 从 yolov8 迁移到 yolo11 的训练配置差异yolo11 同样用 ultralytics 框架命令几乎一样但有几个参数要注意yolo detect train \ datadatasets/transmission_ir/data.yaml \ modelyolo11n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ optimizerAdamW \ lr00.001 \ warmup_epochs3 \ projectruns/ir_detect \ nameyolo11n_iter参数说明yolo11 默认优化器在部分版本里是 auto小数据集上 AdamW 比 SGD 收敛更稳lr00.001是 AdamW 的常用起点比 SGD 的 0.01 小一个量级。warmup_epochs3让学习率在前 3 个 epoch 线性上升避免一开始就大步长把预训练权重冲坏。如果显存够batch可以上到 32梯度更稳。迁移时权重不能直接复用yolov8 的.pt和 yolo11 的结构不兼容必须用 yolo11 自己的预训练权重。数据集和data.yaml可以直接复用这是同一套系统里两个版本能共存的基础。4.3 两个版本同框对比mAP、速度、显存怎么记对比要控制变量同一份数据、同一个 imgsz、同一个 batch只换模型。记录表格模型mAP50mAP50-95单图推理(ms)显存(G)参数量(M)yolov8n0.860.528.23.13.2yolov8s0.890.5614.55.411.2yolo11n0.880.557.83.02.6yolo11s0.910.5913.95.29.4以上是典型量级具体数值随数据集变化别照抄。推理速度用model.val()里的 speed 字段或者自己写循环测 100 张取平均。显存用torch.cuda.max_memory_allocated()读。选型上如果边缘设备算力紧张yolo11n 在精度略高于 yolov8n 的同时参数量更小是更优解如果追求极致精度且算力够yolo11s 是甜点。5. 部署到 RK3588从 PyTorch 到边缘盒子的完整链路5.1 导出 ONNX 与 RKNN 转换的关键参数RK3588 部署 yolov8/yolo11标准链路是 PyTorch → ONNX → RKNN。导出 ONNXyolo export modelruns/ir_detect/yolo11n_iter/weights/best.pt \ formatonnx imgsz640 opset12 simplifyTrue参数说明opset12兼容性最好RKNN 工具链对高版本 opset 支持不稳。simplifyTrue会做图优化去掉冗余算子转换成功率更高。导出后检查输入输出名字RKNN 转换时要对上。RKNN 转换脚本from rknn.api import RKNN rknn RKNN(verboseTrue) # 均值方差要和训练时一致YOLO 默认 0~1 归一化 rknn.config(mean_values[[0, 0, 0]], std_values[[255, 255, 255]], target_platformrk3588) rknn.load_onnx(modelbest.onnx) rknn.build(do_quantizationTrue, datasetquant_dataset.txt) rknn.export_rknn(best.rknn)逻辑说明mean_values和std_values决定预处理YOLO 训练时输入是 0~1所以 std 用 255。do_quantizationTrue做 int8 量化能大幅提速但需要quant_dataset.txt里放几百张代表性图片做校准。量化后精度一般掉 1~3 个点如果掉太多检查校准集是否覆盖了各种光照和角度。参数说明target_platformrk3588必须写对写错平台转换出来的模型跑不了。dataset文件每行一张图片路径建议 200~500 张从训练集里均匀采样。5.2 板端推理与后处理对齐RK3588 上跑 RKNN 模型后处理要自己写因为 RKNN 输出的是原始特征图不是检测框。yolo11 和 yolov8 的输出格式类似都是多尺度特征图需要做解码import numpy as np def decode_yolo(outputs, conf_thres0.25, iou_thres0.45): # outputs: list of feature maps, shape [1, 4nc, h, w] boxes, scores, class_ids [], [], [] for out in outputs: _, c, h, w out.shape out out.reshape(1, c, h * w).transpose(0, 2, 1)[0] # 前 4 个是 xywh后面是类别分数 xywh out[:, :4] cls_scores out[:, 4:] cls_id np.argmax(cls_scores, axis1) conf np.max(cls_scores, axis1) mask conf conf_thres if not mask.any(): continue # 解码到原图坐标这里省略 stride 和 anchor 计算按实际输出补 boxes.append(xywh[mask]) scores.append(conf[mask]) class_ids.append(cls_id[mask]) # NMS 部分用 cv2.dnn.NMSBoxes 或自己实现 return boxes, scores, class_ids逻辑说明RKNN 输出的特征图需要按 stride 还原到原图坐标再拼成 xyxy 格式做 NMS。这段代码省略了 stride 计算实际要按模型输出的三个尺度分别处理。后处理对齐是部署最容易翻车的地方板端框位置偏了九成是解码时 stride 或归一化系数写错。参数说明conf_thres0.25是置信度阈值红外过热检测宁可多报不可漏报可以降到 0.2。iou_thres0.45是 NMS 的 IoU 阈值过热区域重叠少可以适当调高到 0.5。5.3 边缘端性能实测与调优方向RK3588 上 yolo11n 量化后单帧推理大概在 30~50msyolov8n 差不多。如果达不到先查是不是跑在 CPU 上RKNN 要显式指定 NPU 核心。多核 NPU 可以用rknn.init_runtime(core_maskRKNN.NPU_CORE_0_1_2)把三个核心都用上速度能再提一截。输入尺寸从 640 降到 416 能提速近一倍但小目标召回会掉红外过热检测不建议降太多。6. 避坑与排查这套系统最容易翻车的五个地方6.1 训练 loss 正常但 mAP 一直是 0现象训练日志里 box loss 在降但 mAP50 始终是 0。原因标注文件的 class_id 从 1 开始而 YOLO 要求从 0 开始模型把所有目标当背景。解决检查labels里第一列必须是 0 到 nc-1用脚本批量扫一遍发现最大值等于 nc 就整体减 1。6.2 验证集 mAP 很高实际巡检图全漏检现象val mAP 0.9拿现场新拍的图测一个都没框出来。原因训练集和验证集来自同一批拍摄分布太像模型没学到泛化特征。解决划分数据集时按杆塔或按拍摄日期切不要随机切另外检查现场图的分辨率和训练图是否差太多差太多要做 resize 或切图。6.3 RKNN 量化后精度断崖式下跌现象ONNX 上 mAP 0.88转 RKNN int8 后掉到 0.6。原因校准集没覆盖实际场景或者量化时某些层对数值敏感。解决校准集从训练集里按类别和亮度分层采样至少 300 张如果还不行对敏感层做混合量化把检测 head 保留 fp16。6.4 板端推理框位置整体偏移现象框能出来但位置比真实目标偏了几十像素。原因后处理解码时 stride 用错或者预处理 resize 的 padding 没还原。解决打印第一个特征图的输出尺寸反推 strideletterbox 的 padding 值要在解码后减掉再除以缩放比例。6.5 显存够但训练中途 OOM现象GTX1660Ti 6Gbatch16 跑几十个 epoch 后突然 OOM。原因验证阶段会额外占显存加上 dataloader 的缓存累积。解决把batch降到 8开ampTrue混合精度workers从 8 降到 4验证频率从每 epoch 改成每 5 个 epoch。7. 一个能落地的技巧用温度阈值做二次过滤模型输出的是框但电力巡检真正要的是「这个接头到底过不过热」。光靠检测框置信度不够因为红外图里阳光反射、金属反光也会形成亮斑模型分不清。我一般加一层温度阈值过滤如果红外图带温度矩阵很多红外相机导出时带 RAW 温度数据取检测框内的最高温和环境温度比超过 15K 才告警。import numpy as np def temp_filter(box, temp_matrix, ambient_temp, delta15.0): x1, y1, x2, y2 box roi temp_matrix[y1:y2, x1:x2] max_temp np.max(roi) # 相对温差比绝对温度稳不受季节影响 return (max_temp - ambient_temp) delta, max_temp逻辑说明temp_matrix是红外图对应的温度矩阵单位摄氏度。ambient_temp取画面里杆塔背景区域的中位数温度。用相对温差而不是绝对温度是因为夏天环境 40 度时接头 55 度不算异常冬天环境 5 度时接头 25 度就该查了。delta15.0是经验阈值按 DL/T 664 的惯例相对温差超过 15K 属于一般缺陷超过 30K 是严重缺陷可以按需调。参数说明temp_matrix要和可见光图对齐如果红外和可见光有视差先做配准。ambient_temp别用整图平均画面里天空占比大会把均值拉低用杆塔区域的中位数更准。这套系统我从 yolov8 基线跑到 yolo11 迭代再到 RK3588 部署前后踩的坑基本都在上面了。最大的教训是别一上来就追新版本、追改进模块先把数据集标注一致性做到位把 yolov8 基线跑稳后面换 yolo11、上边缘设备都是顺水推舟的事。数据集烂什么模型都救不了。希望帮到你。本文还有配套的精品资源点击获取