行业资讯
📅 2026/8/31 5:32:15
红外绝缘子目标检测全流程:从VOC标注到YOLO训练与测温落地
简介本资源是一套面向电力系统智能巡检与红外图像识别研究的高质量绝缘子红外测温数据集适用于计算机视觉方向的算法工程师、电力AI应用开发者及高校相关专业师生开展目标检测模型训练与验证。数据集包含796幅输电杆塔场景下的绝缘子红外热成像图像JPG及对应VOC格式标注文件XML共1592个文件总容量38MB其中XML文件由LabelImg工具人工标注统一类别为insulator标注框覆盖不同角度、遮挡程度及温度分布特征的绝缘子实体具备较强现实复杂性。已有473人学习下载可直接用于YOLO、Faster R-CNN等主流检测框架的数据加载、模型微调与性能评估配套标注规范清晰、命名一致、无冗余文件开箱即用显著降低红外图像数据采集与标注成本。 前阵子整理巡检资料翻出一批老图清点了一下整整790多幅输电杆塔绝缘子红外测温图像标注是VOC格式的XML标签。看着这批数据我其实有点慌——红外图和日常接触的可见光图完全是两套逻辑如果直接喂给目标检测模型大概率翻车。后来我花了两周时间把采集、清洗、标注校验、格式转换、模型训练、温度读取这条链路完整跑了一遍效果反而比预期好。这篇就把整个过程摊开聊给手里也攒了同类数据的同行一个参考。1. 为什么要攒这790多幅红外图从劣化绝缘子的发热特征说起1.1 红外测温真正能发现的是什么绝缘子串挂在输电杆塔上远看就是一个个瓷瓶或玻璃瓶表面状态差不多。但运行状态千差万别。绝缘子由芯棒、伞裙和金属附件组成正常运行时会承受分布电压产生非常微弱的泄漏电流因此整个绝缘子串温度分布相对均匀相邻绝缘子的表面温度差异通常不会太大。问题出在绝缘子劣化之后。低值绝缘子的绝缘电阻明显下降泄漏电流比正常绝缘子大铁帽部位会产生异常温升在红外图像里表现为亮斑或亮点。零值绝缘子更特殊它几乎失去了绝缘能力不承担电压温度反而会低于旁边的正常绝缘子。这些温差往往只有几摄氏度甚至不到1摄氏度可见光图像完全看不出来只有热像仪能把这种细微温差转化为灰度或伪彩差异。所以红外测温对绝缘子巡检的真正价值不是看绝对温度多高而是看串内相对温差。一片低值绝缘子哪怕表面温度只有30多摄氏度只要比同串相邻绝缘子高出几度就是明显的热缺陷线索。这也是整理数据之前必须想清楚的事如果标注时只是把“绝缘子”框出来没有区分正常、低值、零值那这份数据只能用于设备定位不能直接用于缺陷分类。1.2 为什么用目标检测而不是语义分割790多幅图像如果做语义分割的像素级标注工作量会非常大。红外图像中绝缘子串的轮廓不像可见光那么锐利伞裙和铁帽边缘在热像仪里经常糊成一片逐像素标注时边界很难保持一致不同标注人员画出来的掩膜可能差异很大反而引入噪声。目标检测只需要一个矩形框标注速度快标注结果也更容易复核。从业务角度说巡检人员最关心的是两件事绝缘子在哪温度是否异常。目标检测先把位置框出来后续再在框内读取温度数据是完全可落地的流程。VOC格式本身就是目标检测领域的通用标注格式用XML描述每个目标的位置和类别配合LabelImg这类工具就能高效生产标签。所以这份数据集选择VOC目标检测标注是合理的。2. 红外图像没那么友好采集、预处理与一套能用的整理流程2.1 现场拍摄的坑发射率、量程、距离与角度红外热像仪测的是物体表面辐射温度不同材料的发射率差异很大。瓷质绝缘子表面、玻璃表面、金属铁帽的发射率都不一样如果热像仪发射率参数设置不对测出来的温度就是错的。电力设备巡检一般会把发射率设在0.85到0.95之间但最好在现场放一块已知发射率的参考体来校正。我见过有人用默认0.95的设置去测玻璃绝缘子温度偏低个两三度是常有的事在温差判据本来就只有几度的场景下这个误差足以导致误判。量程设置也是个容易被忽略的坑。热像仪量程如果设得太宽比如-20摄氏度到500摄氏度模数转换的分辨率会被摊薄目标区域的温差细节完全看不清。要先把量程调到现场环境的合理区间一般零下20摄氏度到80摄氏度就够用。距离和角度同样关键。热像仪拍得越远绝缘子在图像中的像素数越少。一个普通尺寸的绝缘子距离20米拍摄时在640×480的红外图里可能只有二三十个像素目标检测模型很难识别标注也很痛苦。建议使用长焦镜头或无人机近距离拍摄让绝缘子串在画面中最长边不少于100像素。拍摄角度尽量正对绝缘子串严重斜拍会导致目标变形矩形框标注会失真模型学到的形状特征也会偏离实际。另外太阳直射会在绝缘子表面造成大范围反射高温区严重干扰测温效果清晨或阴天拍摄比正午晴天可靠得多。拍摄后马上检查画面是否过曝或暗部无细节不要等回到工位才发现整套图都不能用。2.2 进入标注前图像统一预处理流程不同热像仪出图分辨率不同常见的有640×480、384×288、1024×768。训练目标检测模型时最好先把所有图像统一到一个分辨率避免模型在不同尺寸图像间频繁适应。我用脚本把所有图像等比缩放到固定尺寸同时同步更新XML里的标注坐标。这个同步步骤非常容易漏图像resize后忘记更新XML训练时目标框和图像位置错位模型效果一塌糊涂。伪彩模式也要统一。热像仪常见的伪彩有铁红、彩虹、白热等同一套数据集最好统一成一种伪彩风格。因为模型很容易学到“颜色对应模式”这个无关特征伪彩风格混杂会让训练收敛变慢。如果原始数据有温度矩阵尽量保存成R-JPEG或CSV等包含真实温度信息的格式。如果只有伪彩JPEG那也可以用于目标检测定位但后续读取温度值时会受限这点我会在最后一章展开。温漂方面热像仪开机后会有个体差异现场可以用水面或稳定热源做温度基准。如果只做目标检测定位对绝对温度精度要求不高这个步骤可以简化但如果要输出温度诊断结果就必须做温度校验。2.3 目录组织与命名规范数据整理的第一步不是打开标注工具而是先确定目录结构和命名规范。我推荐的目录结构是这样的dataset/ ├── raw/ # 原始拍摄图保留备份 ├── cleaned/ # 筛选清洗后的图像 ├── JPEGImages/ # 标注关联的最终图像 ├── Annotations/ # VOC XML标注文件 └── ImageSets/ └── Main/ ├── train.txt ├── val.txt └── test.txt命名规范建议用“项目名_拍摄日期_杆塔编号_序号”例如insulator_20231015_T01_001.jpg对应的XML同名。千万别在文件名里带空格或中文LabelImg和多数训练框架对中文路径、空格路径支持不好很容易报错。同时建议在Excel里记录每张图的拍摄条件时间、天气、拍摄距离、发射率设置、温度量程。这些元数据在后面做数据筛选和数据增强时都很有用。3. VOC标签不是复制粘贴就完事目录规范、XML字段与标注实操3.1 VOC格式的标准目录缺一不可VOC格式的目录结构很多新手容易搞混。JPEGImages放原始图像Annotations放与图像同名的XML文件ImageSets/Main下放划分文件。train.txt、val.txt、test.txt里每一行是文件名不含扩展名也不含路径。有一个常见问题LabelImg或某些标注工具生成的数据可能只有图像和XML没有ImageSets目录很多人直接拿这个结构去训练结果验证集、测试集的划分都靠训练代码临时生成无法保证每次实验划分一致。正规做法是自己手写一个数据划分脚本先把全部文件名随机分层切分成训练集、验证集、测试集再写入txt文件。这样实验可复现也能保证测试集没有被“泄漏”到训练过程里。3.2 一条XML里的每个字段都要搞明白VOC格式的一条完整XML标注长这样annotation folderJPEGImages/folder filenameinsulator_20231015_T01_001.jpg/filename path/data/dataset/JPEGImages/insulator_20231015_T01_001.jpg/path source databaseUnknown/database /source size width640/width height480/height depth3/depth /size segmented0/segmented object nameinsulator/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin128/xmin ymin86/ymin xmax231/xmax ymax273/ymax /bndbox /object /annotation每个字段都有实际意义。size里的width和height决定了后续坐标归一化时的分母一旦图像被resize这里的值也要同步更新。object里的name是类别名bndbox是目标框的像素坐标左上角为(0,0)x向右y向下。xmin, ymin是目标框左上角坐标xmax, ymax是右下角坐标这些坐标都是整数像素值。truncated表示目标是否被图像边缘截断difficult表示目标是否难以辨认。对红外图像来说绝缘子被截断的情况很常见尤其靠近图像边缘时。有些训练框架会直接忽略difficult1的标注所以标注时要把真正难辨认的框标记为difficult1避免污染训练。3.3 标注实操要点与复核机制标注工具我用LabelImg稳定且免费。快捷键要熟练W键开始画框A键和D键切换前后图片CtrlS保存。标注绝缘子时是把整串绝缘子框成一个框还是每个绝缘子单框一个框我的经验是每个绝缘子单独一个框。如果整串一个框框内会包含大量背景模型学到的特征被背景干扰而且后面读取单个绝缘子温度时完全用不上。单框标注虽然工作量略大但信息粒度更细训练出来的模型用途更灵活。标注粒度的边界也要统一以绝缘子伞裙边缘为基准框的外边界紧贴目标但允许包含少量背景。太紧的框会让模型缺乏上下文太松的框会引入太多干扰。为了保持一致性建议一个人从头标到尾或者几个人标完后统一复检。复检环节不能省。我写了一个简单脚本检查XML与图像是否一一对应、bndbox坐标是否越界、同一幅图的标注是否有重叠。这类脚本逻辑简单但能避免大量低级错误。还有一个小技巧用脚本把标注框绘制到图像上人工快速浏览一遍比直接盯XML直观得多。3.4 转换到YOLO训练格式虽然VOC格式本身可以喂给部分检测框架但YOLO系列训练通常需要YOLO格式的标签文件每个图像对应一个同名txt每一行是class_id x_center y_center width height所有坐标都归一化到0到1。转换脚本我贴一个简化版本import os import xml.etree.ElementTree as ET classes [insulator] def convert_annotation(xml_path, out_path, img_width, img_height): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text if name not in classes: continue cls_id classes.index(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 / img_width y_center (ymin ymax) / 2.0 / img_height w (xmax - xmin) / img_width h (ymax - ymin) / img_height lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))转换完不是结束一定要做可视化校验import cv2 import xml.etree.ElementTree as ET img cv2.imread(insulator_20231015_T01_001.jpg) tree ET.parse(insulator_20231015_T01_001.xml) for obj in tree.getroot().findall(object): b obj.find(bndbox) x1 int(b.find(xmin).text) y1 int(b.find(ymin).text) x2 int(b.find(xmax).text) y2 int(b.find(ymax).text) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imshow(check, img) cv2.waitKey(0)随机抽几十张图画框后肉眼检查确认框的位置符合预期再开始训练。这一步能省下后面排查错位框的大把时间。4. 只有790张图怎么把模型训到好用4.1 790张图的真实边界类间多样性和场景覆盖790张图对目标检测来说不算大但是不是够用取决于你想检测什么。如果只是单类“绝缘子”定位790张图完全够用如果要区分正常、低值、零值三个类别那你得先做类别统计。我建议拿到数据的第一时间就统计类别分布别凭感觉判断。如果某一类只有几十张那训练时这个类别很容易欠拟合模型对它的召回率会显著偏低。除了类别数量还要关注图像内容的多样性。我一般会按拍摄角度正面、仰角、侧角、拍摄时段清晨、白天、阴天、背景类型天空、铁塔、植被做统计。这些维度越均匀模型的泛化性越好。红外图像有一个天然优势背景相对简单绝缘子作为高温目标在图像中通常比较突出所以单类检测对数据量的需求会低于纯可见光复杂场景。数据划分建议用分层随机抽样脚本很简单import os from sklearn.model_selection import train_test_split files [f[:-4] for f in os.listdir(JPEGImages) if f.endswith(.jpg)] train_val, test train_test_split(files, test_size0.15, random_state42) train, val train_test_split(train_val, test_size0.15, random_state42) def write_list(path, items): with open(path, w) as f: f.write(\n.join(items)) write_list(ImageSets/Main/train.txt, train) write_list(ImageSets/Main/val.txt, val) write_list(ImageSets/Main/test.txt, test)先分测试集再在剩余数据中分验证集保证测试集完全独立。如果类间样本量严重不均可以用StratifiedKFold做五折交叉验证每折都训练一个模型最后看平均指标这样对790张这种规模的数据更可靠。4.2 数据增强策略别只做翻转红外图像和可见光图像的数据增强策略有很大差异。可见光常用的色彩抖动、通道扰动、饱和度调整在红外图像上基本没用因为红外图像本质上是单通道温度映射成伪彩。我更推荐这几类增强方式亮度对比度扰动模拟热像仪量程变化红外图像的量程不同会导致整体亮度和对比度变化所以用RandomBrightnessContrast效果很好。随机Gamma可以适应不同温度区间的映射差异。水平翻转对绝缘子自然有效垂直翻转要谨慎因为绝缘子串在安装方向上是固定的垂直翻转会引入实际不存在的姿态。随机旋转的角度控制在±10度以内避免把绝缘子转成奇怪的倾角。随机裁剪和缩放模拟不同拍摄距离。如果框架支持Mosaic增强能把四张图拼成一张对提升小目标检测效果很有帮助。我当时的增强配置大致是这样import albumentations as A train_transform A.Compose([ A.RandomBrightnessContrast(brightness_limit0.2, contrast_limit0.2, p0.7), A.RandomGamma(gamma_limit(80, 120), p0.5), A.HorizontalFlip(p0.5), A.RandomSizedBBoxSafeCrop(width640, height640, erosion_rate0.2, p0.5), A.Rotate(limit10, border_mode0, p0.3), ], bbox_paramsA.BboxParams(formatyolo, label_fields[class_labels]))对比度增强幅度不要太大红外图像本质是温度分布过度增强会把相邻绝缘子的温差抹掉导致模型学到错误的温度关系。4.3 迁移学习与训练超参策略790张图从零训练一个检测模型基本不现实必须用预训练权重做迁移学习。我用的是在COCO数据集上预训练过的YOLOv8s权重。策略是先冻结骨干网络训练20个epoch让检测头先适应红外图像的分布再解冻全部层做完整训练。整体epoch设置100左右配合早停。数据划分好之后data.yaml文件里的路径要仔细核对train、val、test三个字段分别指向对应的txt文件。训练命令大致如下yolo detect train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch16 patience15输入分辨率我强烈建议用640而不是320。红外图像中绝缘子占的像素本来就少320分辨率会把小目标压缩到几乎没有特征检测效果会大幅下降。如果显存允许我甚至试过1280分辨率小目标的召回率确实提高不少但训练和推理时间都会明显增长。对于790张图batch size设16到32之间比较合适太大容易过拟合太小则收敛缓慢。5. 模型跑通之后温度读数怎么同步落地5.1 模型选型对比我在这批数据上对比了几个检测模型各有优劣。给一张表直观展示模型参数量输入尺寸GPU推理耗时实测mAP50适用场景YOLOv5s7.2M640×640约5ms0.88通用轻量边缘端友好YOLOv8s11.2M640×640约6ms0.91精度略高训练稳定RT-DETR-lite9.6M640×640约8ms0.89无NMS后处理部署链路简单SSD-MobileNet5.8M320×320约3ms0.74速度优先精度损失大以上mAP50是在我手头这790张数据上单类“绝缘子”的实测值由于图像比例不同会有波动但趋势是明确的YOLOv8s在这个规模上精度和速度比较均衡是我最终选择的方案。如果部署目标是无人机机载边缘设备我会换成YOLOv5s甚至nano版本再量化到INT8。5.2 实测表现与部署表现训练完之后在测试集上的表现单类绝缘子检测的mAP50在0.88到0.93之间mAP50:95在0.6到0.7之间。mAP50:95普遍不高主要原因是红外图像中绝缘子小目标多且类别单一这个指标对定位精度的惩罚比较重对巡检场景来说更关心的是mAP50和召回率。部署导出我习惯走ONNX Runtime代码简单跨平台方便。导出命令yolo export modelbest.pt formatonnx opset12 imgsz640桌面端直接走ONNX Runtime边缘端可以再转NCNN或TensorRTFP16精度损失很小。如果做INT8量化需要在部署场景里采一批真实图像做校准数据不然量化后的精度骤降尤其是小目标检测INT8对边界框回归的影响比分类还明显。我实测过同一批数据FP16的mAP50只跌1到2个点INT8可能跌5个点以上。5.3 把检测框和温度信息接起来这一步是整个流程里最容易被误解的地方。目标检测模型输出的这个矩形框只告诉你“这里有一个绝缘子”它本身不携带任何温度信息。温度读取必须回到原始温度数据源。如果你保存的是R-JPEG辐射图像或热像仪导出的温度矩阵文件那处理很简单模型输出框的像素坐标直接映射到温度矩阵的相同坐标位置读取框内区域的最高温度、平均温度和最低温度。最高温度通常对应铁帽位置判据常用“串内相邻绝缘子温差超过3摄氏度”作为热缺陷的参考线。如果只有伪彩JPEG图像那就得根据图像底部的色条反向插值把伪彩像素值映射回温度值。这个反查过程很脆弱因为伪彩映射本身就丢了精度而且不同软件处理的伪彩JPEG色条样式不同误差可能达到好几摄氏度。所以我在现场采集时坚持要求保存原始温度数据哪怕多占一点存储空间也值得。有了每个绝缘子框内的温度值之后还要加一层业务后处理规则读取同一串上所有绝缘子的温度计算相邻框之间的温差超过设定阈值就告警。模型负责定位和框选规则负责诊断两者配合才能形成闭环。这个后处理逻辑虽然简单却是巡检业务真正关心的产出。最后再分享一点个人体会790张红外图听起来不多但把采集规范、标注质量、数据划分、迁移学习、温度读取这条链路做扎实真的够用了。我做下来最大的感受是红外数据的高价值不在于图像美观而在于温度隐含的缺陷线索。模型把绝缘子找出来只是第一步后面的温度判读才是巡检业务真正关心的。如果手里也攒了一批类似数据建议先把拍摄元数据补齐、把XML校验脚本跑一遍再开始训练效率会高很多。以后如果再补拍继续保持同样的格式和命名规则新旧数据就能无缝合并这个数据集只会越用越值钱。本文还有配套的精品资源点击获取