
简介这是一份面向计算机视觉研究者和深度学习学习者的红外小目标飞机检测数据集聚焦红外场景下低空小尺寸飞机的识别任务尤其适合小目标检测、红外图像分析与模型轻量化等方向。包内按YOLO格式划分训练集与验证集配置文件标明训练集包含16551张图像路径验证集包含4952张图像路径类别为单一飞机可直接用于YOLO系列等主流目标检测框架的训练与验证。压缩包共包含2000个文件以926个xml标注文件、926个txt标签文件、147个bmp红外图像文件和一个cache缓存文件为主体其中xml可转为VOC格式txt为YOLO训练所需的标签bmp提供原始红外小目标图像整体大小约37.4MB。目前已有169人学习使用入手即可获得完整标注、划分配置与原始图像能够直接开展算法对比实验有效节省自行整理和标注数据的时间对关注红外弱小目标检测的研究者尤具参考价值。1. 红外小目标飞机检测数据集一份能直接开训的 YOLO 格式底料做红外弱小目标检测的同行应该都有过这种经历算法模型选好了loss 设计好了结果卡在数据上——自己标红外图费眼睛不说小目标在 256×256 里就占几个像素框稍微偏一点 IoU 直接掉到零点几标注质量根本没法保证。这份 红外小目标飞机检测数据集 train 解决的就是这个痛点它是一个按 VOC2007 目录组织、已经转好 YOLO 格式标注的飞机检测数据集训练集 16551 张、验证 4952 张全部是红外场景下的飞机目标类别就一个air。拿到手之后不需要再做格式转换直接用 YOLOv5、YOLOv8 或者 mmrotate 的训练脚本就能跑起来。如果你正在做红外告警、机场净空监测、低慢小目标检测这类项目或者想用一个干净的单类红外数据集来调通自己的训练流程这份数据是很好的起点。2. 数据集的真实构成VOC 目录、YOLO 标签和那 16551 张图的可信度2.1 目录结构先看明白为什么说它是 VOC 组织格式从摘要里的配置信息能推断出这个数据集的落盘方式。train: ./data/VOC2007/train.txt和val: ./data/VOC2007/test.txt这两行说明图片真实存放路径在 VOC2007 目录体系下而 train.txt / test.txt 是 YOLO 系列训练框架读取的图片清单文件。这也是 YOLOv5 / YOLOv8 官方数据组织方式之一从官方coco128.yaml的写法沿袭而来。常见做法是这样三步# 第一步看 train.txt 的前几行确认图片路径是绝对路径还是相对路径 head -n 5 train.txt # 第二步确认 label 文件是否和图片一一对应 find . -name *.bmp | wc -l find . -name *.txt | wc -l # 第三步确认 JPEGImages 和 labels 目录存在且命名规则匹配 ls ./data/VOC2007/JPEGImages | head -n 10 ls ./data/VOC2007/labels | head -n 10这里 train.txt 里每行是图片的完整或相对路径YOLO 会拿这个路径去找图片然后把图片路径里的images替换成labels来找标注文件。这是 YOLOv5 系列框架约定好的自动映射逻辑不需要你手动写代码去配对。所以关键检查点在于图片扩展名是.bmp还是.jpglabels 目录下是不是同名.txt。这个数据集里正文列出的是683.bmp、956.bmp、898.bmp这类纯数字命名说明原始采集就做了匿名处理。数据集项目数值说明图片格式bmp红外原始图常见格式不经过有损压缩训练集规模16551 张对应 train.txt验证集规模4952 张对应 test.txt目标类别数1 类names 中只有一个air标注格式YOLO txt每行 class_id x_center y_center width height归一化从这份配置看训练和验证比大约是 76.9% / 23.1%这个比例在单类检测任务里是比较健康的验证集足够大不会出现训练集涨点、验证集波动剧烈的局面。2.2 YOLO 标签格式还原红外小目标的标注粒度所有 YOLO 格式标注的本质是归一化坐标加宽高即每个目标占一行五个数字分别是类别序号、框中心 x、框中心 y、框宽、框高全部除以图片宽高做了归一化。这个数据集只有air一个类所以类别序号恒为 0。它的目标框是小目标尺度在红外图像中飞机通常只占几十个像素甚至十几个像素归一化后宽高往往在 0.05 以下。# 随便挑一张图的标签看一眼分布 import os import numpy as np labels_dir ./data/VOC2007/labels label_files os.listdir(labels_dir) sample np.loadtxt(os.path.join(labels_dir, label_files[0])) print(该图目标数量:, sample.shape) if sample.ndim 2: # 每一列分别是 class_id, x_center, y_center, width, height print(归一化宽高范围:, sample[:, 3].min(), sample[:, 3].max(), sample[:, 4].min(), sample[:, 4].max())跑完这段脚本能看到目标尺寸分布。如果归一化后的 w 和 h 大多数在 0.02 到 0.08 之间说明这张红外图是典型的宽场景、远距离目标。这种数据不能直接套用 COCO 上预训练模型的默认 anchor 尺度后面训练时需要对 anchor 做调整或者改用 anchor-free 的检测头。这个数据集跟常见的 CCD 可见光数据集最大的不同在于红外图像是单通道灰度图目标与背景的对比度由温差决定而不是颜色或纹理。因此做数据增强时要小心颜色抖动类操作它们对红外图像基本无效反而可能把目标边缘抹淡。后面第 4 章讲训练参数时会具体说怎么调。3. 把数据挂进训练框架从 YAML 配置到起训一条龙3.1 挂载到 YOLOv8一份 YAML 搞定训练集与验证集拿到这份数据后第一步不是写代码而是把数据挂载到检测框架的接口上。YOLOv8 和 YOLOv5 都支持通过一个 YAML 文件声明数据和模型配置。这里我以 YOLOv8 为例因为它的 detect 模块对红外小目标的适配更友好# infrared_air.yaml train: ./data/VOC2007/train.txt val: ./data/VOC2007/test.txt # 类别数 nc: 1 # 类别名 names: [air]注意如果 train.txt 里写的是绝对路径那么 YAML 里也用绝对路径如果是相对路径YAML 路径是相对你执行训练命令的工作目录而言的建议直接在项目根目录下执行避免嵌套路径导致的 FileNotFoundError。然后直接起训练yolo detect train datainfrared_air.yaml modelyolov8n.pt epochs100 imgsz640 batch16这里modelyolov8n.pt表示加载 COCO 预训练权重做迁移学习虽然 COCO 里没有红外飞机类别但浅层特征边缘、角点、明暗对比是可以迁移的。imgsz640是输入分辨率如果你的红外原图本身是 640×512 或 320×256建议直接读原图尺寸训练不要强行 resize 到 640 以上因为红外小目标放大后容易模糊。3.2 自定义 Dataset 加载绕过 YOLO 框架直接看图如果你不想用现成的 detect 脚本而是想自己写训练循环、控制数据增强策略可以自己加载这个数据集。关键点在于读取 train.txt 的路径列表然后用 OpenCV 读灰度图配合解析同名 txt 标签做可视化验证# custom_dataset.py import cv2 import numpy as np from pathlib import Path def load_infrared_dataset(list_file, labels_root): with open(list_file, r) as f: img_paths [line.strip() for line in f.readlines() if line.strip()] samples [] for img_path in img_paths: img_path Path(img_path) # 把图片路径中的 images 目录替换为 labels 目录得到标注路径 label_path Path(str(img_path).replace(images, labels)).with_suffix(.txt) if not label_path.exists(): print(f警告: {label_path} 不存在跳过) continue samples.append((str(img_path), str(label_path))) return samples def draw_yolo_boxes(img, label_path, img_shape): h, w img_shape[:2] boxes np.loadtxt(label_path).reshape(-1, 5) for box in boxes: x_c, y_c, bw, bh box[1] * w, box[2] * h, box[3] * w, box[4] * h x1 int(x_c - bw / 2) y1 int(y_c - bh / 2) x2 int(x_c bw / 2) y2 int(y_c bh / 2) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 1) return img if __name__ __main__: samples load_infrared_dataset(./data/VOC2007/train.txt, ./data/VOC2007/labels) print(有效样本数:, len(samples))这段代码做了两件事一是把 train.txt 的图片路径映射到 labels 目录下同名 txt二是把 YOLO 归一化坐标还原成像素坐标画框便于人工检查标注是否偏离目标。开发阶段建议先跑这个脚本随机抽查 50 张图做可视化确认标注质量没问题再投喂给模型训练这一步能避免训练半天发现标签错位的问题。3.3 VOC 格式转 YOLO 的兜底方案./data/VOC2007/这个路径暗示原始标注可能保留了 VOC 的 XML 格式Annotations 目录如果你后续要改成多类检测或者用 Detectron2、mmdetection 这类框架训练它们默认吃 COCO JSON 或 VOC XML这时候需要把 YOLO txt 导回 VOC XML。比较省事的方式是反向解析# 用 roboflow 提供的转换工具一条命令把 YOLO 转成 VOC pip install pyyaml python -c from roboflow import Roboflow; ... # 需要联网取工具包不过更推荐的离线做法是直接写脚本遍历 labels 目录每读一个 txt 生成一个 XML根节点是annotation子节点object里填nameair/name和bndbox坐标值。坐标要先乘回原图宽高再转成整数。这部分只在你换框架时才用得上如果你一直跑 YOLO 系列完全可以跳过。4. 训练参数怎么定红外小目标的特殊调参路线4.1 输入尺寸和 anchor小目标检测的玄学在这里单类小目标检测跟通用检测最大的区别在 anchor 尺度。COCO 预训练模型的 anchor 是为平均 50×50 像素以上的目标设计的对于归一化宽高只有 0.03 的红外飞机目标原始 anchor 完全失效。YOLOv8 是 anchor-free 的其实没有 anchor 参数要调但 YOLOv5 需要。在 YOLOv5 里可以关掉 autoanchorpython train.py --data infrared_air.yaml --cfg yolov5n.yaml \ --weights yolov5s.pt --img 640 --batch 16 --epochs 100 \ --noautoanchor关闭 autoanchor 后YOLOv5 会使用配置文件里的默认 anchor此时小目标的召回一般不会太差因为检测头本身有 80×80 的细粒度特征图对应原图 8×8 像素的区域能覆盖大多数红外小目标。如果发现漏检严重再用 k-means 重新聚类 anchor# 在 YOLOv5 utils/autoanchor.py 中运行 k-means python utils/autoanchor.py --data infrared_air.yaml输出的新 anchor 会打印在终端把它回填到模型 yaml 配置里再重新训练。这种做法对 YOLOv5 来说效果立竿见影聚类出来的 anchor 会更贴近归一化宽高 0.02~0.06 的真实目标分布。4.2 训练轮次、batch size、学习率权衡红外小目标数据单类、背景相对单一训练不需要像 COCO 那样跑 300 轮一般 100~150 轮就够了。batch size 取决于显存yolov8n 在 16G 显卡上 batch32 没问题如果显存小batch8 也行但要同步把学习率调低。给一个能直接用的组合输入尺寸imgsz640或原图分辨率如果原图是 512 就 512batch size16 到 32 之间用梯度累积补偿初始学习率YOLOv8 默认lr00.01跑小数据集建议降到0.001防止前期震荡数据增强关闭 mosaic 或者把 mosaic 概率设为 0.3因为红外小目标拼接后容易重叠、丢失目标类别权重单类不存在类别不平衡不需要配class_weightsyolo detect train datainfrared_air.yaml modelyolov8n.pt \ epochs150 imgsz640 batch24 lr00.001 \ mosaic0.3 close_mosaic15close_mosaic15表示最后 15 轮关闭 mosaic 增强。这个参数是 YOLOv8 里专门为小目标加的因为 mosaic 拼图产生的伪边界容易让模型学到错误的上下文。同样的逻辑也适用于 YOLOv5对应参数是--mosaic 0.3但没有 close_mosaic 这个选项只能自己在训练后期手动减小。4.3 数据增强配置别照搬 COCO 习惯COCO 上跑得好的增强策略在红外数据集上可能翻车。具体来说HSV 变换、随机色彩抖动这些增强在可见光数据集上能提升泛化能力但红外图是单通道HSV 只会改变灰度映射甚至会把目标和背景的对比度拉低。常见做法是只保留空间类增强增强操作是否建议原因随机翻转建议飞机朝向不固定翻转不改变目标形态随机缩放建议0.5~1.5 倍模拟不同距离下的目标尺度随机平移建议±10%增强位置泛化HSV 变化不建议红外单通道无意义Mosaic谨慎0.3 以下拼接导致小目标重叠MixUp不建议目标透明化小目标直接消失YOLOv8 的增强参数可以在 yaml 里关闭颜色类增强只开几何增强这样训练稳定性会好很多val mAP 的抖动也会小。5. 避坑指南红外小目标数据集训练的四个高频故障5.1 训练报错 No labels found in ... 但标签目录明明是满的现象启动训练后终端打印警告提示 train 目录下没找到标签训练直接卡住或精度恒为 0。原因YOLO 框架依靠图片路径到标签路径的字符串映射。如果图片在JPEGImages标签在labels而 train.txt 里的路径是./data/VOC2007/JPEGImages/683.bmp框架会把JPEGImages替换成labels得到./data/VOC2007/labels/683.txt。一旦你改了目录名比如把 labels 改成 Label映射链就断了。解决让 train.txt 里的路径保持JPEGImages和labels这种成对命名或者将 train.txt 改为绝对路径后重新检查。5.2 验证集 mAP 很高但实际图片漏检严重现象训练过程显示 mAP0.5 达到 0.9 以上但拿到真实场景红外图测试时发现目标漏检尤其是极小目标。原因数据集的验证集和训练集来自同一采集批次背景分布高度相似模型学到的多半是背景模式而不是目标本质特征。解决调整训练策略将imgsz提高从 512 到 640打开多尺度训练--multi-scale如果仍然漏检检查标签里是否有大量宽度小于 3 像素的目标这类目标在下采样到 640 时可能只剩 1 个像素需要把网络下采样倍数从 32 改成 16 或 8。5.3 训练 loss 下降到 0.02 但检测框定位偏半个机身现象分类置信度正常但输出的框中心点稳定偏移IoU 上不去。原因标签中心点与真实目标重心不一致标注时往往框的是整个飞机轮廓而红外图像上飞机最亮的部分是发动机喷口模型学到的是高亮区域位置与框中心偏移了。解决做一次标签清洗用脚本把所有框稍微收缩 10% 到 20%让框贴合目标核心区域。这对小目标检测反而常常提高 mAP因为去除了背景干扰。# shrink_boxes.py: 收缩所有标注框 15% import numpy as np from pathlib import Path label_dir Path(./data/VOC2007/labels) for txt_file in label_dir.glob(*.txt): boxes np.loadtxt(txt_file).reshape(-1, 5) if boxes.size 0: continue boxes[:, 3] * 0.85 boxes[:, 4] * 0.85 # 保存前注意检查是否越界 boxes[:, [1, 3]] np.clip(boxes[:, [1, 3]], 0, 1) boxes[:, [2, 4]] np.clip(boxes[:, [2, 4]], 0, 1) np.savetxt(txt_file, boxes, fmt%.6f) print(完成)收缩框之后要重新可视化一遍确认目标没有被切掉一半再做训练。5.4 数据增强后目标直接融化在背景里现象训练时 mAP 波动特别大早期上升后突然掉点。可视化增强输出后发现目标在增强图上几乎看不见。原因红外图对比度本来就低再做高斯模糊、随机擦除等增强时小目标被当成噪声抹掉了。解决在 YOLOv8 的增强参数里关闭hsv_h、hsv_s、hsv_v也不要用erasing类增强如果必须用随机擦除擦除面积比控制在 0.05 以内。6. 从零到一出图跑完一次完整训练并验证落盘结果数据集本身是训练流程的地基但落盘验证才见真章。建议你按照下面流程强制走一遍确保拿到权重后能直接部署。先做数据完整性校验确保训练集和测试集都没有空标注或越界标注# validate_dataset.py import numpy as np from pathlib import Path def validate_label_file(txt_path, img_w, img_h): boxes np.loadtxt(txt_path).reshape(-1, 5) if boxes.size 0: return False # 检查归一化坐标是否越界允许 0~1 之间 if (boxes[:, 1:] 0).any() or (boxes[:, 1:] 1).any(): return False return True train_list Path(./data/VOC2007/train.txt).read_text().splitlines() bad_count 0 for line in train_list: img_path Path(line.strip()) if not img_path.exists(): bad_count 1 continue label_path Path(str(img_path).replace(JPEGImages, labels)).with_suffix(.txt) if not label_path.exists(): bad_count 1 print(f异常样本数: {bad_count} / {len(train_list)})然后用 YOLOv8 的val模式验证跑完训练后的 best.pt 权重yolo detect val datainfrared_air.yaml modelruns/detect/train/weights/best.pt \ imgsz640 batch8验证输出的 mAP 和混淆矩阵会写入runs/detect/val目录打开 confusion_matrix.png 能直接看到air这一类别的漏检率。正常收敛时 mAP0.5 在 0.85 以上mAP0.5:0.95 在 0.6 左右。如果 mAP0.5 很高而 mAP0.5:0.95 很低说明模型对 IoU 阈值敏感也就是框定位精度不够回到 5.3 的标签清洗思路。最后做一次真实推理选一张 val 集之外的图片把输出画框叠加在原图上保存yolo predict modelruns/detect/train/weights/best.pt \ source./test_images/083.bmp conf0.25 imgsz640如果 detect 框能稳定落在飞机喷口高亮区域且不跳变就说明这份数据集的训练链路走通了。对红外小目标数据集来说训练时养成先看增强样本再开长训练的习惯能少走很多弯路。每次拿到新数据集我都强制走一遍validate - visual check - short epochs - full epochs的顺序短训练跑 20 轮先看 loss 能否降到 0.1 以下确认链路没问题再跑 150 轮这样能省下大量返工时间。希望帮到你。本文还有配套的精品资源点击获取