尧图精选

红外热成像建筑缺陷识别:700张图与YOLOv12训练实战

🕒 发布时间:2026/10/2 9:11:53 📁 来源:尧图网络
简介这是一份带标注的红外热成像建筑缺陷识别数据集面向建筑质量检测、计算机视觉目标检测的研究人员与工程师尤其适合希望使用YOLOv12等模型进行热成像缺陷自动识别训练的场景。数据集共1401个文件包含700张红外JPG图像、700个对应的TXT标注文件以及1个YAML配置文件图像与标注一一对应可直接接入主流YOLO系列训练流程压缩包整体约34.53MB文件名遵循统一命名规则目录结构清晰方便快速导入与数据增广。该资源已有53人浏览学习标注格式统一据作者描述模型识别率可达91.5%可帮助使用者省去大量人工采集与标注时间快速获得可复现的训练数据基础尤其适合作为红外建筑缺陷检测方向的入门与进阶素材。1. 带标注的红外热成像建筑缺陷识别数据集700张图如何撑起91.5%的识别率红外热成像照片上的建筑缺陷和普通可见光照片是两个世界。可见光图像里的裂缝、剥落、变色在热图上可能毫无纹理反过来肉眼觉得平整的外墙在红外镜头下却会露出一片片温度异常。这个带标注的红外热成像建筑缺陷识别数据集就是把这类温度异常用边界框框起来再按YOLOv12的格式组织好700张图标称能跑出91.5%的识别率。对做外墙检测、房屋验收和渗漏排查的从业者它回答的是红外数据怎么采、缺陷怎么标、模型怎么训这一整条链路对刚接触目标检测的新手它也是一份能照着复现的最小样本工程。下面从数据格式、标注规范、训练参数和翻车点逐个拆开讲。2. 红外热成像缺陷数据集的采集与标注YOLOv12能吃到的图片到底是什么样子2.1 热像仪拍摄参数与发射率设定决定标注质量的第一步红外热成像缺陷识别的数据质量首先由采集端决定而不是由标注决定。这个数据集里出现的是建筑外墙、屋面和各种结构表面的热图典型分辨率集中在640×512或384×288温度灵敏度NETD在50mK上下。这类图的特点是单个缺陷区域往往很小一个外墙空鼓可能只有十几个像素而整面墙的温度梯度又很大阳光直射面、阴影面、窗框热桥混在一起。拍摄时发射率设错整张图都会出现系统性偏差。常见做法是把发射率按材料分别设混凝土和水泥砂浆取0.920.96砖墙取0.930.95金属构件要降到0.30.5玻璃则按入射角调整。建筑外立面多数是多材料混合不可能一张图一个发射率所以采集经验是“按主体材料设一个值记录在文件名里”。我一般会在文件名里加后缀例如bd03_brick_em093_dn_001.jpg表示3号楼、砖墙、发射率0.93、夜间拍摄。这样回头做数据集清洗时能直接按后缀分组看分布不用去翻拍摄日志。采集时间段比设备参数更容易被忽略。白天阳光直射时外墙表面温度差异很大但这种差异主要来自阳光辐照和材料吸热率并不都代表缺陷。日落后24小时或日出前1小时表面温度逐渐趋稳内部缺陷引起的温差才能反映出来。常见采集方案是每天固定两个时段拍每栋楼至少覆盖东南西北四个立面距离控制在515米尽量让目标缺陷在图中占30150像素。太远则小缺陷无法辨认太近则会引入自身反射热干扰。2.2 缺陷类型定义与缺陷标注的三条原则这个数据集里的缺陷类别从项目实战看通常归为三类外墙空鼓/剥离、渗漏潮湿、热桥或保温层缺失。标注前必须先定义清楚每类的温度特征否则标注员会按自己的感觉乱框。空鼓区在热图上是一片相对均匀的偏高温区域边界模糊但有整体轮廓渗漏区通常是低温或温度过渡带形状不规则热桥的典型特征是沿梁柱位置的规则条带温度与周围墙体差异明显。标注原则第一条框住温度异常区而不是框住整个物理构件。经验不足的标注员往往把整面墙都框进去因为整面墙的温度和背景都有差异这样会让模型学到“整墙即缺陷”。正确做法是只框与周围温差超过0.51.0℃的连续区域且面积至少有几十个像素。第二条重叠缺陷各自独立标注。一块空鼓旁边正好有渗水痕迹两个框可以重叠但不能合并成一个框否则类别边界被糊掉。第三条没有把握的弱温差区域宁可漏标也不要乱标。弱信号框会让模型把正常温差误当缺陷对精确率伤害远大于漏标对召回率的伤害。标注工具上Labelimg和LabelStudio用得最多。对这个数据集Labelimg直接导出VOC格式比较稳类别少、操作直接LabelStudio适合团队协作特别是多人同时标注需要审核流的情况。700张图不算多单人用Labelimg两三个工作日能做完关键是先集中时间把前50张图标完并给有经验的人复查确认标准一致后再批量推进。2.3 从Labelimg标注到YOLOv12的TXT格式转换脚本与边界框约束Labelimg导出的VOC XML里记录的是xmin、ymin、xmax、ymax的绝对坐标而YOLOv12训练需要的TXT每行是“类别ID 归一化中心x 归一化中心y 归一化宽 归一化高”。这一步看着简单踩坑的人不少。下面这个脚本是常见做法按目录批量转换并做了边界剪裁。import xml.etree.ElementTree as ET from pathlib import Path class_names [void, moisture, thermal_bridge] def convert_voc(xml_path: str, img_w: int, img_h: int) - list[str]: lines [] root ET.parse(xml_path).getroot() for obj in root.iter(object): name obj.find(name).text if name not in class_names: continue b obj.find(bndbox) x1 float(b.find(xmin).text) y1 float(b.find(ymin).text) x2 float(b.find(xmax).text) y2 float(b.find(ymax).text) # 边界剪裁防止标注框超出画面导致训练报错 x1 max(0, min(x1, img_w - 1)) x2 max(0, min(x2, img_w - 1)) y1 max(0, min(y1, img_h - 1)) y2 max(0, min(y2, img_h - 1)) if x2 x1 or y2 y1: continue # 无效框直接丢弃 cx (x1 x2) / 2 / img_w cy (y1 y2) / 2 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h lines.append(f{class_names.index(name)} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) return lines def batch_convert(voc_dir: str, txt_dir: str, img_dir: str, suffix: str .xml): voc_dir, txt_dir, img_dir Path(voc_dir), Path(txt_dir), Path(img_dir) txt_dir.mkdir(parentsTrue, exist_okTrue) for xml_file in voc_dir.glob(f*{suffix}): root ET.parse(xml_file).getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines convert_voc(str(xml_file), img_w, img_h) out_path txt_dir / (xml_file.stem .txt) out_path.write_text(\n.join(lines), encodingutf-8) if __name__ __main__: batch_convert(labels_voc, labels_txt, images)脚本逻辑很简单但有几个参数要因地制宜。class_names的顺序必须和后续data.yaml里names的顺序完全一致否则类别ID错位训练出来全部是错标。边界剪裁那两行不是多余的Labelimg里偶尔会出现框拖出画布的情况训练时YOLO会把负坐标解析成异常anchor轻则损失曲线跳变重则训练直接崩掉。转换后要抽查几份TXT确认归一化坐标都在01区间并且宽高值不为0。还需要强调一点红外热图本身的色彩通道问题。热像仪直接保存的往往是伪彩色图或8位灰度图而YOLOv12默认输入是三通道。伪彩色图可以直接用但标注时看到的颜色和训练时喂进去的颜色必须一致。如果前期标注用的是灰度图训练也一律用灰度图不要混合。伪彩色里不同调色板对应的温度映射不同混合使用会让模型在色相层面产生虚假关联后面测试时换个调色板就翻车。3. 用YOLOv12在700张热图上训练缺陷检测模型训练命令与关键超参数3.1 环境准备与预训练权重选择YOLOv12的模型权重入口是yolo12n.pt、yolo12s.pt、yolo12m.pt这几个使用Ultralytics框架训练。安装环境前先确认Python版本和PyTorch版本显卡驱动也要提前检查。# Python 3.8到3.11都兼容建议直接用3.10 python -m pip install -U pip python -m pip install -U ultralytics # 验证安装 python -c import ultralytics; print(ultralytics.__version__)如果网络环境受限可以考虑源码安装git clone https://github.com/ultralytics/ultralytics.git cd ultralytics pip install -e .权重选择上700张小数据集不要直接用yolo12x或yolo12l模型容量过大预训练权重虽能压住前期loss但微调阶段极易过拟合。我一般先用yolo12n跑通流程再看mAP决定是否换yolo12s。红外热图的纹理信息密度远低于自然图像yolo12n完全能承接这类任务如果缺陷类别之间外观高度相似比如空鼓和热桥在温度分布上接近再考虑提升到yolo12s。3.2 数据集目录结构与配置文件YOLOv12数据目录保持Ultralytics的标准布局images和labels两个大目录下分别放train和val所有TXT和图片文件名一一对应。目录结构示例如下。datasets/thermal_defect/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── thermal_defect.yaml关键是thermal_defect.yaml的写法它控制训练时读数据的一切路径。配置文件如下# 数据集根目录配置path为相对于YAML文件所在位置的路径 path: ./datasets/thermal_defect train: images/train val: images/val # 类别序号必须与TXT首列数字一一对应 names: 0: void 1: moisture 2: thermal_bridge这里的坑在于path字段的解析方式。Ultralytics在训练时会基于当前工作目录拼接路径如果直接在项目根目录执行命令path写相对路径没问题如果换到其他目录执行路径拼接会出错。稳妥做法是把path写成绝对路径或在执行命令前先cd到数据集所在目录。另外train和val的划分不要随机切按建筑楼栋切。同一个楼的图像放进同一个集合否则验证集会混入训练楼的图像特征mAP虚高但换楼就失效。3.3 训练命令与红外场景下的增强参数调整环境就绪后训练命令如下。yolo detect train \ datathermal_defect.yaml \ modelyolo12n.pt \ epochs300 \ batch16 \ imgsz640 \ device0 \ patience60 \ projectruns_defect \ nameexp01 \ fliplr0.5 \ hsv_h0.0 \ hsv_s0.0 \ hsv_v0.0逐项说明几个关键参数。epochs设300是因为红外小数据集收敛慢但早期停止会因patience60在验证指标60轮不提升时自动结束不一定真的跑到300。batch16在700张图规模下够用显存允许可以提到24或32更大的batch能让BN统计更稳定。imgsz640与常见热像仪分辨率接近如果热图是384×288原尺寸也可以直接设384×288减少缩放带来的温度细节损失但模型输出特征图相应变小需要根据实际缺陷像素尺寸权衡。增强参数是红外训练容易翻车的地方。hsv_h、hsv_s、hsv_v全部设0原因在于热图像的色相和饱和度不代表装饰性颜色而代表温度范围。伪彩色图里一块区域的红色换成蓝色在可见光任务里是正常增强在红外任务里等于把一个高温区变成了低温区模型会学到完全错误的温度语义。fliplr保持0.5因为建筑左右翻转后缺陷语义不变。另外可以额外打开轻度scale和translate增强模拟不同拍摄距离和角度但不要在命令行里写而是写进自定义增强配置避免误改整体增强策略。训练结束后立即看结果而不是急着生产部署。yolo detect val \ modelruns_defect/exp01/weights/best.pt \ datathermal_defect.yaml \ plotsTrueval命令会生成confusion_matrix.png、PR_curve.png、results.png等一系列图。先看PR曲线的走势如果曲线在低置信度区间急剧下降说明模型区分度不足如果右上角饱满说明候选框质量好。再看混淆矩阵里哪些类别互相串比如moisture被普遍识别成thermal_bridge那就要回去看标注是否把两者的边界区域标混了。3.4 判断收敛与过拟合训练曲线不全是看loss很多人只盯训练loss降到多少这在700张图的小数据集上是远远不够的。还要看验证集上的box_loss和cls_loss。常见情况是训练loss持续下降但验证loss在第120轮左右开始反弹这是过拟合的信号。此时应该做的不是继续加epoch而是增加数据增强强度或降低模型复杂度。另一个判断依据是验证集上置信度阈值的分布。模型给出的缺陷框置信度普遍落在0.20.6而不是0.7以上说明特征学习不足。这时优先检查训练集和验证集的图像采集条件差异比如训练集全是晴天夜里拍的验证集混入阴天凌晨的照片模型没见过这类热惯性特征自然给不出高分。把数据按拍摄条件重新分层划分比调参更有效。4. 红外缺陷识别的避坑记录NUC伪影、温度漂移与小目标漏标4.1 现象同一模型白天准确、昼夜切换后误检暴涨现象模型在白天拍摄的热图上识别正常换成夜间或凌晨拍摄的图像时外墙边缘、窗框附近出现大量虚假缺陷框。原因热像仪的非均匀性校正NUC在环境温度变化后产生残留伪影同时夜间建筑表面整体温度接近环境温度缺陷与背景的温差变小信噪比降低白天的特征分布不再适用。解决这类问题的核心在数据分布。将训练集按拍摄时段分层抽样保证夜间样本占30%以上并在标注时把NUC伪影形成的条带排除在框外。另一个实用做法是记录每张图拍摄时的环境温度训练时把环境温度作为上下文信息输入但YOLO本身没有这类机制所以更常用的还是时段分层配合温度归一化预处理。4.2 现象画面固定位置出现整排细长框现象验证时发现模型在图像的同一片区域频繁输出狭长的检测框这些框排列规整形状类似条码。原因热像仪内部快门在校正瞬间产生非均匀性校正残留形成明暗条纹条纹区域在热图上表现为周期性温度跳变模型误把条纹当成热桥或渗漏的线性特征。解决采集时先开机预热10分钟让探测器温度稳定后再拍摄。拍摄过程中听到快门动作声后等待23秒再取帧。数据清洗阶段对每张图做傅里叶变换检查是否存在明显的高频横纵条纹有则剔除或裁剪掉条纹区域。标注时遇到条纹覆盖的缺陷位置优先从素材库里替换另一时段的图像而不是强行标注。4.3 现象小缺陷框召回率几乎为零现象模型对整面墙上的大范围空鼓、渗漏识别较好但对屋檐下的小空鼓、局部渗水点几乎无输出验证集上的召回率可能不到30%。原因一方面小目标在热图上像素少温度过渡区域占比大特征不明显另一方面标注阶段容易漏标小缺陷700张图标注量巨大眼睛疲劳后最先被漏掉的就是小目标。解决标注流程改成两轮。第一轮先把大缺陷全部标完第二轮把图像放大24倍逐区域检查小目标。我常用Labelimg的窗口缩放功能把图像局部放大到接近原图3倍再补标。训练层面把imgsz从640提到768能直接增加小目标在特征图上的映射尺寸。如果小目标仍然漏检就用滑窗推理把原图切成640×640的重叠块分别检测最后合并NMS结果。4.4 现象16位温度数据转8位后细节全丢现象训练时loss下降正常但验证集mAP徘徊在低位人工看图能明显辨别缺陷模型却学不到。原因热像仪原始数据是16位或14位温度数据很多数据集的原始图像在转8位时用了全局最小最大温窗压缩。建筑场景动辄050℃跨度缺陷温差只有12℃压缩后缺陷信号淹没在量化噪声里肉眼还能勉强看出轮廓CNN已经分不清了。解决转换8位图时不要用全局温窗而是固定一个建筑检测专用的温度范围。常见做法是设定545℃在这个范围内做线性映射低于5℃按5℃处理高于45℃按45℃处理。具体温窗还要结合实际季节和地域微调夏天可以把上限提到55℃。转换后的图像要对比原始温度矩阵确认缺陷区域的灰度对比度能被人眼清晰感知。4.5 现象测试集上误检集中在金属门窗和玻璃幕墙现象模型把窗外金属栏杆、铝塑板接缝、玻璃反射光斑识别为缺陷。原因金属和玻璃发射率低会反射周围环境的热辐射热图上呈现的温度并非自身真实温度而是周围建筑、天空、人体的反射温度。这部分在标注阶段往往被忽略模型把反射热源当成了缺陷。解决对训练图中的高反射区域做掩膜处理避免标注这些区域同时在增强环节加入局部模糊模拟反射干扰。推理阶段可以结合可见光图像的语义分割结果把玻璃幕墙和金属构件区域直接遮罩不让检测框落在这些区域。严格一点的做法是用双波段相机同步采集红外和可见光在推理后处理时把可见光识别出的非建筑表面区域过滤掉。5. 复现91.5%识别率的验证流程和一个能继续提升的推理习惯5.1 先核对指标口径91.5%到底是mAP还是召回率判断模型是否达到91.5%之前先把指标口径对齐。目标检测里91.5%通常指mAP50即在IoU阈值为0.5时所有类别的平均AP也有项目把“识别率”定义为Recall两者数值不能直接比较。复现时用下面的命令先看验证集指标表。yolo detect val \ modelruns_defect/exp01/weights/best.pt \ datathermal_defect.yaml \ conf0.25 \ iou0.5 \ plotsTrue指标含义数据集中常见数值Precision检出的框中真正缺陷的比例85%95%Recall真实缺陷中被检出的比例80%92%mAP50IoU阈值0.5下所有类别的平均精度85%92%mAP50-95多IoU阈值下的平均精度60%75%如果mAP50接近91.5%说明模型在大缺陷、清晰温差场景下表现良好如果mAP50-95明显低说明检测框位置精度不足缺陷边界贴合不好。实际部署时应关注后者因为框偏移会影响面积计算和缺陷等级判定。5.2 跨楼栋、跨时段验证不要把验证集当作最终结论数据集的验证集即使做了分层划分也只是证明了模型在同类拍摄条件下的表现。真正有效的验证流程是单独留一栋楼、一个从未出现在训练和验证中的楼整套流程跑一遍推理。yolo detect predict \ modelruns_defect/exp01/weights/best.pt \ source./unknown_building_night/ \ imgsz640 \ conf0.25 \ save_txtTrue \ save_confTrue推理结果里每行TXT记录的是边界框和置信度统计这批结果时注意按楼栋汇总。如果换楼之后mAP掉10个点以上问题几乎都出在拍摄距离和拍摄角度的分布差异上而不是模型本身。此时回看训练集的标注框尺度分布用脚本统计所有框的宽高占比如果绝大多数框都在5%15%的图像宽度范围内说明训练分布过窄。补充不同距离的图像或采用多尺度训练是解决这类泛化问题的最直接手段。5.3 断点微调与滑窗推理把复杂场景的检测结果再稳一档700张图的训练在早期停止后通常还有余力。断点微调的做法保留原有训练状态只改变学习率和局部参数避免从头再来。命令如下。yolo detect train \ datathermal_defect.yaml \ modelruns_defect/exp01/weights/best.pt \ resumeTrue \ epochs380 \ lr00.0005 \ lrf0.01 \ patience80resumeTrue会从上次中断的epoch继续同时读取原有优化器状态。lr0降到0.0005是为了在小学习率下精细调整特征lrf保留0.01让学习率在后期进一步衰减。断点微调常见效果是mAP小幅上涨0.52个点主要是边界框回归更稳定。滑窗推理针对的是外立面这种超长图。热像仪拍出的单张图像宽高比可能达到41甚至更极端直接压到640×640会让缺陷失去空间尺度。做法是把长图切成640×640的重叠块每块单独推理再做NMS合并。伪代码如下。import cv2 from ultralytics import YOLO model YOLO(runs_defect/exp01/weights/best.pt) def slide_infer(image_path: str, crop: int 640, stride: int 480, conf: float 0.25): img cv2.imread(image_path) h, w img.shape[:2] detections [] for top in range(0, max(1, h - crop 1), stride): for left in range(0, max(1, w - crop 1), stride): tile img[top:top crop, left:left crop] result model(tile, confconf, verboseFalse) for box in result[0].boxes: x1, y1, x2, y2 box.xyxy[0].tolist() score float(box.conf[0]) cls_id int(box.cls[0]) detections.append((x1 left, y1 top, x2 left, y2 top, score, cls_id)) # 省略NMS合并步骤实际应按类别做IoU合并 return detections滑窗推理的代价是计算量成倍增加4000像素长的图要切成两轮十几块。一个替代方案是先用整图推理找出高置信度区域只对低置信度但不该漏检的区域做二次裁剪放大。把这类策略固化到推理脚本里是提高红外热成像缺陷识别稳定性的有效习惯我的经验是它通常能再把整体识别率拉高13个点同时不牺牲推理速度。我保留的一个习惯是训练完成后不急着看mAP先把验证集里所有的误检和漏检图单独导出来按“拍摄时段、缺陷类型、缺陷尺寸、表面材料”四个维度登记跑两轮之后能准确说出当前模型的短板分布。这个习惯帮我在不同建筑数据集上省掉了大量盲目调参的时间。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →