简介:针对电力场景电气设备检测需求,提供一份红外图像变压器检测数据集说明文档,主要面向电力设备缺陷识别、目标检测模型训练的研究人员与工程师。文档围绕4271张红外图像数据集,详细说明其同时采用Pascal VOC与YOLO两种标注格式,每张图片均配有对应xml和txt标注文件,并整理出14个类别(含ACB空气断路器、CT电流互感器、LA避雷器、LBS负荷开关、PT电压互感器、VCB真空断路器及Connection等)的标注含义与数量分布,例如Connection类框数3961、MCCB类框数1600、core类框数699,可帮助读者快速评估类别样本均衡性,判断数据规模是否适配自身变压器检测任务。整个资源仅1个docx文档,大小约1006KB,目前已有101人浏览学习。借助该文档,读者可清晰了解数据集格式规则、labelImg画框流程以及原始数据下载地址,为后续获取图像并训练检测模型提供明确指引。
1. 红外变压器检测数据集:它到底是什么,解决了什么
拿到一份名为“电力场景电气设备红外图像变压器检测数据集VOC+YOLO格式4271张14类别”的数据集,第一反应不是高兴,而是先想清楚它到底能不能直接拿来用。做过电力巡检算法的人都知道,可见光下的变压器检测早就有了成熟方案,真正难啃的是红外图像——对比度低、噪声重、目标边界模糊,同一个变压器在不同负载和天气下拍出来完全是两幅面孔。这份数据集把“电力场景”“红外图像”“变压器检测”三个关键词绑在一起,本质上是在解决一个现实问题:想训练一个能在红外画面里稳定找出变压器各组件的检测模型,但手里没有像样的标注数据。
4271张、14个类别、同时提供VOC和YOLO两种标注格式,这几个数字说明它不是随手整理的小样本,而是冲着实际训练去准备的。适合谁?两类人。一类是刚接触电力设备检测的开发者,想在真实红外数据上跑通YOLO训练链路;另一类是已经在做巡检系统的人,手里有自己拍的红外视频,缺的是一个可靠的训练起点。这篇文章不打算夸这份数据有多好,而是把它拆开看:每种格式怎么用、转换脚本怎么写、训练时哪些参数要动、哪些坑会让你白跑一夜。
2. 从标题拆数据:4271张红外图与14类标注,先弄清能拿来做什么
2.1 红外图像和可见光图像差在哪:决定了模型怎么迁、增强怎么配
同样一个变压器,可见光照片里套管是白色的瓷瓶,散热器是银灰色的金属片,轮廓靠颜色和纹理区分;红外图像里这些部件全变成了灰度或伪彩色块,区分依据从“颜色”变成了“温度”。发热的部位亮,不发热的部位暗,而温度分布会随负载、风速、太阳辐照、拍摄距离变化,同一个设备白天和晚上拍出来的红外图,灰度分布能差出好几个量级。
这对检测模型的影响是直接的。用ImageNet预训练权重做迁移学习时,模型前几层学到的彩色纹理特征在红外图像上基本失效,因为红外图本质上是单通道热辐射分布,哪怕存成三通道伪彩色JPG,三个通道之间也不是可见光那样的独立光谱信息。所以拿到这份数据集后的第一个意识应该是:不能把它当成普通RGB检测任务来处理,输入预处理和增强策略都要围绕“灰度分布大跨度变化”来设计。
另一个容易被忽略的点是红外的“边缘软化”。可见光图像里部件边缘是锐利的,红外图像由于热扩散和传感器分辨率限制,边缘往往是逐渐过渡的。检测框稍微偏一点,在可见光数据集里可能只是IoU下降,在红外数据集里会让置信度直接从0.9掉到0.3。这也是为什么很多在VOC或COCO上效果很好的检测配置,搬到红外数据上第一轮训练结果很难看。
2.2 14类别的组织逻辑:参考的组件划分和一张图的标注长什么样
14个类别,从电力设备的组件粒度来看,常见的数据集会围绕变压器的关键部件做标注。我按自己做过项目的习惯,整理一份参考的类别划分逻辑,具体以数据自带的label说明为准:变压器本体、高压套管、油枕、散热器、油箱、分接开关、绝缘子、母线连接头、避雷器、呼吸器、端子盒、接地引下线、电流互感器、红外热缺陷。前13类是可检测的设备部件类别,最后这一类的存在意味着数据里可能包含了过热缺陷样本,检测出它在巡检场景里的价值比单纯识别设备要高。
一张红外图上标注什么样,本质上和可见光检测的标注格式一致,每个目标一个矩形框,框住目标在画面里的位置。区别在于框边界的判定:红外图里目标边缘过渡带很宽,有的标注会把过渡带算进框里,有的只框核心高温区域。这直接影响训练出来的框紧不紧。我拿到这类数据集的第一件事就是随机抽100张图,把标注框可视化出来看一遍,看看整体框的松紧程度是否一致。如果一半框贴着目标边缘、一半框外边沿还有一大圈模糊区域,说明标注人员之间存在主观差异,这种数据集直接训练会导致边界框回归不稳定。
另一个值得关注的是分辨率和拍摄角度。4271张图的来源不同,有些可能是无人机正拍视角、有些是手持红外仪斜拍,目标在画面里的比例从大到小分布很广。小目标多不多,决定了要不要在训练时专门开高分辨率输入或加小目标检测层。手段是做一个宽高比和目标面积统计,把每张图的标注框面积除以整图面积,看分布情况。如果大量目标面积占比不到1%,那训练时输入尺寸就不能给得太小。
2.3 拿到这份数据先做的三件事:清单核对、脏数据抽检、类别统计
不要急着转换格式或开训练,先花半小时做三件事,能省掉后面几天的排查时间。
第一件事,核对文件结构。正常来说数据目录下会有JPEGImages存放图片、Annotations存放XML标注或labels存放TXT标注、还有一个类别列表文件。要确认三件事:图片数量是否与声明一致、每张图片是否有对应的标注文件、是否存在空标注图片(有图无标注文件)。命令行里可以快速过一遍:
ls images/ | wc -l && ls labels/ 2>/dev/null | wc -l # 对比两个目录下的文件数,再逐个找没有标注对应的图片 for img in images/*.jpg; do name=$(basename "$img" .jpg) if [ ! -f "labels/$name.txt" ]; then echo "missing: $name"; fi done这段脚本用最基础的bash完成核对:第一个命令分别统计图片和标注文件数量;循环语句遍历所有图片,检查同名标注文件是否存在。如果出现大量missing输出,说明数据有掉标注的情况,训练前必须补齐或过滤,否则模型会把这些图片当成负样本学习,造成漏检。
第二件事,类别统计。用一段简单的Python读取所有标注文件,统计每个类别出现的次数和包含该类别的图片数。这一步能暴露出类别失衡问题——比如“变压器本体”出现2000次,而“呼吸器”只出现50次,训练时呼吸器几乎学不出来,需要额外做类别权重或复制增强。
第三件事,脏数据抽检。红外图里经常混入可见光图、手机拍的屏幕照片、或者机器过热保护前的白噪图。我的习惯是每类别抽10张图出来直接看一眼,确认图像质量和标注框位置是否大致合理。这一步没有任何命令技巧,纯粹靠经验和耐心。
3. VOC和YOLO双格式落地:格式差异、转换脚本与4个边界问题
3.1 VOC的XML和YOLO的TXT差在哪:坐标系与文件组织的两处关键不同
VOC格式的标注是以XML文件为单位存储的,一个XML对应一张图片,文件里记录了图片尺寸、来源、目标列表;每个目标对象有name类别名和bndbox边界框,边界框的坐标是像素值,并且是绝对值坐标。
YOLO格式的标注就简单得多:一张图片对应一个同名TXT文件,TXT里每一行是一行文本,格式为“类别编号 x_center y_center width height”,其中中心点坐标和宽高都是归一化到0到1之间的相对值。类别编号按类别列表顺序从0开始计数,不是直接用类别名。这是两种格式之间最本质的差别——一个是绝对像素坐标加类名字符串,一个是归一化相对坐标加数字编号。格式转换的核心工作就是把XML里的绝对坐标算成归一化坐标,并把类名映射成编号。
第二个差别在文件组织。VOC格式通常还伴随一个类别名单或者按照固定目录结构存放,YOLO格式则只关心每张图旁边放一个同名TXT,以及一个train.txt/val.txt列表文件,列表里每一行是图片的绝对路径。YOLO训练时读取列表文件找到图片,再按同名规则去找TXT标注,缺一个就跳过或报错。
3.2 把VOC转成YOLO:一个能直接跑的Python脚本
转换脚本不难写,我用的版本长这样。脚本读取VOC的XML目录和一个classes列表,输出YOLO格式的TXT到指定目录。
import xml.etree.ElementTree as ET import os from pathlib import Path def voc_to_yolo(xml_dir, classes_file, output_dir, img_width, img_height): # 读取类别列表,按行映射成编号 with open(classes_file, 'r') as f: classes = [line.strip() for line in f.readlines()] class_to_id = {name: idx for idx, name in enumerate(classes)} os.makedirs(output_dir, exist_ok=True) for xml_file in Path(xml_dir).glob('*.xml'): tree = ET.parse(xml_file) root = tree.getroot() # 优先用XML里记录的图片宽高,避免外部传参错误 size = root.find('size') if size is not None: img_width = int(size.find('width').text) img_height = int(size.find('height').text) txt_name = xml_file.stem + '.txt' with open(os.path.join(output_dir, txt_name), 'w') as out: for obj in root.findall('object'): name = obj.find('name').text if name not in class_to_id: continue # 类别不在列表里就跳过 bnd = obj.find('bndbox') xmin = float(bnd.find('xmin').text) ymin = float(bnd.find('ymin').text) xmax = float(bnd.find('xmax').text) ymax = float(bnd.find('ymax').text) # 归一化,并保证中心点和宽高不为负 x_center = ((xmin + xmax) / 2) / img_width y_center = ((ymin + ymax) / 2) / img_height w = (xmax - xmin) / img_width h = (ymax - ymin) / img_height out.write(f"{class_to_id[name]} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}\n")Python标准库的ElementTree足够完成解析,不需要装额外包。class_to_id把类别名映射成从0开始的编号;size节点优先读取XML里记录的图片尺寸来做归一化;坐标计算公式就是中心点等于(xmin+xmax)除以2再除以宽度,宽等于xmax减xmin再除以宽度。.6f保留六位小数,精度足够,写太多位反而让文件变大。
运行命令行示例:
python voc_to_yolo.py --xml_dir ./Annotations --classes_file ./classes.txt --output_dir ./labels3.3 转换脚本背后4个容易翻车的边界
第一个坑是类别列表顺序前后不一致。VOC里用的是类别名字符串,YOLO用编号,如果训练时用的classes.txt和转换时用的不是同一份,编号错位会导致模型学的是“套管”但预测出来是“油枕”。解决方法是把转换时用的classes.txt固化到数据目录里,训练前再次核对。
第二个坑是XML的size节点缺失或写错。有的数据集的标注是从标注工具导出的,size节点可能缺失或与实际图片尺寸不符,这时转换脚本会使用外部传参,一旦传参错误,整张图的标注框位置全部偏移。我的做法是转换后随机挑几张图叠加可视化,而不是依赖睁眼检查。
第三个坑是坐标裁剪。正常情况下xmin和xmax都在图片范围内,但有些标注工具或人工标注会把框拉出图片边界,导致归一化后w或h超过1,YOLO训练时直接报错。转换脚本里建议加一句:
xmin = max(0, min(xmin, img_width - 1)) xmax = max(0, min(xmax, img_width - 1))把坐标限制在有效范围内再算中心点和宽高。这样做的代价是边界框略微收缩,但至少训练不会中断,比捂着报错强。
第四个坑是重复类别编号。14个类别,有的数据可能包含一个“unknown”或“other”类别,占一个编号但实际样本很少。如果转换时保留它,训练中会一直学不好,还会抢占一个输出通道。我的做法是把这类样本直接过滤掉,只保留有实际意义的类别。
3.4 反向转换YOLO到VOC:什么时候需要,简化做法
反过来的需求也存在。比如想在mmdetection这种只支持VOC或COCO的框架里做对比实验,或者想把这份数据集合并进自己原有的VOC格式数据里。反向转换的核心是逆运算:把归一化的中心点坐标乘回图片尺寸,算出xmin、ymin、xmax、ymax,同时把类别编号映射回类名字符串。
最常见的问题是TXT标注里不包含图片宽高信息,反向转换时必须传入图片尺寸。可以读取图片文件本身拿到尺寸,这样最稳妥:
from PIL import Image img = Image.open(img_path) w, h = img.size如果数据里有大量图像已经被resize过但标注没同步更新,反向转换会把错误坐标直接写进XML。后续做数据合并或重新标注时不要盲目拼接,先对原图片和标注做一次Mosaic可视化检查再合并。
4. 用这份红外数据训YOLO:数据划分、预处理与关键参数怎么给
4.1 避免同一设备两头进:按设备划分train/val/test
很多人在划分数据集时直接train_test_split按文件随机分割,这是红外检测里最大的隐患。原因在于,同一个变压器的不同拍摄角度、不同时间的多张图,理论上存在强相关性。如果同一个设备的图同时出现在训练集和验证集里,模型相当于提前见过了答案,验证集Loss会失真,等真正部署到新的巡检点位时性能掉得让人看不懂。
按设备划分的做法是先看文件名是否包含设备编号或拍摄批次前缀。我处理这类数据的习惯是先用下划线切分文件名的第一段作为设备标识,然后按设备去重划分:
import random from pathlib import Path img_files = list(Path("./images").glob("*.jpg")) device_ids = set() for f in img_files: # 假设文件命名是 device_id_xxx.jpg,取第一段作为设备标识 did = f.stem.split("_")[0] device_ids.add(did) device_list = list(device_ids) random.shuffle(device_list) # 按 7:1.5:1.5 切分设备,并写回图片路径列表 train_count = int(len(device_list) * 0.7) val_count = int(len(device_list) * 0.15) train_devices = set(device_list[:train_count]) val_devices = set(device_list[train_count:train_count + val_count]) test_devices = set(device_list[train_count + val_count:]) for split, devs in [("train", train_devices), ("val", val_devices), ("test", test_devices)]: with open(f"{split}.txt", "w") as out: for f in img_files: if f.stem.split("_")[0] in devs: out.write(str(f.resolve()) + "\n")这里的关键是把设备ID先拆出来,再对设备集合做随机切分,最后回写图片路径。如果不确定文件名里的设备标识规则,先输出前20个file stem确认一下再写划分逻辑。宁可在划分上多花十分钟,也不要在训练结束后发现验证集不可信。
4.2 红外图的预处理顺序:灰度归一化、CLAHE与增强策略
红外图像建议按这个顺序做预处理。第一步,如果是三通道伪彩色JPG,转成单通道灰度图——直接用cv2读图再取灰度,或者按原图的温度色卡映射关系加权转灰度。伪彩色到灰度的映射没有统一公式,最稳妥的做法是先转成灰度图跑一遍基线,对比一下转灰度前后的mAP差异再决定用哪个。第二步,做直方图均衡化或CLAHE(对比度受限的自适应直方图均衡化)。红外图的灰度分布往往集中在狭窄的温度区间,直接训练会让模型区分度不够,CLAHE能增强局部对比度。第三步,归一化到0到1。YOLO系列对输入有内置归一化,但如果你用自己写的预处理管线,这一步不能省。
import cv2 img = cv2.imread("infrared.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # clipLimit 控制对比度增强幅度,数值越大增强越强;tileGridSize 是局部区域大小 clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) enhanced = clahe.apply(gray)clipLimit=2.0是常见的起点值,红外图上太小的值几乎看不出效果,太大的值会把噪声一并放大。训练时如果需要三通道输入,就把增强后的灰度图复制三个通道,而不是直接把原伪彩色图丢进网络。
训练时的数据增强,我一般会关闭色彩类增强的激进程度,因为红外图的色彩扰动没有意义。重点开几何增强:随机旋转10度、随机平移0.1、随机缩放0.3,以及Mosaic拼接。Mosaic在红外小目标场景下特别有用,能把不同温度背景下的小目标拼在一起,增加模型对温度跨度的适应力。但要注意Mosaic比例不要设到1.0,建议0.5到0.7之间,留一部分原图让模型稳定学习真实背景分布。
4.3 训练参数建议:从batch、lr到epochs怎么设第一版
以YOLOv8为例,我给的基线参数表如下,别的版本大同小异。这些参数不是极限调优状态,但能在绝大多数单卡环境下跑出可用的基线,然后你再根据验证集结果去拧参数。
| 参数 | 建议值 | 说明 |
|---|---|---|
| imgsz | 640 | 确认小目标占比高再考虑升到960 |
| batch | 16 | 单卡显存不够就降到8,不要硬撑 |
| epochs | 200 | 红外收敛慢,100个epoch不够看趋势 |
| lr0 | 0.01 | 用AdamW时可降到0.001 |
| lrf | 0.01 | 余弦退火末端学习率 |
| mosaic | 0.7 | 红外场景适合高Mosaic比例 |
| scale | 0.5 | 允许目标缩放到0.5到1.5倍 |
| fliplr | 0.5 | 水平翻转,红外图可安全使用 |
| degrees | 10 | 角度扰动不宜太大,红外拍摄角度本来就规范 |
| freeze | 10 | 冻结骨干前10层,能加速收敛并缓解红外RGB差异 |
训练命令是YOLO长项,不需要重复太多,关键是理解上面几个参数为什么这么给。imgsz直接影响小目标检出的上限,但显存代价翻倍,先跑640版本的基线比直接上960更划算。epochs给200是因为红外数据的有效信息密度低,前期loss下降很快,后期需要更多epochs来收敛边界回归。freeze参数我建议保留,因为从头开始训练骨干层学到的红外纹理特征可能还不如迁移的RGB特征有用,冻结一层一层解冻是常见做法。
还有一点容易被忽略:类别失衡时可以在训练配置里开cls权重或手动给类别加loss权重。如果统计发现“呼吸器”只有几十个样本,而“变压器本体”有一千多个,模型会倾向于把不确定的目标预测成高频类别。先加权重再考虑要不要合并小类别。
5. 红外变压器检测训练避坑:5个现象、原因和解决办法
5.1 现象一:模型把母线误检成套管
训练出来的模型在测试图上频繁把母线的连接处框成套管,置信度还不低。这个现象在红外场景里很常见,因为母线和套管在可见光下差异明显,但在红外图里都是高温亮区域,形状也接近长条状或椭圆状。模型看到的是灰度纹理,不是颜色信息,两个类别在特征空间里严重重叠。
排查方式是把两类样本单独拿出来看它们在特征层的分布,或者简单一点:统计标注框的宽高比。如果“套管”类别的框宽高比集中在某个区间,而“母线”类别的宽高比也有大量落进这个区间,说明标注本身区分度不足。解决路径有两个:一是检查标注边界是否准确,红外图里母线连接处经常和套管重叠,标注边界模糊导致模型学混;二是增加被误判区域的负样本或让模型看到更多“母线连接但不属于套管”的上下文。实在不行就把两类的RoI裁剪区域放到tensorboard里对比,人工确认是否真的可分。
5.2 现象二:验证集mAP不错,实拍画面却大面积漏检
这是最让人头疼的情况,训练时mAP有0.85,拉到现场实测一台设备直接漏掉一半目标。先别怀疑模型,先怀疑数据分布不一致。验证集来自同样的拍摄设备、同样的距离、同样的天气条件,而实拍画面是不同时段、不同负载状态下的红外图,灰度分布完全不同。模型学到的是训练集的温度分布模式,换个环境就不认了。
解决思路分两路。一路是数据增强里加灰度扰动,把训练图的灰度值随机拉伸或压缩,模拟不同环境下的温度分布变化;另一路是收集现场负例加入训练集,不需要完整标注,把没有目标的背景图作为负样本放进去,让模型学会区分“有目标的分布”和“没有目标的分布”。从工程角度看,当场采集50张现场红外图、粗略标注框一次,往往比在办公室调一周参数管用。
5.3 现象三:转换后的标注框在图上明显偏移
训练前可视化检查发现,转换出来的TXT框在图上偏了一大截,看起来像整体平移或缩放比例不对。这个问题的绝大多数原因是转换脚本使用了错误的图片尺寸。比如XML里记录的width和height是原图的,但实际网络训练读入的是resize后的图,两者不一致。
另一个隐蔽原因是图片的EXIF旋转信息。手机或某些红外仪拍摄的照片带有旋转方向标记,OpenCV默认忽略EXIF,直接按原始像素读图,而标注工具按旋转后的方向标注。结果是图片显示方向和标注坐标方向不一致,框全部偏转。解决方法是读图后统一按IMREAD_IGNORE_ORIENTATION处理,或者预处理脚本里应用旋转后保存。这个坑不遇到一次不会长记性,遇到之后我每次拿到新数据集第一件事就是跑一遍可视化。
5.4 现象四:14个类别里有几个始终检测不出来
某个小类别在训练200个epoch后依旧Recall接近0。最常见的原因是样本数量太少,在总体里占比不到3%,模型把它的特征当成噪声忽略了。我遇到过“呼吸器”类别只有不到100个目标,而“散热器”类别有3000多个目标。类别失衡到这种程度,任何常规训练都调不出来。
处理办法按优先级排序:第一,先用类别权重把Loss里小类的梯度放大;第二,对小类样本做复制粘贴增强——把小类目标抠出来随机贴到其他红外图的合理位置上,这样既增加数量又保留真实纹理;第三,合并类别,把这个小类和它容易混淆的邻近类别合并成一个类,先保证整体检测能力,后续再细分;第四,做两阶段检测,先用一个通用检测器找到变压器区域,再在小图上专门训练一个分类或检测模型处理细分类别。直接训练单模型试图同时学好14类,不是不可能,但代价高,投入产出比并不好。
5.5 现象五:直接用可见光预训练权重,训练loss压不下去
红外图从头训练loss还是有玄学成分的,但“loss压不下去”更多是输入分布不匹配。红外图转灰度后直接作为三通道输入,和ImageNet预训练模型期望的RGB分布差距很大。模型前几层的统计数据完全失效,训练自然不稳定。
我的做法是三选一:一是把灰度图复制三个通道,但不做任何额外的通道扰动,训练时减小初始学习率;二是用ImageNet预训练权重,但冻结前10层,只训练深层和检测头;三是用可见光数据先做一个域自适应预训练,把红外图映射到接近可见光的特征空间后再进入检测任务。实际操作中选项二最省事,大多数场景下足够稳定。如果loss在训练初期就出现大范围震荡,先降lr0到0.001,不要先动模型结构。
6. 交付前的最后一步:用可视化脚本把标注和预测框画回图上
6.1 标注可视化脚本只用OpenCV就够了
训练前检查标注、训练后检查预测,都需要把框画回图上。不要指望肉眼对着TXT文件检查,坐标那串数字看十遍也看不出偏移。我习惯用一个不到三十行的脚本解决所有可视化需求:
import cv2 import numpy as np def draw_yolo_boxes(image_path, label_path, class_names, output_path): img = cv2.imread(image_path) h, w = img.shape[:2] colors = np.random.randint(0, 255, (len(class_names), 3), dtype=np.uint8) with open(label_path, 'r') as f: for line in f.readlines(): parts = line.strip().split() cls_id, x_c, y_c, bw, bh = int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) # 反归一化回像素坐标 x1 = int((x_c - bw / 2) * w) y1 = int((y_c - bh / 2) * h) x2 = int((x_c + bw / 2) * w) y2 = int((y_c + bh / 2) * h) color = tuple(int(c) for c in colors[cls_id]) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, class_names[cls_id], (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1, cv2.LINE_AA) cv2.imwrite(output_path, img)核心逻辑是反归一化:中心点坐标乘回图片宽高得到像素坐标,再算出左上角和右下角。colors按类别生成一组随机颜色,保证不同类别用不同颜色区分。跑完之后把输出图片按类别分目录存放,一眼就能看出哪个类别的框偏了、漏了、画多了。
6.2 我的检查习惯
训练前检查一遍训练集,训练后检查验证集的预测输出,这是两次独立检查,缺一不可。训练前主要看标注框的贴合度和坐标方向,训练后主要看误检和漏检的分布规律。检查样本量不用多,每类别随机抽50张就够覆盖大多数标注问题。
还有一个我踩过的坑:可视化脚本和图的角度用了不同的坐标系,导致在脚本里看完没问题,部署时发现框是准的。现在我的习惯是可视化时同时把图像宽高打印在图片左上角,核对是否和标注时一致。一个方向错了,后面所有调整全是徒劳。
另外一个实用的习惯:第一轮训练结束后,把验证集预测结果中置信度0.5到0.9之间的样本单独筛选出来输出,这一批是“模型自己都没把握”的样本,往往能看出数据标注问题或类别混淆问题。比只看Best模型的mAP有用得多。这个筛选脚本不用改网络,只需要在预测导出时同时保存置信度并做一次排序过滤。
最后一个建议,像红外检测这种数据集来源多样、类别组织各异的方向,任何时候拿到一份新数据集,先复现一次完整链路——格式转换、可视化、训练、再可视化——确认没有意外之后,再投入时间去调优。这个流程跑一遍就能看出数据集是认真整理的还是赶工拼凑的,也能决定你的时间应该花在调参数还是在补数据上。希望帮到你。
本文还有配套的精品资源,点击获取