简介:面向目标检测与建筑质量检测场景,这份红外热成像缺陷识别数据集支持 YOLOv12 模型训练,整体识别率达 91.5%。包内包含 700 张红外建筑缺陷图片,每张图片均配有对应的 txt 格式 YOLO 标注文件,另有 1 个 yaml 配置文件用于定义类别与路径信息,便于快速搭建训练环境;标注文件记录缺陷类别与目标框坐标,适合具备一定深度学习基础的研究者、算法工程师或建筑智能化方向的学生直接使用。压缩包共 1401 个文件,大小约 34.53MB,体量轻、结构清晰,便于下载后在本地或云端完成模型训练与验证。目前已有 53 人学习下载,属于中小规模、可直接上手的实用型数据集。通过这批数据,使用者可以快速开展建筑外墙渗漏、空鼓等典型缺陷的自动识别实验,结合配套标注信息完成从数据准备到模型评估的完整流程,节省人工采集和整理的精力。

1. 红外热成像缺陷数据集:小样本、高识别率背后的复现门槛

做过建筑检测的人都知道,外墙空鼓、渗漏、保温层破损这类缺陷,可见光图像里往往只是一条不起眼的裂缝或一片色差,但在红外热像仪下,温度场的异常让缺陷无处遁形。带标注的红外热成像建筑缺陷识别数据集,是把这种温度异常转化为目标检测模型训练样本的一种资源:700张图配好标注文件,直接适配yolov12训练管线,宣称能到91.5%的识别率。这个数字在小样本前提下很诱人,但它到底怎么复现、训练时有哪些坑、91.5%指的是mAP还是类别精度,我在这篇笔记里一次性讲透。适合手里有红外设备、想快速验证缺陷自动识别方案的工程师,也适合刚接触目标检测、想用现成数据集跑通yolov12流程的研究者。

2. 红外热成像建筑缺陷的检测逻辑:为什么是yolov12而不是传统阈值法

2.1 温度场异常是本质信号,可见光算法天然吃亏

建筑外墙缺陷在红外图像里的表现形式,和普通目标检测任务差别非常大。拿最常见的三类缺陷举例:外墙空鼓在红外图像里是一块温差在1到3摄氏度的区域,边界模糊,和背景的灰度差很小;渗漏区域在夜间红外图里呈现明显的低温条带或团块;保温层破损则是高温区域,因为热量在破损处集中散失。传统做法是用红外测温仪人工巡检,靠经验判断温差阈值,但现场环境温度、太阳辐射、风速都会改变温度场分布,固定阈值的方法在清晨、正午、雨后完全失效。

目标检测模型在这里的优势在于,它不直接学习温度绝对值,而是学习温度异常的空间形态和相对关系。yolov12这类anchor-free检测器对小目标相对友好——建筑缺陷在红外图像里往往只占几十乘几十像素的区域,而且同一张图里可能出现十几个形态相似的缺陷点。用yolov12做这类任务,核心是把缺陷当成“温度场里的局部异常对象”来学习,而不是像图像分割那样把整个热图都分类。这也是为什么数据集的标注方式会直接影响模型效果:标注框是否紧贴缺陷边缘,决定了模型能不能从模糊的热区里学出准确的边界。

2.2 yolov12在红外小目标上的结构性优势与代价

yolov12继承yolov8的anchor-free框架,但有几个改动让它更适合红外缺陷检测。一是引入基于注意力机制的特征融合模块,对不同尺度特征图的融合方式做了调整,这让网络在浅层就能捕捉到小缺陷的细节纹理,而不是等特征传到深层后已经丢失了空间信息。二是它的head结构对目标框回归做了解耦,分类和回归分支各自独立训练,对红外图像这种低纹理、高噪声场景更稳。三是yolov12的模型参数量相比yolov5同规模版本略有增加,但推理速度仍然能跑到实时水平,这对未来上无人机或移动巡检设备很重要。

代价也很明显:yolov12训练时的超参数敏感度比yolov8更高,尤其是学习率和batch size的搭配,稍不注意就会loss震荡。另一个代价是模型对红外图像的预处理要求更苛刻。红外图是单通道灰度图,直接复制成三通道喂给模型,和用伪彩色图喂给模型,训练出来的特征完全不同。我自己的经验是,单通道转三通道训练稳定,但要提升mAP,得用红外厂商预设的调色板转成伪彩色,让模型学到的是温度分层的颜色关系,而不是纯灰度纹理。

