资讯动态

红外多目标检测数据集:1000张图三套标签与训练避坑指南

发布时间:2026/10/13 20:59:19 来源:尧图企业网站定制
简介本资源为面向目标检测学习者的YOLO红外多目标检测数据集适用于红外场景下的算法训练、课程设计与科研实验可解决红外图像样本稀缺、标注格式不统一的问题。压缩包共2000个文件约96.39MB包含1000张真实场景红外图片以及vocxml、cocojson和yolotxt三种格式标签另附yaml配置文件、划分脚本与教程页面方便直接接入YOLO系列模型训练。资源还提供训练集、验证集、测试集划分脚本可按需生成ImageSets下的txt文件并附Windows与Linux环境搭建、训练案例教程帮助读者快速跑通从环境配置到模型训练的全流程。目前已有458人学习下载适合具备一定深度学习基础、希望快速上手红外多目标检测的开发者与研究人员参考使用。1. 红外多目标检测数据集为什么1000张图配三套标签才是能跑通的关键做红外目标检测的同行大多有过这种体验模型在可见光数据集上指标漂亮一换到红外图像就集体翻车白天还凑合夜间或低照度场景下召回率断崖式下跌。问题往往不在网络结构而在数据——红外图像对比度低、纹理弱、目标边缘模糊如果标签格式不统一、划分不合理训练过程就是一场玄学。这个标题指向的正是一套面向红外多目标检测的完整数据工程方案1000张红外图片同时提供VOC、COCO、YOLO三种格式标签附带数据集划分脚本和训练教程。它解决的不是“有没有数据”的问题而是“数据能不能直接喂给不同框架、划分是否可复现、训练配置是否有参考”的问题。适合正在做红外安防、夜间巡检、嵌入式视觉检测的工程师也适合想从可见光检测迁移到红外域的学生和研究者。下面按数据落地路径拆开讲。2. 红外数据集的三套标签格式VOC、COCO、YOLO到底怎么选2.1 三种格式的本质差异与适用框架VOC格式以XML文件描述每张图的标注信息结构清晰适合用PyTorch的torchvision.datasets.VOCDetection直接加载也方便做数据增强前的可视化检查。COCO格式用单个JSON文件管理所有图像的标注字段包含images、annotations、categories适合pycocotools评估和Detectron2、MMDetection这类框架。YOLO格式则是每张图对应一个TXT文件每行class_id x_center y_center width height坐标全部归一化到0到1之间直接适配YOLOv5/v8/v11的训练管线。选型逻辑很简单如果你用YOLO系列做训练和部署YOLO格式最省事如果要做多模型对比或使用MMDetectionCOCO格式更通用VOC格式则适合作为中间转换层因为它的XML结构最容易解析和校验。这套数据集同时提供三种格式意味着你不需要自己写转换脚本省去了格式对齐时最容易出错的环节。2.2 用脚本在三种格式之间做校验和转换即便数据集已经提供了三种格式仍然建议自己跑一遍校验脚本确认标注框没有越界、类别ID没有错位、图像文件名和标签文件名严格对应。下面是一个Python校验脚本同时输出三种格式的统计信息。import os import xml.etree.ElementTree as ET import json from pathlib import Path # 配置路径根据实际解压后的目录结构调整 DATASET_ROOT Path(./infrared_dataset) VOC_DIR DATASET_ROOT / VOC / Annotations YOLO_DIR DATASET_ROOT / YOLO / labels COCO_JSON DATASET_ROOT / COCO / annotations.json IMG_DIR DATASET_ROOT / images def check_voc(voc_dir): 检查VOC XML统计类别、检测宽高是否越界 stats {} for xml_file in voc_dir.glob(*.xml): tree ET.parse(xml_file) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) for obj in root.findall(object): name obj.find(name).text stats[name] stats.get(name, 0) 1 bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) # 越界检查红外图像边缘目标容易标出界 if xmin 0 or ymin 0 or xmax w or ymax h: print(f[越界] {xml_file.name}: ({xmin},{ymin},{xmax},{ymax}) 图像尺寸 {w}x{h}) return stats def check_yolo(yolo_dir): 检查YOLO TXT确认坐标在0-1之间类别ID为整数 for txt_file in yolo_dir.glob(*.txt): with open(txt_file, r) as f: for line_num, line in enumerate(f, 1): parts line.strip().split() if len(parts) ! 5: print(f[格式错误] {txt_file.name} 第{line_num}行: 字段数{len(parts)}) continue cls_id int(parts[0]) coords [float(x) for x in parts[1:]] if any(c 0 or c 1 for c in coords): print(f[归一化异常] {txt_file.name} 第{line_num}行: {coords}) def check_coco(coco_json): 检查COCO JSON确认image_id和annotation对应关系 with open(coco_json, r) as f: data json.load(f) img_ids {img[id] for img in data[images]} for ann in data[annotations]: if ann[image_id] not in img_ids: print(f[孤立标注] annotation id{ann[id]} 指向不存在的image_id{ann[image_id]}) print(fCOCO统计: {len(data[images])}张图, {len(data[annotations])}个标注, {len(data[categories])}个类别) if __name__ __main__: print( VOC校验 ) voc_stats check_voc(VOC_DIR) print(fVOC类别分布: {voc_stats}) print( YOLO校验 ) check_yolo(YOLO_DIR) print( COCO校验 ) check_coco(COCO_JSON)这段脚本的逻辑说明check_voc遍历所有XML文件读取图像宽高和每个目标框的坐标重点检查xmax w或ymax h的情况红外图像中热源目标靠近画面边缘时容易出现标注越界。check_yolo检查每行是否恰好5个字段坐标是否归一化到0到1类别ID是否为整数。check_coco验证标注中的image_id是否都能在images列表中找到对应项。参数方面DATASET_ROOT需要根据实际解压路径修改如果目录名不同同步调整VOC_DIR、YOLO_DIR、COCO_JSON三个变量即可。2.3 划分脚本为什么随机划分在红外数据集上会出问题数据集划分看似简单但红外多目标检测场景下有几个坑同一场景的连续帧如果被随机分到训练集和验证集验证指标会虚高某些类别样本极少随机划分可能导致验证集中该类样本数为零。常见做法是按场景或按时间戳做分组划分保证同一场景的图片只出现在一个子集中。import random from pathlib import Path from collections import defaultdict def split_dataset(img_dir, label_dir, output_dir, train_ratio0.7, val_ratio0.2, test_ratio0.1, seed42): 按类别分布做分层划分避免验证集中某些类别缺失。 输入img_dir图像目录label_dir YOLO标签目录 输出output_dir下生成train.txt/val.txt/test.txt每行是图像绝对路径 random.seed(seed) img_files sorted(img_dir.glob(*.jpg)) sorted(img_dir.glob(*.png)) # 统计每张图包含的类别用于分层 img_to_classes {} for img_path in img_files: label_path label_dir / (img_path.stem .txt) classes set() if label_path.exists(): with open(label_path, r) as f: for line in f: if line.strip(): classes.add(int(line.split()[0])) img_to_classes[img_path] classes # 按类别组合分组保证每个组合在训练集中有代表 group_dict defaultdict(list) for img_path, classes in img_to_classes.items(): key tuple(sorted(classes)) group_dict[key].append(img_path) train, val, test [], [], [] for key, paths in group_dict.items(): random.shuffle(paths) n len(paths) n_train max(1, int(n * train_ratio)) n_val max(1, int(n * val_ratio)) if n 3 else 0 train.extend(paths[:n_train]) val.extend(paths[n_train:n_train n_val]) test.extend(paths[n_train n_val:]) output_dir Path(output_dir) output_dir.mkdir(parentsTrue, exist_okTrue) for name, data in [(train, train), (val, val), (test, test)]: with open(output_dir / f{name}.txt, w) as f: for p in data: f.write(str(p.resolve()) \n) print(f{name}: {len(data)}张) if __name__ __main__: split_dataset( img_dirPath(./infrared_dataset/images), label_dirPath(./infrared_dataset/YOLO/labels), output_dirPath(./infrared_dataset/splits), train_ratio0.7, val_ratio0.2, test_ratio0.1 )逻辑说明脚本先统计每张图包含的类别集合按类别组合分组再在每个组内按比例划分。这样做的目的是保证稀有类别在训练集和验证集中都有出现。参数方面train_ratio、val_ratio、test_ratio三者之和应为1.0seed固定后划分结果可复现。如果某个类别组合只有1张图脚本会强制放入训练集验证集和测试集可能缺少该类这是小样本红外数据集的固有限制需要在训练时通过类别权重或重采样来补偿。3. 用YOLO格式标签跑通红外多目标检测训练3.1 数据配置文件与目录结构YOLO系列训练需要两个YAML文件数据集配置文件和模型配置文件。数据集配置文件指定训练、验证、测试图像的路径以及类别名称和数量。目录结构建议如下infrared_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── infrared.yamlinfrared.yaml内容示例path: ./infrared_dataset train: images/train val: images/val test: images/test nc: 4 names: 0: person 1: vehicle 2: animal 3: other_heat_source这里nc是类别数names按类别ID顺序列出。注意红外数据集的类别定义要和标注时的类别ID严格一致否则训练时会出现标签错位表现为损失下降但mAP始终为零。3.2 训练命令与关键参数设置以YOLOv8为例训练命令如下yolo detect train \ data./infrared_dataset/infrared.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ warmup_epochs3 \ patience20 \ device0 \ project./runs/infrared \ nameexp1参数说明imgsz640是输入分辨率红外图像如果原始尺寸较小可以适当降低到416或320以加快训练batch16根据显存调整显存不足时降到8或4lr00.01是初始学习率红外数据集样本量少时建议降到0.001patience20表示20个epoch验证指标不提升就早停防止过拟合warmup_epochs3让学习率在前3个epoch从低到高预热避免初期梯度震荡。如果训练损失正常下降但验证mAP波动大优先检查验证集划分是否合理而不是盲目调学习率。3.3 从VOC或COCO格式转YOLO的转换脚本如果只想用YOLO格式训练但手头只有VOC或COCO标注可以用以下脚本转换。VOC转YOLO的核心是把绝对坐标转成归一化中心坐标import xml.etree.ElementTree as ET from pathlib import Path def voc_to_yolo(voc_dir, img_dir, output_dir, class_list): VOC XML转YOLO TXT class_list: 类别名称列表顺序决定类别ID output_dir Path(output_dir) output_dir.mkdir(parentsTrue, exist_okTrue) for xml_file in Path(voc_dir).glob(*.xml): tree ET.parse(xml_file) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_list: continue cls_id class_list.index(name) bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 归一化中心坐标 x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h # 裁剪到0-1防止浮点误差导致越界 x_center min(max(x_center, 0), 1) y_center min(max(y_center, 0), 1) bw min(max(bw, 0), 1) bh min(max(bh, 0), 1) lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}) with open(output_dir / (xml_file.stem .txt), w) as f: f.write(\n.join(lines)) if __name__ __main__: voc_to_yolo( voc_dir./infrared_dataset/VOC/Annotations, img_dir./infrared_dataset/images, output_dir./infrared_dataset/YOLO/labels, class_list[person, vehicle, animal, other_heat_source] )逻辑说明class_list的顺序必须和训练时YAML中的names一致否则类别ID会错位。归一化后做了0到1的裁剪防止浮点计算误差导致坐标略微超出边界。转换完成后建议用第2章的校验脚本再跑一遍确认没有格式错误。4. 红外多目标检测的避坑与排查记录4.1 训练损失下降但mAP为零现象训练日志中box_loss和cls_loss持续下降但验证集mAP始终为0或接近0。原因通常是类别ID错位或标签文件路径配置错误。YOLO读取标签时如果labels/train/下没有对应图像名的TXT文件会静默跳过该图导致模型只学到背景。解决检查infrared.yaml中train和val路径是否指向包含图像的目录确认每张图像都有同名TXT标签且TXT中类别ID从0开始连续编号。4.2 验证集指标虚高但测试集崩盘现象验证集mAP达到0.8以上换到测试集或实际场景中掉到0.3以下。原因通常是同一场景的连续帧被分到了训练集和验证集模型记住了场景背景而非目标特征。解决用第2章的分层划分脚本按类别组合分组划分或者手动按场景文件夹划分保证同一场景只出现在一个子集中。4.3 红外图像标注框越界导致训练报错现象训练启动时报AssertionError或坐标越界警告。原因红外图像中热源目标靠近边缘时标注框的xmax或ymax可能等于或略大于图像宽高。解决用第2章的VOC校验脚本找出越界标注手动修正或裁剪到图像边界内。YOLO格式虽然做了归一化裁剪但VOC和COCO格式不会自动裁剪需要在转换前处理。4.4 小目标漏检严重现象红外图像中远距离行人或车辆漏检率高。原因红外小目标对比度低下采样后特征几乎消失。解决训练时提高输入分辨率到1280或在模型配置中增加P2小目标检测层。如果显存不够可以用切片推理把大图切成小图分别检测再合并结果。4.5 类别不平衡导致稀有类别召回率低现象某些类别样本极少训练后该类AP远低于其他类别。原因损失函数被多数类主导。解决在YOLO训练中启用类别权重或对稀有类别做过采样。更直接的办法是在数据增强时对稀有类别图像做更多变换增加其出现频率。5. 红外检测的进阶技巧从能跑到跑得稳训练跑通只是第一步真正落地时还要解决跨场景泛化和推理速度的问题。一个实用技巧是温度归一化不同红外相机输出的灰度范围不同直接训练会导致模型对绝对灰度值过拟合。可以在数据加载时做逐图归一化把灰度拉伸到0到255或做直方图均衡化。下面是一个在YOLO训练管线中插入自定义归一化的示例import cv2 import numpy as np def infrared_normalize(img_path): 红外图像归一化先做百分位裁剪再拉伸到0-255 避免极端热源像素拉偏整体对比度 img cv2.imread(str(img_path), cv2.IMREAD_GRAYSCALE) # 百分位裁剪去掉最高和最低1%的像素 low, high np.percentile(img, (1, 99)) img np.clip(img, low, high) # 拉伸到0-255 img ((img - low) / (high - low 1e-6) * 255).astype(np.uint8) # 转三通道适配YOLO预训练权重 img cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) return img这个函数可以替换YOLO数据加载中的图像读取逻辑或者在预处理阶段批量处理。参数方面百分位裁剪的1和99可以根据实际图像调整如果图像中热源目标占比很小可以收紧到2和98。另一个技巧是验证时用测试集做一次完整推理统计每个类别的AP和AR而不是只看总体mAP。如果某个类别AR低但AP高说明该类别漏检多但检出的都准需要提高召回如果AP低但AR高说明误检多需要提高分类阈值。我自己的习惯是每次训练完先看混淆矩阵再看每个类别的PR曲线最后才看总体mAP。红外数据集上总体mAP容易被多数类拉高掩盖稀有类别的翻车。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