ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

输电线路红外过热检测数据集:VOC转YOLO与训练避坑实战

输电线路红外过热检测数据集:VOC转YOLO与训练避坑实战 简介针对输电线路红外过热缺陷检测任务该数据集以2000个Pascal VOC格式的XML标注文件为主体压缩包约36.3MB面向电力巡检算法工程师、计算机视觉研究人员及目标检测初学者可用于模型训练、验证集构建和算法效果评估。标注内容覆盖图像融合形成的过热缺陷与真实过热缺陷两类均由LabelImg人工逐框标注类别与边界框坐标信息完整可直接接入YOLO、Faster R-CNN等主流检测框架。样本聚焦绝缘子、线夹、接续管等易发热部位包含不同拍摄视角与场景能够支撑红外巡检缺陷识别、合成数据与真实数据分布对比、模型泛化能力测试等实验。目前已有564人学习下载适合需要扩充红外缺陷样本、检验标注一致性或在真实场景中调优检测精度的研究者和工程师使用。1. 输电线路红外过热检测图像数据集2000多张VOC标注图能解决什么实际问题输电线路红外过热检测图像数据集核心就一件事让做巡检算法的人不用从零攒图。2000多张红外图像每张都带VOC格式的XML标签框出的是发热点或过热缺陷。值得留意的是数据集里同时包含真实拍摄的过热缺陷和通过图像融合合成的缺陷这既是亮点也是训练时容易翻车的地方。巡检班组的日常是拿着热像仪对杆塔、导线、金具逐基测温晚上回来导出的图少则几百、多则上千过去靠人眼在热像仪软件里一张一张标经常到凌晨还在补报告。这份数据集能直接拿去训练目标检测模型把过热缺陷初筛从纯人工变成先算法后人工人力解放一半。适合正在做输电线路红外巡检算法、训练检测器、或者给电力视觉系统做demo验证的人。拿到手先别急着跑训练先把VOC结构和两类缺陷拆明白否则后边全是坑——这正是本文的主线。2. VOC标签与数据集结构先搞清楚2000多张图里到底有什么2.1 目录组织JPEGImages、Annotations、ImageSets缺一不可VOC格式的目录结构几乎是一套标准约定用表格列清楚的话是下面这样目录/文件作用JPEGImages/存放全部红外图像文件名与标注文件一一对应Annotations/存放VOC格式的XML标签每个XML描述一张图ImageSets/Main/存放train.txt、val.txt等划分文件每行一个文件名label.txt类别清单按行列出类别名部分数据集有有的没有拿到压缩包先解压第一件事就是核对这个目录骨架。JPEGImages里的图片数量和Annotations里的XML数量必须一致这是我最先查的。不一致时绝大多数是漏传、损坏或者把没标注的图也塞了进来。ImageSets/Main里的划分文件也要看一眼——有些发布者会给好train/val划分有些只给全量文件。这份数据集标题说的是2000多张图但2000多张怎么分到train和val发布者未必给了明确比例花10分钟核对完全值得。另外把label.txt打开看一眼。类别名是几个是只有过热缺陷一类还是分了真实缺陷和融合缺陷两个类这直接决定后边类别映射怎么写。很多做检测的人在这步偷懒后边转YOLO格式时才发现类名对不上回头翻XML是纯浪费时间。2.2 XML标签拆解一个发热点标注包含哪些字段VOC的annotation文件内容是XML结构固定。打开任意一个文件能看到类似下面这样的结构annotation folderJPEGImages/folder filenameIMG_1023.jpg/filename size width640/width height480/height depth3/depth /size object nameoverheat_defect/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin178/xmin ymin205/ymin xmax248/xmax ymax265/ymax /bndbox /object /annotation这套字段里训练真正用到的只有三块filename、size、object下的name和bndbox。filename决定图片名size里的width和height是归一化坐标的分母。注意depth字段对红外图没有实际意义热像仪输出的是单通道温度数据保存成伪彩色图后才是三通道这个不影响读取只要width和height对得上就行。object可能有多组表示一张图里有多个发热点。truncated表示目标是否被图像边界截断红外巡检图中目标在边缘很常见这个字段参考价值不大。difficult字段倒值得留意它表示这个目标是否很难识别。对这份数据集如果发布者用difficult标记了图像融合形成的缺陷你可以在转换时把它单独拎出来处理。看到这里就会明白VOC的标注是绝对像素坐标xmin、ymin是目标左上角在整张图里的像素位置xmax、ymax是右下角。模型训练并不直接用这个绝对值所以要转成相对坐标这就是下一章的核心转换。类别名以你实际解压后的XML为准上面示例里的overheat_defect只是演示。2.3 为什么这个数据集选VOC而不是COCO迁移成本最低同类的目标检测数据集常见的标签格式有VOC、COCO、YOLO三种。数据发布者选了VOC我认为是刻意的——这是迁移成本最低的选择。标注工具LabelImg默认导出就是VOCYOLOv5、YOLOv8、mmdetection、PaddleDetection几乎都提供或兼容VOC读入网上现成的VOC转YOLO脚本一大把。COCO的JSON格式虽然信息更丰富有segmentation、iscrowd、area这些扩展字段但输电线路过热检测要的是方形目标框不需要实例分割这些字段全是冗余。YOLO原生的txt格式虽然训练时最直接但它是归一化相对坐标人眼无法直接审阅不适合作为发布格式。说白了VOC是这个资源链条上最稳的中间格式兼容工具多、转换脚本成熟、出问题有迹可循。你在搜索引擎里看到的电力红外数据集 VOC YOLO大多也是这个链路——VOC格式发布再转YOLO去训练。如果哪个数据源直接给你COCO格式的电力红外数据反倒要先验证一下它的area字段是不是算对了因为红外图像的长宽比千差万别有些生成工具会把area算成0导致训练崩溃。3. 把VOC转成YOLO格式一份脚本把XML变成txt并自动划分训练集3.1 转换脚本边读XML边算归一化坐标YOLO训练用的标签是txt文件每行一个目标格式是类别id、归一化中心x、归一化中心y、归一化宽、归一化高。这里给一份可以直接跑的通用的VOC转YOLO脚本唯一的改动点是CLASSES列表要换成你自己数据集里的真实类别名import os import glob import xml.etree.ElementTree as ET # 改成你的实际类别名顺序一旦确定后不要再换 CLASSES [overheat_defect, fusion_defect] xml_dir Annotations label_dir yolo_labels os.makedirs(label_dir, exist_okTrue) def convert_xml(xml_path): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(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) # 防止标注越界YOLO对越界框会直接丢弃 xmin max(0.0, min(xmin, img_w)) xmax max(0.0, min(xmax, img_w)) ymin max(0.0, min(ymin, img_h)) ymax max(0.0, min(ymax, img_h)) if xmax xmin or ymax ymin: continue cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) return lines for xml_path in glob.glob(os.path.join(xml_dir, *.xml)): stem os.path.splitext(os.path.basename(xml_path))[0] lines convert_xml(xml_path) out_path os.path.join(label_dir, stem .txt) with open(out_path, w, encodingutf-8) as f: f.write(\n.join(lines)) print(f{stem}.txt: {len(lines)} objects)脚本的逻辑分四步解析XML拿图片宽高遍历每个object拿类别名和bndbox坐标把绝对像素坐标换算成0到1之间的归一化中心点和宽高按类别id 中心x 中心y 宽度 高度写入txt。换算公式就是VOC转YOLO的标准做法中心x等于左右边界的平均值除以图片宽宽度等于右边界减左边界再除以图片宽y和h同理。这里有个细节我先把坐标钳制在图像范围内再算归一化避免XML里出现xmax比图宽还大的脏数据。很多现成脚本没做这步训练时那些框会被底层库静默丢掉损失丢得莫名其妙。CLASSES列表是整个转换的命门。VOC里写的是字符串类名YOLO里用的是数字id这个列表的顺序就决定了最终每个类编号几。一旦开始训练这个顺序就不能改否则之前训练的模型权重对你的新标签序号是错位的。常见的合并需求——把真实缺陷和融合缺陷当成同一类——只需要把CLASSES改成单一列表脚本会自动把两个类名都映射到0但你的data.yaml只能用一行类别名。3.2 关键参数与边界问题类别顺序、坐标越界、空标签转换脚本跑完先别急着训练检查三件事。第一空标签文件。如果某张图没有任何有效目标生成的是0字节txt。YOLO训练时这种文件无害但会浪费一次前向更重要的是它往往意味着源XML里的difficult目标被过滤掉了你要确认这是有意为之。第二类别id和data.yaml的names顺序必须完全一致。第三原图分辨率。脚本用XML里的size字段做分母这是最可靠的做法。不要用cv2.imread去读图再取shape——红外伪彩色图的通道数可能是3也可能是4JPEG和PNG混在一起时shape会骗人而XML里记录的尺寸是标注者当初看到的以它为准。下面是一份配套的data.yaml注意names列表下标和CLASSES严格对应path: ./power_infrared_dataset train: train.txt val: val.txt names: 0: overheat_defect 1: fusion_defect如果你的发布者没给train.txt和val.txt常见做法是按8:2比例随机划分固定随机种子保证每次划分一致import random random.seed(42) files [os.path.splitext(os.path.basename(p))[0] for p in glob.glob(os.path.join(img_dir, *.jpg))] random.shuffle(files) split int(len(files) * 0.8) with open(train.txt, w) as f: f.write(\n.join(img_dir / name .jpg for name in files[:split])) with open(val.txt, w) as f: f.write(\n.join(img_dir / name .jpg for name in files[split:]))这个划分代码里img_dir是JPEGImages的路径train.txt里写的是图片的绝对路径或相对路径YOLO会根据data.yaml里的path字段拼出完整路径。划分比例没有标准答案2000多张图不算多我一般留15%~20%做验证集如果你的真实缺陷样本本来就不多可以在划分前先按类别统计一下确保验证集里每个类至少有几张。3.3 转换前后对照与首轮验证转换完拿出一张图做对照比什么都管用。已知XML里某个对象的坐标为xmin178、ymin205、xmax248、ymax265图片尺寸是640×480那转换后这一行应该是字段计算过程结果类别idCLASSES.index(overheat_defect)0中心x(178248)/2/6400.332812中心y(205265)/2/4800.489583宽度(248-178)/6400.109375高度(265-205)/4800.125000这张表可以当公式用。手算对不上说明脚本某处出了问题对得上再做一次可视化验证把txt里的框画回原图import cv2 img cv2.imread(JPEGImages/IMG_1023.jpg) h, w img.shape[:2] with open(yolo_labels/IMG_1023.txt) as f: for line in f: cid, cx, cy, bw, bh map(float, line.split()) 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, 0, 255), 2) cv2.putText(img, str(int(cid)), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imwrite(check_IMG_1023.jpg, img)这段代码把归一化坐标换算回像素坐标并画框。我习惯随机抽20张生成check图一眼就能看出框是不是在发热点上。这一步值5分钟能拦住大部分转换错误。4. 图像融合缺陷与真实缺陷训练前必须分清的两类样本4.1 融合缺陷是怎么生成的红外与可见光的像素级叠加这组数据集特殊的地方在标题里已经说透了过热缺陷包含图像融合形成的缺陷和真实缺陷。真实缺陷好理解就是热像仪在现场实际拍到、标注者确认过的发热点。融合缺陷本质上是数据增强的产物它的生成逻辑一般是这样的红外热像仪分辨率低常见的是320×240或者640×512而配套的可见光相机分辨率高得多两者帧率、视角、畸变都不同。生成融合缺陷时先对红外图和可见光图做配准把可见光的高频纹理映射到红外空间再把目标区域的温度灰度做增强处理让一个原本不明显的区域变成明显的高温区或者把两幅图中的缺陷区域按一定权重叠加起来。这个过程和红外可见光图像融合是一个技术方向。融合出来的图看起来像真实场景但细节上已经留了痕迹。作为标注者你框的是一张人工合成的图缺陷边缘往往过于锐利背景纹理和真实红外图不一致甚至会在缺陷周围留下亮度截断的伪影。这些差异平时一眼扫过去看不出来但在训练目标检测模型时会被放大——模型会去学那些伪影特征而不是真正的高温形态。4.2 两类缺陷在分布上的差异边缘锐度、背景纹理、温度梯度我把两类缺陷在图像层面的差异整理成一张表训练前最好照着这张表检查一遍你的数据维度真实缺陷融合缺陷边缘形态过渡自然有温度梯度缓变带边界锐利常带人工伪影背景纹理真实杆塔、导线、天空的噪声纹理可见光纹理叠加后的二次纹理偏干净灰度分布缺陷中心亮向外衰减局部可能出现过曝式的平台区缺陷位置集中在耐张线夹、引流板、接续管、绝缘子位置跟随合成区域有时脱离真实结构与环境的相对温差通常有物理意义可用相对温差验证温差是人为设定的不代表真实发热这几行差异直接影响模型行为。如果训练集里融合缺陷占多数模型很容易学到边缘锐利、对比强烈这类特征。真到了现场阳光直射下的金属塔材同样有锐利边缘和强对比模型就会把阳光反射当成过热缺陷检出来这是误检的重灾区。反过来如果只用真实缺陷训融合缺陷可能几乎检不出因为模型没见过那种灰度模式。所以拿到这份数据集先统计两类缺陷各有多少个框心里有底再谈训练策略。4.3 训练策略建议两套标签还是混合训练我的经验是分三种场景处理不要一股脑混合训练。第一种目标是做现场真实巡检。这时以真实缺陷为主训练集融合缺陷只做辅助。一个落地效果好又简单的办法是先让模型在全部数据上出个初始模型再用真实缺陷的子集微调几十个epoch。这样模型先学到大致的目标形态再用真实缺陷把分布校准回来收敛比直接只用真实缺陷训要稳。第二种研究融合方法本身比如你在做红外可见光图像融合的算法评测。这时要按difficult字段把融合缺陷单独划出来测看模型在合成数据上的上限。融合缺陷数量多、标注稳定适合做消融实验但得在报告中说明这是合成样本。第三种两类缺陷合并成一个类别。如果业务只关心哪里过热而不关心缺陷来源直接在CLASSES里把它们映射成同一个id。代价是模型会同时学习两种分布评估时单个类的AP会下降一点但部署简单。我一般会同时保留两个版本的配置一个二分类版本做分析一个单类版本做部署。训练程序不会告诉你该选哪个这个决策得由你想要的应用场景来定。5. 避坑与常见问题标注质量、类别不平衡与光照干扰5.1 标注框偏移发热点中心与可见光边缘对不齐现象训练出来的模型检测框整体比实际发热区域偏左或偏上mAP看着不低但部署到现场画框时框总是漂在发热点旁边。原因VOC里的bndbox是标注者根据融合后的图框的图像融合配准本身存在几个像素的误差。红外图分辨率低可见光图分辨率高映射到同一坐标系时边缘本来就对不齐。标注者要是严格照着可见光边缘框框就会和目标实际热区错开。这类误差在训练集里是系统性偏差模型学到的就是这个偏移量。解决先在验证集上统计偏移方向把预测框中心减去标注框中心看平均偏移矢量。如果往右偏了两个像素推理时把预测框整体反向平移补偿还要在训练时给每个框做轻微膨胀——把xmin、ymin向外放几像素、xmax、ymax也向外放几像素让模型不再死抠那个不一致的边缘。处理完再做一轮验证框的实际视觉贴合度比mAP数字重要得多。5.2 类别不平衡真实过热缺陷占比少召回率上不去现象训练loss下降正常但看每类AP时真实缺陷的recall明显低于融合缺陷。把输出置信度阈值调到0.25检出一堆融合缺陷真实缺陷却漏了不少。原因数据集的构建方式决定了这种不平衡——融合缺陷生成成本低可以批量合成真实缺陷要靠外场巡检积累一张是一张。用2000多张图融合缺陷的标注数量可能是真实缺陷的几倍。模型在样本量大的类别上拟合得更充分天然倾向把不确定区域判成多数类。解决三个手段配合。先把真实缺陷类在损失函数里的权重提高YOLOv8里可以给类别设置group或者自己改loss最简单的是用数据加载器里的过采样——复制真实缺陷样本让它多进几次训练。再把融合缺陷的difficult样本剔除一部分它们本来就带模糊标注留着只会稀释注意力。最后如果真实缺陷确实只有一两百个框别指望一个单模型解决所有场景接受真实缺陷初筛人工复核的定位。5.3 阳光反射与背景散热造成误检现象验证时发现大量误检集中在金属塔材、导线下方的高亮区域这些位置没有发热缺陷但检测器给它们打了很高的置信度。尤其是中午拍摄的样本误检率比早晚高出一截。原因红外图是灰度增强的伪彩色图阳光照射下的金属表面温度升高在图像上的亮度和真实发热缺陷几乎一样。模型没有物理知识它只会学灰度模式。融合缺陷又加剧了这个问题——合成缺陷的边缘锐利特征和金属反光边缘很像。解决一手治数据一手治物理先验。数据层面在训练集里加一些无缺陷的背景红外图不画标签让负样本回归正常预处理时不要对红外灰度图做全局直方图均衡那会把背景噪声一起放大。物理先验层面在推理后的后处理里加一条规则只保留位于连接金具、线夹、引流板这类已知易发热部件区域内的检测框对背景天空和塔身反射区域直接滤掉。这条规则用y坐标和部件位置约束就能实现成本极低却能把误检率砍掉一大块。5.4 拍摄距离与发射率设置导致的温差漂移现象同一个发热点在距离10米和30米拍的样本里框的大小和灰度分布差异很大。模型在近距离样本上准远距离样本上漏检多。原因红外热像仪测的是辐射温度受发射率、环境温度、拍摄距离共同影响。不同巡检批次里热像仪设定的发射率不同画面整体亮度就不同距离远了缺陷在图像里只有几个像素标注时人眼都容易忽略标签自然不稳定。解决训练前对标注框做一次面积统计把宽、高小于图像尺寸2%的框筛出来看一遍这种小目标框本身标注噪声大要么补标要么删除。训练时给这类小目标加专门的增强Mosaic和自动增强对红外小目标很有用。部署阶段固定采集条件统一发射率参数、统一拍摄距离区间不要让模型去适应一个发散的输入分布。这个坑看起来不如误检严重但它在现场输出的是漏报而不是误报造成的损失完全不同。6. 进阶验证用YOLOv8把这份数据集跑通并输出热力图可视化6.1 数据配置与训练命令转换完成、检查无误后YOLOv8是上手最快的验证框架。data.yaml沿用第三章那份训练用nano权重起步先跑通流程再谈精度yolo detect train datapower_infrared.yaml modelyolov8n.pt epochs100 imgsz640 batch16 yolo detect val datapower_infrared.yaml modelruns/detect/train/weights/best.pt第一条命令训练第二条在验证集上评测。epochs从100起步2000多张图在这个量级下100轮足够看趋势。imgsz用640红外图本身分辨率不高用更大的输入只会增加显存压力而不会带来明显精度提升。6.2 看混淆矩阵不只看mAP训练结束后去runs/detect/train下看混淆矩阵图和大图预测结果。重点看真实缺陷和融合缺陷在混淆矩阵里的互相污染程度——如果两者经常互相混淆说明你的类别设计有问题应该考虑合并成单类。如果混淆集中在背景类说明负样本不够回到5.3去补背景图。这一步能回答这个数据集值不值得用看单类AP真实缺陷AP在0.7以上就值得继续投入。6.3 把检测结果叠加到红外原图做人工巡检最后养成一个习惯把验证集预测结果里置信度最高的50张图和最低的50张图都翻一遍。置信度高的图如果框得准说明模型学到了有效特征置信度最高的图居然框错那一定是数据分布出了问题别急着调参。多模态和伪彩色红外图导出时注意用原始灰度图做底图再叠加伪彩色避免二次压缩带来颜色失真。我从那以后每次拿到电力红外数据集都强制先走一遍标签可视化巡检——随机抽50张把每张图的标注框画上去人眼过一遍再进训练流程。这个习惯帮我拦下了至少三次标注错位的翻车也让我对数据集的真实质量有了直接判断。这份数据集把真实缺陷和融合缺陷放在一起其实是在提醒所有使用者数据集的坑往往不在算法里而在你开始训练之前。希望帮到你。本文还有配套的精品资源点击获取
返回列表