2.3 识别率91.5%的真相:指标口径才是第一道坑

标题里写了91.5%识别率,这个数字在落地时必须先确认口径。目标检测领域常用的指标有mAP@0.5、mAP@0.5:0.95、precision、recall,四个指标的数值差异很大。700张红外图的训练集规模属于典型小样本,如果按mAP@0.5计算,靠迁移学习和数据增强,在单一建筑场景下跑到90%以上并不罕见;但如果换成mAP@0.5:0.95,因为IOU阈值严格,小缺陷框稍微偏移几个像素就会判定为负样本,能到75%已经算不错了。

常见做法是:拿到数据集后先用yolov12自带的验证脚本跑一次,看它输出的各项指标,再和标题里的91.5%对比。如果对方没有提供验证脚本或指标定义,就默认是mAP@0.5——这是多数商业数据集汇报业绩时采用的保守有利口径。只要是mAP@0.5,我的建议是别被数字迷惑,重点看模型在小目标、多目标、遮挡三种场景下的PR曲线,那才是判断数据集质量的关键。

2.4 数据集的构成和标注格式:先检查再训练

拿到数据集第一步不是急着配环境,而是检查文件结构。常见的红外缺陷数据集包含四类文件:原始红外图像(通常是jpg或png格式,分辨率在640乘480到1920乘1080之间)、标注文件(yolov12用的txt格式,每一行是class_id和归一化坐标)、类别配置文件(描述缺陷类别名称,典型的有delamination、crack、water_leak、thermal_bridge四类)、以及划分好的train和val子集。标注坐标的归一化方式通常是中心点x、中心点y、宽度、高度,四个值都是0到1之间的小数。

检查时有几个关键点:

  • 标注框是否越界,也就是框的坐标加上宽高后是否超过1.0,这会导致训练时报错或loss异常
  • 类别是否均衡,比如700张图里900个缺陷,其中500个是空鼓,150个是渗漏,这就是典型的长尾分布,直接训练会忽略少样本类别
  • 有没有标注错位,红外图像和可见光图像对齐不当会导致框对不上实际缺陷位置
  • 一个缺陷是不是被重复标注了,重复框会让模型在同一个位置叠加学习,导致推理时出现重复检测结果

3. yolov12环境配置与数据集转换:从零跑通最小训练命令

3.1 yolov12环境怎么配:CUDA、PyTorch和ultralytics源码的版本组合

yolov12的环境配置是新人最容易卡住的第一关,网上常见的报错是import模块找不到、或者训练时xtensor维度不匹配。我先给出一个我验证过能稳定运行的最小环境组合,然后拆解每个组件的选型原因。

# 创建独立环境,避免污染系统python
conda create -n yolov12 python=3.10
conda activate yolov12

# 安装CUDA 11.8对应的PyTorch版本
pip install torch==2.1.0 torchvision==0.16.0 --index-url https://download.pytorch.org/whl/cu118

# 拉取yolov12官方源码并安装依赖
git clone https://github.com/sunsmarterjie/yolov12
cd yolov12
pip install -r requirements.txt

# 验证环境是否可用,能输出模型参数就算成功
python -c "from ultralytics import YOLO; model = YOLO('yolov12n.pt'); print('model loaded')"

这段命令的逻辑是:先用conda创建一个干净的3.10环境,避免系统里其他python版本干扰;然后安装CUDA 11.8构建的PyTorch,因为yolov12的attention模块依赖torch2.0以上的算子,老版本会直接报torch版本过低;之后拉取源码安装依赖。如果最后一行能打印model loaded,说明环境没问题。

参数说明:三处值得注意的地方。python版本不要用3.9以下,因为yolov12源码里用了新语法特性,3.8会解析报错;CUDA版本选择11.8是兼容性最好的,12.x虽然也能跑,但某些机器上attn模块的算子会出nan loss;git clone用的是官方仓库地址,如果你在本地已经下载好了源码包,直接cd进目录执行pip install -r requirements.txt也行。

3.2 标注文件检查与类别配置文件校正

数据集标注是直接决定训练效果的一环,700张图花的时间不多,但必须逐项核对。我一般会写一个小脚本快速跑一遍检查。

import os

