简介:面向变电站设备状态监测的红外图像数据集包含889张现场拍摄的电压电流互感器红外图像,供电力运维人员、计算机视觉研究者及深度学习入门者训练与评估模型,用于监测互感器运行状态、预警过热故障。资源整体共1778个文件,包括889张JPG原始红外图像和889个XML标注文件,压缩后仅24.72MB;标注采用VOC格式,每张图像都配有像素级语义分割结果,电流互感器(TC)共标注516个,电压互感器(TP)共标注650个,类别区分明确,可直接用于目标检测、实例分割等任务。利用红外图像中的温度分布可开展设备热分析、老化预测,也可基于这些标注训练YOLO、Faster R-CNN等目标检测算法,或通过CNN实现互感器分类与异常检测。目前已有2083人学习下载,适合作为电力场景深度学习实验、毕业设计或智能运维算法验证的标准数据集。
1. 变电站红外图像数据集:889张VOC标注能省下两天标注时间,但坑也不少
做变电站设备目标检测的人多半有过这种经历:可见光数据集一抓一大把,红外图像却总在“带标注”这一步卡住。变电站红外巡检图看似平淡——灰蒙蒙的画面里,设备轮廓模糊,温度分布代替了纹理细节,最麻烦的是电压互感器(PT)和电流互感器(CT)在红外下长得几乎一样,标错一次类别,模型就跟着学歪。这份变电站红外图像数据集一共889张,带VOC格式的XML标签,覆盖常见的PT与CT设备,正好解决“有图没标注”的尴尬。适合两类人:刚接触红外目标检测、想拿真实数据练手的新手,以及手头有巡检需求、想快速验证算法或小规模训练的工程师。不过说实话,我第一次用它跑YOLO时也踩了不少坑,这篇文章就把数据链路、格式转换和训练排错一次说清楚。
2. VOC标签先拆明白:XML结构、边界框坐标与PT/CT标注规则
2.1 VOC标注不是“画个框”那么简朴:XML字段逐个拆解
VOC格式全称是PASCAL VOC,核心是每张图像对应一个同名的XML文件,目标信息全部写在XML里。打开一个标注文件,结构大致长这样:
<annotation> <folder>JPEGImages</folder> <filename>infrared_0001.jpg</filename> <size> <width>640</width> <height>512</height> <depth>3</depth> </size> <object> <name>current_transformer</name> <difficult>0</difficult> <bndbox> <xmin>120</xmin> <ymin>89</ymin> <xmax>286</xmax> <ymax>241</ymax> </bndbox> </object> </annotation>这里最要紧的字段是size和bndbox。size里记录的是原始图像的宽、高、通道数,后面做归一化转换时要靠它做分母;bndbox给的是左上角坐标(xmin, ymin)和右下角坐标(xmax, ymax),也就是大家常说的 xyxy 格式。这和COCO格式的 [x, y, width, height] 不一样,和YOLO的归一化中心点格式也不一样,转换时稍不注意就会把 xyxy 当成 xywh 直接用,结果框全部偏移,这是最常见的翻车点之一。
VOC标注字段还包含truncated(目标是否被截断)和difficult(目标是否难以识别)等可选字段。在电力设备场景里,图像边缘的设备经常被截断,truncated字段就是干这个用的。处理的时候建议保留difficult标记,训练时可以把difficult=1的样本过滤掉,否则验证集的 mAP 会被这些“争议框”拖低。下面这张表是处理时最常碰到的字段:
| 字段 | 含义 | 处理建议 |
|---|---|---|
| filename | 图像文件名 | 转换输出文件名时依赖它 |
| size/width, height | 原始图像尺寸 | 归一化分母,必须以它为准 |
| object/name | 目标类别名 | 转换成类别ID前先统计类别集合 |
| bndbox | 左上角+右下角坐标 | 注意是xyxy,不是xywh |
| difficult | 难以识别标记 | difficult=1的样本建议训练时过滤 |
| truncated | 目标截断标记 | 边缘被截断的框可保留但需关注 |
类别名是个容易忽略的坑。不同批次标注时,有人把电流互感器写成current_transformer,有人简写成CT,还有人统一标成transformer或voltage_transformer。转换前一定要先跑一遍统计脚本,把所有name值打印出来,统一映射表,否则类别ID对不上,训练时损失函数直接爆掉。
2.2 PT和CT怎么区分:红外图里的同源设备标注难点
电压互感器(PT)和电流互感器(CT)在可见光下还算好认,但在红外图像里,两者轮廓高度相似,都是挂在构架上的瓷套或方形箱体,温度分布一覆盖,细节几乎全没了。标注的时候需要依赖安装位置、器身比例和接线方式这些间接特征来辅助判断。下面这个表是我在拆这份数据时总结的区分经验:
| 区分维度 | 电压互感器(PT) | 电流互感器(CT) |
|---|---|---|
| 安装位置 | 母线侧、线路侧,常与避雷器相邻 | 断路器两侧,间隔内成组出现 |
| 器身形状 | 体积偏大,油箱与瓷套一体 | 瓷套层数更密,径向更窄 |
| 红外特征 | 温升集中在顶部接线端子 | 一次绕组发热,整体温度分布较均匀 |
| 标注易错点 | 容易和避雷器混淆 | 容易和PT混淆、容易被杆塔遮挡 |
这份数据集的难点不在画框,而在类别判断。红外图像分辨率本身不高,设备发热区域和背景对比度又低,标注时容易出现两种问题:一是外接矩形框得过大,一个框把旁边的绝缘子或支柱也包进去;二是设备紧挨着,两个框高度重叠,导致训练时正样本重复。我一般会写个简单脚本,遍历XML统计所有框的IoU,把IoU超过0.6的框单独导出来人工复查:
import xml.etree.ElementTree as ET import os def box_iou(a, b): x1 = max(a[0], b[0]); y1 = max(a[1], b[1]) x2 = min(a[2], b[2]); y2 = min(a[3], b[3]) inter = max(0, x2 - x1) * max(0, y2 - y1) area_a = (a[2] - a[0]) * (a[3] - a[1]) area_b = (b[2] - b[0]) * (b[3] - b[1]) return inter / (area_a + area_b - inter + 1e-6) xml_dir = "Annotations" for xml_file in os.listdir(xml_dir): tree = ET.parse(os.path.join(xml_dir, xml_file)) boxes = [] for obj in tree.getroot().iter("object"): bb = obj.find("bndbox") boxes.append([float(bb.findtext("xmin")), float(bb.findtext("ymin")), float(bb.findtext("xmax")), float(bb.findtext("ymax"))]) for i in range(len(boxes)): for j in range(i + 1, len(boxes)): if box_iou(boxes[i], boxes[j]) > 0.6: print(f"{xml_file}: IoU={box_iou(boxes[i], boxes[j]):.2f}")这段代码的逻辑是对每个XML文件内的所有框两两计算交并比,超过0.6就打印出来。参数0.6是我根据红外设备重叠情况定的经验值,如果目标是密集排列的绝缘子串,可以放宽到0.7;如果框的是大型变压器本体,0.4就值得怀疑了。复查时重点看两个高度重叠的框是不是属于不同的设备——如果是同设备被标了两遍,直接删掉一个。
2.3 889张图的划分逻辑:为什么建议按拍摄批次切分
把数据集划分成训练集和验证集,看起来用个random_split就完事,但在变电站红外场景里,随机划分有隐藏问题。红外巡检图往往是同一批设备连续拍摄几十帧,相邻帧之间背景几乎一样、设备角度只有微小变化。如果这些相似帧同时进了训练集和验证集,验证指标会虚高,模型看起来 mAP 有0.85,换到真正的新场景立刻掉到0.6。
我处理这类巡检数据集的习惯是按拍摄批次划分。先看文件名或目录结构,把同一批次、同一机位拍摄的图像归为一组,然后按组分训练/验证,而不是按单张图分。比如这份数据有889张,如果共约20个拍摄批次,按8:2划分就是16个批次进训练、4个批次进验证。这样验证集里的设备和训练集设备角度、温度分布都有差异,评估结果才接近真实部署。还有一种更严格的做法是按变电站站点划分,训练集用A站的图,验证集用B站的图,能直接检验模型的跨站泛化能力,但需要数据集本身覆盖多个站点——如果只有单站点数据,按批次划分已经够用。
3. 红外图像的数据链路:灰度特性、直方图均衡与训练清单生成
3.1 红外图像为什么看着“发白”:灰度分布和可见光的本质差异
把红外图像和可见光图像放进同一个训练管线,是新手最容易犯的错误之一。可见光图像有三个通道,纹理、颜色、边缘信息丰富,而红外热像仪接收的是物体表面的辐射强度,灰度值反映的是温度高低。变电站设备的红外图有几个明显特征:背景天空和构架温度低,灰度值集中在暗部;设备本体温度高,灰度值集中在一个相对窄的亮部区间;整个画面的直方图呈双峰或尖峰分布,中间过渡带很窄。
这意味着直接套用 ImageNet 预训练模型时,模型的浅层卷积核是为自然图像设计的,对红外灰度图的响应会很奇怪。我一般做两件事:一是把灰度图复制成三通道,让模型输入保持标准形状;二是做对比度增强,把设备的温度区间拉伸开。直方图均衡是最常用的手段,但对红外图来说,全局直方图均衡容易把背景噪点一并放大,所以优先用CLAHE(对比度受限的自适应直方图均衡),它按小块做均衡,能在增强设备区域对比度的同时抑制背景噪声放大。
3.2 预处理三件套:CLAHE增强、归一化和通道转换
下面这段代码是适合红外设备检测的预处理做法:
import cv2 def load_infrared_rgb(path, clahe_clip=2.0, tile_size=8): img = cv2.imread(path, cv2.IMREAD_GRAYSCALE) if img is None: raise FileNotFoundError(f"无法读取图像: {path}") clahe = cv2.createCLAHE(clipLimit=clahe_clip, tileGridSize=(tile_size, tile_size)) img = clahe.apply(img) img_rgb = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) img_norm = img_rgb.astype("float32") / 255.0 return img_norm img = load_infrared_rgb("JPEGImages/infrared_0001.jpg")说明一下参数:clahe_clip=2.0是对比度限制阈值,值越大增强越激进,红外设备图上如果设备占画面比例小,可以提高到3.0,但如果背景温度分布复杂,太大会把背景的温差也拉出来,训练时引入大量无效纹理;tile_size=8是分块大小,8×8是常用值,图像分辨率高时可以用16。最后一步归一化到0到1,是因为后续训练框架内部还会做一次ImageNet标准化,提前归一化可以避免数值溢出。注意这里读图时用了IMREAD_GRAYSCALE,如果原图本身就是单通道红外图,这个读法是正确的;如果部分图像是伪彩色图,灰度化会丢失温度分层信息,这类图建议保留原始伪彩色通道直接作为三通道输入。
3.3 生成训练清单:从图像名列表到train.txt/val.txt
很多检测框架不直接吃XML,而是先要一份“图像路径清单”。生成清单这一步看似简单,但路径写法直接影响后面的训练。下面是我常用的脚本:
import os import random from sklearn.model_selection import train_test_split random.seed(42) image_dir = "JPEGImages" images = sorted([f for f in os.listdir(image_dir) if f.endswith(".jpg")]) train_files, val_files = train_test_split(images, test_size=0.2, random_state=42, shuffle=True) with open("train.txt", "w") as f: for name in train_files: f.write(f"JPEGImages/{name}\n") with open("val.txt", "w") as f: for name in val_files: f.write(f"JPEGImages/{name}\n") print(f"训练集 {len(train_files)} 张,验证集 {len(val_files)} 张")这段脚本的逻辑是把所有jpg文件名取出来,按8:2划分并写入两个txt。两个关键点:一是路径写法,这里写的是相对路径JPEGImages/infrared_0001.jpg,YOLOv5/YOLOv8的Data YAML里如果配置了path字段,txt里用不带扩展名的文件名即可,但如果直接给绝对路径,迁移到别的机器就要全部重写,所以建议用相对路径;二是随机种子固定为42,保证每次划分结果一致,否则换个机器划分结果不同,复现实验时指标对不上。划分完之后记得统计一下训练集和验证集的类别分布,确认两个集合里PT和CT都有足够样本,出现某一类全在训练集、验证集一条都没有的情况,评估结果会失真。
4. VOC转YOLO格式:转换脚本与四个边界坑
4.1 转换脚本:把XML里的xyxy映射成归一化的中心点格式
把VOC转成YOLO是绕不开的一步,因为YOLO系列训练时读的是每张图对应的txt文件,每行格式是类别ID 中心点x 中心点y 框宽 框高,所有坐标都归一化到0到1之间。下面是我在多个红外数据集上验证过的转换脚本:
import xml.etree.ElementTree as ET import os CLASS_MAP = { "voltage_transformer": 0, "current_transformer": 1, } def convert_voc_to_yolo(xml_path, out_dir): tree = ET.parse(xml_path) root = tree.getroot() filename = root.findtext("filename") size = root.find("size") img_w = int(size.findtext("width")) img_h = int(size.findtext("height")) lines = [] for obj in root.iter("object"): name = obj.findtext("name") if name not in CLASS_MAP: print(f"跳过未知类别 {name} in {filename}") continue cls_id = CLASS_MAP[name] bbox = obj.find("bndbox") xmin = float(bbox.findtext("xmin")) ymin = float(bbox.findtext("ymin")) xmax = float(bbox.findtext("xmax")) ymax = float(bbox.findtext("ymax")) x_center = (xmin + xmax) / 2.0 / img_w y_center = (ymin + ymax) / 2.0 / img_h box_w = (xmax - xmin) / img_w box_h = (ymax - ymin) / img_h x_center = max(0.0, min(1.0, x_center)) y_center = max(0.0, min(1.0, y_center)) box_w = max(0.0, min(1.0, box_w)) box_h = max(0.0, min(1.0, box_h)) lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}") out_name = os.path.splitext(filename)[0] + ".txt" out_path = os.path.join(out_dir, out_name) with open(out_path, "w") as f: f.write("\n".join(lines) + "\n") xml_dir = "Annotations" out_dir = "labels" os.makedirs(out_dir, exist_ok=True) for xml_file in os.listdir(xml_dir): if xml_file.endswith(".xml"): convert_voc_to_yolo(os.path.join(xml_dir, xml_file), out_dir)脚本的核心逻辑分三步:从XML读宽高和边界框坐标、用中心点公式做归一化、限制数值范围后写入txt。CLASS_MAP是类别映射表,键用XML里的name,值是对应的类别ID,必须和模型的类别顺序保持一致。:.6f保留6位小数足够,再多的精度在640分辨率下已经没有实际意义。最后的裁剪逻辑max(0.0, min(1.0, ...))是防止个别框略微超出图像边界导致训练报错,但注意这只能处理轻微越界,如果xmax比图像宽度大很多,说明XML本身有问题,要回头查原图。
4.2 边界坑一:归一化分母到底用哪组宽高
这是转换时最容易翻车的地方。有人图省事,用cv2.imread读图后取shape得到宽高,但红外图经常被预处理脚本重新保存过,实际保存的尺寸可能和XML里记录的尺寸不一致。比如原图是640×512,某次批量处理时转成了512×512,但XML里的<size>没更新,归一化后坐标就全偏了。
正确做法是只用XML里的<size>字段做分母,因为它描述的是标注时参考的图像尺寸。转换完成后,抽三到五张图,把生成的txt坐标反算回整数坐标,画在原图上肉眼检查一遍,确认框的位置没有整体偏移。我每次转完格式都会跑一次这个校验,花不了两分钟,能省掉后面训练出问题时的排查时间。
4.3 边界坑二:类别名的通配处理
红外设备数据集的类别命名经常不统一。有的标注员把电压互感器写成PT,有的写成voltage_transformer,还有的细分出pt_primary之类的层级。如果脚本里硬编码映射表,遇到没见过的名称会直接跳过或报错,导致少标一堆目标。
转换前先写一行命令统计所有类别名:
grep -h "<name>" Annotations/*.xml | sort | uniq -c | sort -rn看输出的名称清单,再决定是做归一化映射(把PT、pt、voltage_transformer统一映射到同一个ID)还是做合并归类。如果这份数据集的标注者把所有设备统一标成了transformer或equipment,那就按单个类别处理,训练时类别数设为1。这个决定要在转换前做,转换后再改类别ID就是灾难。
4.4 边界坑三:空标注文件与缺失XML
红外巡检图里很多帧没有目标设备,或者目标太小被标注员忽略,这类图像在XML里没有<object>节点。转换脚本写出空txt文件,大部分训练框架能接受空标注,但个别数据加载器会在读取时抛Empty label file异常,导致训练中断。
我一般会在转换脚本里统计空文件,单独生成一份清单,然后做两个选择:要么把它从训练清单里剔除,要么保留并确保数据加载器能跳过空文件。剔除更省心,但要注意别把验证集里用于测漏检的负样本也剔光了,否则模型学不会“没有设备时不该输出框”。
4.5 边界坑四:train.txt和val.txt的路径写法决定成败
路径这个问题在不同框架里表现不一样。Darknet版的YOLOv3要求txt里写图片的绝对路径或相对路径,训练时直接打开这个路径读图;Ultralytics YOLOv8则不同,它在Data YAML里指定了train和val指向txt文件,txt里写的是图片相对路径,同时它会自动把路径中的images替换成labels去寻找对应的标注txt。如果图片在JPEGImages/目录而标注在labels/目录,且两者不在同一个父目录下,YOLOv8就会找不到标注文件。
最简单的规避办法是保持统一目录结构:images/放图,labels/放txt,train.txt里写images/infrared_0001.jpg,YOLOv8会自动解析到labels/infrared_0001.txt。如果你用的是老版Darknet结构,那就在txt里写完整路径并确保labels和JPEGImages同级。
5. 训练参数与常见问题排查:过拟合、漏检和标注噪声
5.1 小数据集训练参数基线
889张图像在这个领域算偏小规模的数据集,直接套用COCO的训练配置会过拟合。我测试过的参数基线如下:
| 参数 | 建议值 | 说明 |
|---|---|---|
| 模型 | YOLOv8n 或 YOLOv8s | 小模型在小数据上更稳 |
| imgsz | 640 | 红外设备框占比不大,640够用 |
| epochs | 300 | 早停机制patience设为50 |
| batch | 16 | 显存不够降到8 |
| optimizer | AdamW | lr0=0.001, weight_decay=0.0005 |
| mosaic | 0.0 或 0.5 | 设备重叠严重时建议关闭 |
| 预处理增强 | 轻微HSV、随机平移、翻转 | 不要开大角度旋转 |
| 类别数 | 1 或 2 | 由XML里的name决定 |
| 早停 | patience=50 | 防止小数据集上过拟合 |
红外设备图像的另一个特殊性是设备框通常比较紧凑、形状变化不大,开大角度的旋转增强反而会制造大量“设备倒挂”的无效样本。我一般只开水平翻转和小于15度的旋转,mosaic在设备重叠严重时建议关闭,因为马赛克拼接会让断裂的设备框更难学。
5.2 现象:loss降了但mAP不动,甚至训练集mAP就异常高
排查思路:这种情况先怀疑数据泄漏。前面提到按批次划分,如果随机划分时同一拍摄序列的相似帧同时进了训练和验证,验证集的“好成绩”其实是记忆而非泛化。具体表现为训练loss正常下降,验证mAP看着也不低,但换到另一个变电站的红外图立刻崩掉。解决方法是重新按批次划分数据,并检查train.txt、val.txt里有没有重复的图像路径,输出重复行:
sort train.txt val.txt | uniq -d另外还要看类别是否平衡。如果889张里CT有700个标注框而PT只有150个,模型会偏向学CT的特征,PT的召回率起不来。这种情况可以给PT类别加更高的cls损失权重,或者用简单的过采样——把PT样本复制一份放进训练集,但注意不要复制到验证集。
5.3 现象:CT漏检集中在图像边缘,框总是对不齐
红外巡检图里,设备经常位于画面边缘或被裁掉一半,这时模型的漏检率明显偏高。原因有两个层面:一是训练数据里边缘设备框的样本占比本来就低;二是很多增强策略在随机裁剪时会丢掉边缘目标。解决方法是做“边缘过采样”,对包含边缘框的图像做平移增强,让设备往画面中心靠拢再训练。做法是对这类图像随机平移10%到20%的像素,然后重新生成标注框坐标。也可以打开YOLOv8的close_mosaic=10,让最后10轮训练禁用马赛克增强,帮助模型在真实分布上微调收敛。
5.4 现象:验证集计算mAP时同一设备被算了两次“错框”
这个问题根源在标注阶段。如果某个设备在XML里被标了两遍,比如两个标注框IoU极高,验证时一个框匹配了预测框,另一个框没匹配上,就会被算成漏检或误检,拖低mAP。前面2.2节的IoU统计脚本就是干这个的,发现重复框后,保留置信度较高的那个标注框,或者按标注重叠策略合并两个框。这个操作要在数据划分之前做,否则清理后的结果会让训练集和验证集分布不一致。从那以后我每拿到一批新数据,第一步永远是跑重叠统计,而不是直接进训练流程。
5.5 现象:模型不收敛,loss曲线锯齿状跳动,训练集验证集差别巨大
排查方向是图像通道问题。红外原图是单通道灰度,但很多框架的预训练权重要求三通道输入。如果加载图像时代码里用了cv2.imread(path)默认读成三通道,而另一步预处理又把它当成单通道做处理,通道数不一致会导致模型前向传播报错或loss异常。统一的做法是在数据加载层里强制做灰度转三通道,像我前面代码那样cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)。还要检查图像像素值范围,红外图如果本身是16位PNG保存,读出来像素值最高到65535,直接送进模型会数值爆炸,必须转到8位范围再做归一化。这类问题通常表现为开头loss在正常范围,训练几十轮后突然出现NaN,十有八九是某个样本像素值异常,定位到具体是哪个文件后单独修复。
5.6 训练后必做的一步:用验证集输出PR曲线和置信度分布
很多人训练完只看一个最终mAP数,这在红外小数据集上远远不够。因为样本量小,mAP的置信区间很宽,同一份数据换不同初始种子可能差出3到5个点。我建议训练完后导出验证集的PR曲线和每一类的AP值,同时看置信度分布:如果大量预测框的置信度集中在0.9以上,说明模型过于自信、在陌生场景可能脆;如果集中在0.3附近,说明训练不充分。另外用val模式跑一遍测试集,保存推理结果的图像,把漏检和误检案例抽出来看,比任何指标都能说明问题。对896张这种规模的数据,人工检查每一张验证集的推理结果完全可行,这步别省。
6. 把889张用到极致:难例挖掘、预标注循环与推理验证
6.1 难例挖掘:用第一版模型找出最难的样本
889张数据集训练出的模型,第一版往往在常见角度、清晰温度分布的设备上表现不错,但在遮挡、极端角度、多设备密集排列的场景上漏检严重。把这些漏检样本找出来补充进训练集的方法叫难例挖掘(hard example mining)。具体做法是训练完第一版模型后,对全部训练集做一次推理,把置信度低于0.3的检测结果对应的图像和标注框单独导出。这些样本通常具备特征模糊、目标过小、背景复杂等特点,人工筛选一遍后,把这些图像在训练清单里的权重加大。对小数据集,这比盲目收集更多数据来得实在。
6.2 预标注循环:用模型生成XML,人工只做修正
另一个提效手段是用训练好的模型做预标注。推理模型输出的是归一化的txt坐标,需要把它反算成VOC格式的XML,然后导入LabelImg进行人工修正。这个流程在重标注一批相似场景的新图像时效率翻倍——模型先框出大部分设备,标注员只需要调整边界和修正类别,而不是从零画框。反算脚本的核心就是把txt里的中心点、宽高还原成左上角、右下角整数坐标,再写入XML结构。需要注意,预标注的框通常比人工标注略松或略紧,人工修正时重点检查设备边缘有没有被框截断。
6.3 验证模型推理效果:一个简单的单图推理脚本
from ultralytics import YOLO import cv2 model = YOLO("runs/detect/train/weights/best.pt") img = cv2.imread("val_images/infrared_0100.jpg") results = model.predict(img, conf=0.25, iou=0.5, verbose=True) for r in results: boxes = r.boxes for box in boxes: cls_id = int(box.cls[0]) conf = float(box.conf[0]) x1, y1, x2, y2 = box.xyxy[0].tolist() print(f"类别{cls_id} 置信度{conf:.3f} 坐标({x1:.1f},{y1:.1f},{x2:.1f},{y2:.1f})")这段代码的逻辑是用训练好的best.pt对单张红外图做推理,输出每个目标框的类别、置信度和坐标。conf=0.25是置信度阈值,红外设备图如果目标特征弱、误检多,可以调到0.35;iou=0.5是NMS的IoU阈值,设备重叠严重时降到0.45能减少相邻框被合并的概率。推理时最好逐张比对原图检查输出框是否对准设备本体。从那以后我每次换数据集,都强制走一遍“直方图检查、标注重叠统计、格式转换校验、单图推理目检”的流程,这四步做完才敢提交训练结果。这套流程也希望能帮到你,少走我踩过的弯路。
本文还有配套的精品资源,点击获取