def check_labels(label_dir):
    class_count = {}
    errors = []
    for file in os.listdir(label_dir):
        if not file.endswith('.txt'):
            continue
        with open(os.path.join(label_dir, file), 'r') as f:
            lines = f.readlines()
        for line in lines:
            parts = line.strip().split()
            if len(parts) != 5:
                errors.append(f"{file}: 一行标注不是5个字段")
                continue
            cls_id = int(parts[0])
            x_center, y_center, w, h = map(float, parts[1:5])
            class_count[cls_id] = class_count.get(cls_id, 0) + 1
            # 检查坐标是否越界
            if x_center < 0 or x_center > 1 or y_center < 0 or y_center > 1:
                errors.append(f"{file}: 中心点坐标越界")
            if w <= 0 or h <= 0:
                errors.append(f"{file}: 宽高小于等于0")
    total = sum(class_count.values())
    for cls_id, count in class_count.items():
        print(f"类别{cls_id}: {count}个标注 ({count/total:.1%})")
    if errors:
        print("发现问题:")
        for e in errors[:20]:
            print(e)
    else:
        print("标注格式全部正常")

check_labels('datasets/infrared_building/labels')

逻辑说明:脚本遍历标注目录下的所有txt文件,先检查每行是否恰好5个字段——目标检测的YOLO标注格式必须是类别ID加四个坐标值,字段数不对说明标注工具导出设置有问题。然后检查坐标是否在0到1之间,因为归一化坐标如果越界,训练时模型会去预测超出图像范围的框,导致loss计算异常。最后统计每个类别的标注数量和占比,用来判断类别分布是否均衡。

参数说明:判断坐标越界时,x_center加w/2的结果超过1才算真正越界,但我的脚本只检查了中心点本身,这是保守做法——中心点如果越界,框一定有一部分在图像外,这类标注需要人工复核。类别占比的统计很关键,如果某个类别占比低于5%,训练时可以对这个类别提高loss权重,否则模型学不到这个缺陷的特征。

3.3 最小训练命令和常见训练参数设置

环境配好后,第一步训练不建议直接上完整数据集,而是用700张图先跑一个quick start,确认整个流程能正常走完,再回来调参。

cd yolov12
python train.py --data infrared_building.yaml --weights yolov12n.pt --img 640 --batch 16 --epochs 100 --hyp hyp.scratch-low.yaml

逻辑说明:train.py是yolov12的训练入口。data参数指向数据集配置文件,里面写了训练和验证图片的路径、类别数量、类别名称;weights参数加载预训练权重,用yolov12n(nano版本)的原因是小模型在只有700张图的场景下更不容易过拟合,训练速度也更快;img设为640是平衡分辨率和显存消耗的选择,原始红外图如果大于640,训练时会被缩放,如果缺陷尺寸太小,可以改成960或1280,但显存占用会翻倍。

参数说明:batch设16是因为700张小数据集用大batch容易让模型很快收敛到局部最优,损失函数失去波动性。epochs设100是底线,小数据集训练到第50轮左右基本就趋于稳定,100轮可以观察loss曲线的走势判断要不要early stopping。hyp参数文件控制数据增强强度,hyp.scratch-low.yaml的增强强度较低,适合热红外图像,因为红外图像对随机裁剪、旋转这类几何变换本身就是敏感的。

训练完成后,模型权重保存在runs/train/exp/weights/best.pt和last.pt。best.pt是验证集上mAP最高的那个checkpoint,后面推理和部署都用它,last.pt是最后一轮的结果,一般只用来续训。

4. 提升识别率到91.5%的实战调整:数据增强、迁移学习、超参数

4.1 红外图像数据增强的特殊性:Mosaic必须慎用

数据集只有700张,直接训练必然过拟合,yolov12默认开的数据增强在这个场景下需要逐项调整。先用一个命令查看当前增强配置。

python -c "from ultralytics.utils import DEFAULT_CFG; print(DEFAULT_CFG.dict())"

执行这个能看到所有默认增强参数。最需要改的是mosaic,默认值1.0表示每张训练图都有概率做四图拼贴。mosaic在可见光目标检测里效果很好,因为增加了样本多样性,但在红外建筑缺陷检测里有个大问题:四张不同温度范围的红外图拼在一起,会产生虚假的温度梯度边界,模型学到的是“拼贴缝”而不是缺陷特征。我习惯把mosaic关掉或设到0.2以下,只保留轻微的拼贴概率。

mixup参数同理,默认0.1问题不大,但不要调大。红外图像的温度值是有物理意义的,两张不同场景的图混合后,像素温度值变成两者均值,这可能产生物理上不存在的温度分布,让模型学到错误特征。相比之下,HSV扰动参数可以全部关掉,因为红外图没有颜色信息,调色调饱和度毫无意义,白耗算力。

水平翻转fliplr可以保留0.5,建筑缺陷左右对称,翻转不破坏物理含义。平移、缩放、旋转这几项都建议保留默认,因为巡检时拍摄角度确实有变化,几何增强能提升鲁棒性。

4.2 迁移学习:用COCO预训练权重还是完全从头训

yolov12训练脚本里weights参数除了加载yolov12n.pt,也可以加载COCO数据集上的预训练权重yolov12s.pt或yolov12m.pt。对红外热成像任务,我的建议是:如果目标缺陷和COCO里的对象类别毫无关系,就使用COCO预训练权重做迁移学习,让模型复用低级特征——边缘、纹理、局部对比度;如果完全从头训练,在700张图上只能学到表面模式,一到新场景就露馅。

但迁移学习有两个坑。第一个坑是预训练权重的stride配置和输入分辨率不匹配,把原图640训练改成960推理时,模型输出尺寸会变化,需要确认模型能自适应。第二个坑更隐蔽——用COCO预训练权重第一次跑红外数据集时,前几个epoch的loss会异常大,因为模型发现所有类别都和COCO类别不一致,正在大范围调整权重。这时候别急着中断训练,等loss降下来再判断。

还有一个实操技巧:冻结backbone前几层训练,等head收敛后再解冻全部层。具体做法是训练脚本里设置freeze参数冻结前10层,跑30轮后取消freeze再跑30轮。这个分阶段策略可以让小数据集上的训练更稳定,减少震荡。

4.3 超参数调整实战:从默认到高mAP的调参路径

yolov12自带hyp.scratch-low.yaml和hyp.scratch-high.yaml两个超参文件,low偏保守,high偏激进。小数据集上我建议用low起步,然后手动修改几个关键参数。

lr0: 0.005
lrf: 0.01
momentum: 0.937
weight_decay: 0.0005
warmup_epochs: 3.0
warmup_momentum: 0.8
box: 0.05
cls: 0.5

参数说明:lr0从默认0.01降到0.005,是因为小数据集需要的更新步长更小,lr太高会导致loss在前几十轮来回震荡。warmup_epochs从3调到3.0保持默认即可,但warmup_momentum要保持0.8,防止初期权重更新方向乱跳。box和cls两个loss权重里,cls从默认0.5调高到0.7会更有效——因为红外缺陷类别间的差异小,需要更强的分类监督。如果你发现某个缺陷类别识别率特别低,可以把cls继续往上调,但不要超过1.0,否则回归分支学不好,框的位置会偏移。

4.4 识别率上不去的三板斧:类别权重、测试时增强、伪标签

当mAP@0.5停在80%左右上不去时,依次尝试三个进阶手段。

类别权重是直接在loss计算时给少样本类别更高权重,比如渗漏只有空鼓的1/5数量,它的loss乘5倍惩罚,强制模型关注这个类别。yolov12默认不提供类别权重参数,需要修改loss.py中的权重向量,或者用更简单的方法——过采样,把少样本类别的图像复制两到三份混入训练集。这个方法简单粗暴但有效,缺点是训练时间变长,且复制过多会让模型对这些样本记忆过深。

测试时增强(TTA)是推理时的技巧:原始图像做水平翻转、多尺度缩放后分别推理,最后把多个结果融合。yolov12提供--tta参数,开启后mAP一般能涨1到2个百分点,代价是推理速度降为原来的三到五倍。如果目标场景是无人机巡检后离线分析,TTA很划算;如果要实时检测,这个方案不可行。

伪标签是拿训练好的模型去预测未标注的红外图,把高置信度预测结果当作标注加入训练集。在只有700张图的情况下,这个技巧能让mAP突破瓶颈,但前提是预测结果必须人工抽检,否则会把模型的错误认知固化进训练集。

5. 避坑指南:红外缺陷数据集训练的5条血泪踩坑记录

5.1 现象:训练loss正常下降但mAP始终为0

原因:类别ID从1开始而不是从0开始。很多标注工具导出时类ID从1计数,但yolov12类别索引从0开始,导致模型预测的类别ID永远比标注大1,推理时所有预测框都被判错。解决:检查data配置文件里的类别名称顺序和标注文件里的ID是否一一对应,把类ID全部减1后重新生成标注文件。

5.2 现象:模型在晚上拍摄的红外图上检测正常,白天拍摄的图上检测率骤降

原因:红外热成像在白天和夜晚的成像特征完全不同。白天太阳辐射加热外墙,缺陷可能表现为高温区或低温区,取决于缺陷导热系数;夜晚温度场只受建筑内部热量影响,缺陷表现相对统一。模型只学会了夜晚的温差方向,无法泛化到白天。解决:如果数据集包含白天和夜晚两种图,确认标注文件里是否有拍摄时间字段;如果没有,按图像特征把夜晚图分开作为验证集,看日间表现到底差多少;再决定补充日间标注还是分时段训练两个模型。

5.3 现象:模型预测出的缺陷框总是偏大或偏小

原因:标注框边界不贴合缺陷实际边缘。红外热像仪的测温范围会让缺陷周围形成一圈过渡区域,标注员如果不放大图像仔细看,很容易把过渡区也框进去。框偏大导致IOU计算结果偏低,模型学到的目标是包括背景噪声在内的整体区域。解决:重新检查标注框,尤其是缺陷边界的处理——空鼓缺陷框应紧贴温差突变处而不是温度峰值处;渗漏缺陷框应包含整个渗漏路径,而不是只框最湿的局部区域。

5.4 现象:训练时显存不够,batch调到8还是OOM

原因:输入图像分辨率太大,红外相机出的原始图是1920乘1080,直接resize到640训练时虽然内存占用可控,但如果设置了图片缓存到显存或者开了多尺度训练,占用就会暴增。解决:不要用原始分辨率直接训练,在data配置文件的img参数设为640或960;同时关闭cache参数,默认false即可;如果还爆显存,把batch降到4,同时把workers设为0避免数据加载进程占显存。

5.5 现象:训练到第80轮时mAP突然下降

原因:学习率衰减到极低值后开始过拟合,模型对验证集里个别难样本过度拟合,导致泛化指标下降。解决:在训练脚本里设置early stopping参数,patience设为20轮,mAP连续20轮不涨就自动停止;回调到第60轮的best.pt权重,用那个权重做最终模型。另外一个预防手段是提高label_smoothing参数,让模型不那么自信地预测单一类别。

6. 验证识别率真实水平的自测方法:写一个模拟缺陷注入脚本

拿到模型后,不要只信数据集自带的验证集结果,那太乐观了。用脚本在无缺陷的红外图像上合成已知缺陷,测试模型能否精准定位。具体做法是读取干净的红外图,在固定位置写入一块高斯温度分布模拟空鼓区域,然后跑模型推理,看是否在正确位置输出检测框。

import cv2
import numpy as np

def inject_defect(image, center, size, temp_delta):
    h, w = image.shape[:2]
    cx, cy = center
    mask = np.zeros((h, w), dtype=np.uint8)
    cv2.circle(mask, (cx, cy), size, 255, -1)
    defect = np.zeros_like(image)
    gauss = cv2.getGaussianKernel(size*4, size)
    gauss_2d = gauss @ gauss.T
    defect[mask > 0] = (gauss_2d * temp_delta).flatten()[:mask[mask > 0].shape[0]]
    return cv2.add(image, defect)

image = cv2.imread('clean_infrared.png', cv2.IMREAD_UNCHANGED)
injected = inject_defect(image, (320, 240), 15, 2.5)
cv2.imwrite('injected_defect.png', injected)

逻辑说明:这段脚本在干净的红外图指定位置画一个高斯温度团,模拟温差2.5摄氏度的空鼓缺陷。高斯核的大小由size参数控制,模拟缺陷的实际物理尺寸;temp_delta设为2.5模拟真实空鼓的温差。检测时把injected_defect.png喂给模型,如果模型能在(320,240)附近输出高置信度框,说明模型学到了温度异常的空间特征;如果在错误位置输出框,说明模型学的可能是背景纹理而不是温度场。

参数说明:effect大小和temp_delta需要按场景微调。如果模型在2.5摄氏度的温差下都能稳定检出,说明泛化能力不错;如果检出不了,就把temp_delta调到3再试,逐步找出模型的温差敏感边界。这个方法也可以用来测试不同尺寸的缺陷——最小能检出多大尺寸的热异常,一般比标注里的最小框要小一点才算合格。

最后一个习惯:我每次拿到新的红外数据集,都会先跑一遍这个注入脚本再决定要不要投入训练,省下的可是整周的调参时间。拿到任何数据集都先用这种自测逻辑过一遍,希望对你有用。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

更多推荐