红外小目标检测数据集详解:7559张4类目标,VOC+YOLO双格式与YOLOv8实战

发布时间:2026/8/31 14:51:18
红外小目标检测数据集详解:7559张4类目标,VOC+YOLO双格式与YOLOv8实战 简介本资源是面向红外图像目标检测任务的高质量多类别数据集适用于计算机视觉方向的研究者、算法工程师及深度学习初学者开展小目标识别、模型训练与性能验证。数据集涵盖无人机、直升机、飞机与飞鸟四类典型空中目标共7559张红外图像及严格对齐的VOC XML与YOLO TXT标注文件总标注框数达7858个全部由labelImg工具人工矩形框标注确保定位准确、类别清晰。压缩包含2000个文件1999个XML1个说明文本体积175.53MB结构简洁无冗余便于直接接入主流检测框架如YOLOv5/v8、Faster R-CNN进行端到端训练。目前已有1113人学习下载配套博文提供详细预览与使用指引读者可即刻获取完整标注体系、跨格式兼容标签、合理分布的类别样本及红外场景下的真实小目标挑战样本显著降低数据准备门槛。 做红外小目标检测的朋友天然就面临一个双重难题算法难调是一回事数据难找才是真正劝退人的门槛。可见光目标检测数据集一大堆一到红外场景尤其是无人机、直升机、飞机、飞鸟这类目标公开资源就非常少。最近我重新整理了一份《红外微小目标无人机直升机飞机飞鸟检测数据集》VOCYOLO双格式一共7559张4个类别压成一个7z包。这篇就把这个数据集从解压到训练的全流程实操记录一下包括目录结构、格式转换、YOLOv8/v5训练配置、常见坑位排查争取让拿到数据的人少走弯路。这份东西适合谁如果你在做低空安防、机场驱鸟、电力巡检、光伏电站无人机入侵检测或者单纯研究红外条件下的极小目标检测那这份数据集能省掉你大量整理标注的功夫。双格式也意味着你不用在VOC和YOLO之间反复横跳。我先把整个数据集的逻辑拆开讲清楚再一步步带你跑通训练链路。1. 数据集拆解为什么红外小目标这么难做1.1 红外成像与可见光到底差在哪很多人第一次接触红外图像时会有一个错觉不就是灰度图吗打上标签直接扔进YOLO不就行了实际操作起来远没那么简单。常规可见光图像分辨率动辄1920×1080甚至更高目标清晰、纹理丰富而红外热像仪常用的分辨率是640×512、384×288甚至128×128。在远距离场景下一架无人机在画面里往往就十几个像素飞鸟更是只有几个像素这种目标在深度学习里被称为极小目标。更麻烦的是红外成像的特点目标与背景的对比度低尤其在白天地面建筑、树木、车辆的辐射温度和天空背景拉不开目标信噪比很差。加上传感器噪声、非均匀性校正残留的竖条纹很多目标人眼都看不清。这就导致检测模型不仅要解决目标太小还要解决对比度太低背景干扰太强。这些因素叠加在一起通用目标检测模型直接跑红外数据效果往往很惨。所以红外小目标检测一直有自己独立的研究线用的不是普通检测比赛的套路。传统方法里有基于形态学Top-Hat、基于局部对比度LCM的检测深度学习方法里则要刻意设计小目标检测头、注意力模块或者先做超分辨率再检测。但不管算法怎么设计没有贴近真实场景的高质量红外数据一切都是空中楼阁。这也是这类数据集的价值所在。1.2 7559张、4类目标数据规模与类别构成解读说回这份数据本身。7559张这是什么概念在目标检测领域COCO是12万张VOC是1万多张看起来不多。但放在红外小目标领域这已经属于有诚意的量级。因为红外数据采集成本高、标注难度大很多公开红外面板数据只有几百到一千张左右能到几千张的少之又少。7559张如果按7:2:1划分训练集约5300张验证集1500张测试集750张足够支撑一个小型检测项目的起跑阶段。类别上明确是4类无人机、直升机、飞机、飞鸟。这几个类别在检测难度上差异很大。无人机是典型的刚体目标小旋翼无人机在空中具有规则的几何轮廓但尺寸极小直升机有旋翼结构部分场景下会呈现周期性叶片遮挡轮廓不稳定固定翼飞机一般尺寸较大、巡航速度快容易出现运动模糊飞鸟则是最折磨人的一类它属于柔性目标翅膀扇动时形状不断变化而且尺寸跨度极大近距离的鸟可以看到轮廓远距离的鸟就是一个亮斑像素点。从检测器角度看类别间的这种差异会带来很明显的指标分化。通常飞鸟的AP会最低因为目标太小、尺度变化太剧烈飞机的AP最高因为目标结构清晰、可辨识特征多。阅读数据报告时不能只看总mAP要单独看每一类的AP才能知道模型在哪里掉链子。2. 数据集格式详解VOC和YOLO目录长什么样2.1 VOC格式目录结构与XML标注解析拿到7z压缩包后解压出来的目录结构大概是这样的实际命名可能略有差异但这个结构是VOC规范IR_SmallTarget_Dataset/ ├── Annotations/ │ ├── 000001.xml │ ├── 000002.xml │ └── ... ├── JPEGImages/ │ ├── 000001.jpg │ ├── 000002.jpg │ └── ... ├── ImageSets/ │ └── Main/ │ ├── train.txt │ ├── val.txt │ └── test.txt └── labels/ (若同时附带了YOLO格式标签)JPEGImages存放图像Annotations存放和图像一一对应的VOC标注文件。每一个XML文件描述了一张图里的全部目标信息。我打开一个XML给你看核心结构就是这个annotation filename000001.jpg/filename size width640/width height512/height depth3/depth /size object namedrone/name difficult0/difficult bndbox xmin210/xmin ymin160/ymin xmax230/xmax ymax180/ymax /bndbox /object /annotationxmin、ymin、xmax、ymax是目标框的像素坐标左上角和右下角坐标。注意VOC里还有一个difficult字段表示这个目标是否因为遮挡、模糊等原因被判定为难以识别。如果你用标准VOC评估代码difficult1的样本在评估时会做特殊处理但很多YOLO转换脚本会直接忽略这个字段所以转换前最好确认一下。对于这种小目标数据有一个细节值得提目标框非常小比如只有20×20像素甚至更小那么xmin、xmax之间的差值和ymin、ymax的差值都很小。在转换到YOLO格式后中心点坐标和宽高都是归一化到[0,1]的小数如果框太小宽高值可能只有0.02甚至0.01。浮点数精度在小数值上的相对误差会被放大建议转换时在txt里保留足够多的小数位最少6位我一般用10位避免数值过小时精度的损失。2.2 YOLO格式的label文件与归一化坐标YOLO系列的标注格式和VOC完全不同。它不以XML为单位而是每一张图对应一个同名的txt文件放在labels目录下。txt里每一行代表一个目标格式是class x_center y_center width height这五个值都做了归一化处理。归一化公式很简单x_center ((xmin xmax) / 2) / image_width y_center ((ymin ymax) / 2) / image_height width (xmax - xmin) / image_width height (ymax - ymin) / image_height全部除以图像宽高之后所有数值都落在0到1之间。这样标注就和图像的具体分辨率解耦了训练时模型无论输入640×640还是1280×1280标签都不用重新计算。目录结构一般是IR_SmallTarget_Dataset/ ├── images/ │ ├── train/ │ │ ├── 000001.jpg │ │ └── ... │ └── val/ │ └── ... └── labels/ ├── train/ │ ├── 000001.txt │ └── ... └── val/ └── ...有两点特别容易踩坑。第一images和labels必须严格同名对应jpg对应txt不能有多余文件少一个txt就会导致这一张图被跳过第二txt里如果有空文件表示这张图没有任何目标。空文件本身不影响训练但如果一张标注框极小的图在数据增强比如Mosaic时被裁剪掉了目标生成的txt可能变成空行有时候会触发No labels found的警告。训练前脚本检查一下把这类空标注文件统计出来。2.3 为什么同时提供双格式有的朋友会问为什么不干脆只提供一种格式我要解释一下这个设计的合理性。目标检测的生态里VOC和COCO格式占据了大量开源代码的输入接口比如MMDetection的CocoDataset、Detectron2的COCO格式以及老牌项目里的VOCDataset。你拿到VOC格式后想用MMDetection跑Faster-RCNN或者DETR类模型直接写个dataset配置就能读。而YOLO格式则是YOLOv5、YOLOv8、YOLOX等一系新老模型默认的输入格式适合快速验证。两种格式的存在本质上是覆盖了两类主流工作流。你要是研究算法挂在MMDetection里对比实验VOC格式顺手你要是工程落地急着出一个YOLOv8的模型做demoYOLO格式开箱即用。省去你自己写转换脚本的功夫也避免了格式转换过程中坐标精度、类别顺序出错的风险。不过需要提醒的是双格式虽然省事但你还是要自己确认一件事情两个格式的类别顺序。VOC里类名是字符串drone、helicopter、airplane、bird而YOLO的txt里是整数索引比如0、1、2、3。这个索引必须对应到data.yaml里的names列表顺序。我在工作中见过不少翻车案例就是XML转换时A-Z排序和YOLO配置里names顺序不一致结果模型把飞鸟当成直升机来学。拿到数据集后先把类别顺序核对一遍。3. 实操从解压7z到数据校验的完整流程3.1 7z压缩包的解压与文件完整性检查7z格式在压缩率上比zip高不少尤其是图像这类数据有大量相似结构7z的LZMA2算法能压得很狠。但代价是解压速度略慢而且工具链不像zip那样系统自带。Windows上推荐用7-Zip或者NanaZip7-Zip的增强分支。Linux上多用p7zip# 查看压缩包内容列表 7z l IR_SmallTarget_Dataset.7z # 解压到当前目录 7z x IR_SmallTarget_Dataset.7z # 如果用tar版本工具链 tar -xf IR_SmallTarget_Dataset.7z解压之前有件事先做看一下解压目录的剩余空间。一个包含7559张图的7z包解压后通常是2到4GB甚至更大。如果磁盘空间不足解压到一半报错压缩包本身没坏但你已经解压出来的文件不一定完整最稳妥的办法是释放足够空间后重新解压。文件完整性检查也值得做。如果发布方提供了MD5或SHA256校验值在解压前先跑一遍sha256sum IR_SmallTarget_Dataset.7z拿到结果和官方给出的哈希值对比一致再解压。这一步能避免很多文件损坏导致训练到一半崩掉的问题。尤其是7z包本身带分卷时漏卷一个整个包都废了。解压完成后不要急着开训练。先用系统自带的图片查看器随机翻十几张图看看图像内容是否正常。如果图像整体发绿、发蓝或者有明显条纹可能是图片保存时走了伪彩色映射把红外灰度图映射成彩色图或者采集时传感器故障。这类问题在预处理阶段发现是最好的等你跑了一个小时训练才发现数据有脏那才是真的难受。3.2 标注文件批量校验脚本数据集质量的核心在标注。我强烈建议在训练前跑一遍标注校验脚本别偷懒。我的校验逻辑通常包含以下几项统计JPEGImages和Annotations或images和labels文件数量检查图片和标注是否一一对应。扫描所有XML检查bndbox坐标是否在图像尺寸范围内有没有xmin大于xmax这种逻辑错误。扫描所有YOLO txt文件检查class索引是否在合法范围0到类别数-1宽高是否为负。统计每个类别的目标数量看看类别分布是否严重不均衡。检查有没有目标框面积为0的无效样本。这里给一个简单的Python检查脚本针对YOLO格式import os from pathlib import Path images_dir Path(IR_SmallTarget_Dataset/images/train) labels_dir Path(IR_SmallTarget_Dataset/labels/train) num_classes 4 image_files list(images_dir.glob(*.jpg)) list(images_dir.glob(*.png)) label_files list(labels_dir.glob(*.txt)) # 1. 图片与标签一一对应 img_stem {f.stem for f in image_files} lbl_stem {f.stem for f in label_files} print(只有图片没有标签:, img_stem - lbl_stem) print(只有标签没有图片:, lbl_stem - img_stem) # 2. 标签内容检查 for txt in label_files: with open(txt, r, encodingutf-8) as fp: lines fp.readlines() for line in lines: parts line.strip().split() if len(parts) ! 5: print(f行数异常: {txt} - {line}) continue cls int(parts[0]) x_center float(parts[1]) y_center float(parts[2]) w float(parts[3]) h float(parts[4]) if cls num_classes: print(f类别索引越界: {txt} - {cls}) if w 0 or h 0: print(f框宽高异常: {txt} - {line}) if x_center 0 or x_center 1 or y_center 0 or y_center 1: print(f中心点归一化异常: {txt} - {line})这个脚本按需修改路径就行。跑完如果输出为空或者只有少量警告说明数据基本健康。如果爆出一堆只有图片没有标签的情况你需要回到发布方确认是不是漏传了标签文件。3.3 类别分布统计与数据划分策略拿到健康的数据之后还要看类别分布。红外小目标数据天然存在类别不平衡飞鸟远多于直升机、飞机很正常因为实拍场景里鸟确实更容易出现。用一个简单统计看看from collections import Counter counts Counter() for txt in labels_dir.glob(*.txt): with open(txt, r, encodingutf-8) as fp: for line in fp: line line.strip() if line: cls int(line.split()[0]) counts[cls] 1 for i in range(4): print(f类别{i}: {counts[i]}个目标)如果发现某个类别目标极少比如直升机只有200个实例那训练时模型大概率会严重偏向多数类。应对策略有几种一是给少数类分配更高的类别权重YOLOv8里可以设class_weights二是对少数类做过采样也就是在data.yaml里多复制一些这类图片的路径三是数据增强时对包含少数类的样本提高采样概率。最原始的办法是收集更多该类的样本但现实中很难。数据划分也有一门学问。有一种常见错误是把整个数据集的图片和标签打乱后随机划分。如果同一场景的连续帧图像同时进了训练集和验证集模型的验证指标会虚高因为模型见过这个场景的相邻帧了。更严谨的做法是按场景或者按视频序列划分避免数据泄漏。如果这个数据集是从多个视频片段抽帧得到的最好按照视频片段来split而不是逐帧随机抽。实际划分时我通常用8:1:1也就是训练80%、验证10%、测试10%。验证集用来调参测试集留到最后做最终评估。如果用Ultralytics的YOLO训练它会在训练时自动从训练集里再分出一部分做内部验证所以你可以更简单地把数据集分成train和val两个目录。按我的习惯我会手动切保证val里每条序列至少有10到20张连续帧这样验证结果更有参考价值。4. YOLOv8训练实战配置、参数与调优记录4.1 训练环境与data.yaml配置如果你准备用YOLOv8安装很简单pip install ultralyticsUltralytics会直接把yolo这个命令行工具装到环境里。我用的版本是8.x训练命令基本一样。训练前先建好data.yaml内容类似path: /path/to/IR_SmallTarget_Dataset train: images/train val: images/val test: images/test names: 0: drone 1: helicopter 2: airplane 3: bird这里有一个新手最容易犯的错path如果给了绝对路径train和val就写相对path的相对路径如果path留空train和val就必须写完整绝对路径。两种写法都行但别混着来。我见过有人path设置成数据集根目录train却又写了完整绝对路径结果Ultralytics内部拼接时把路径搞成双重目录直接报No labels found。训练命令我一般这么起yolo detect train datadata.yaml modelyolov8n.pt epochs200 imgsz640 batch16 workers8 device0这里的yolov8n是nano版本速度最快、显存占用最小。如果显存够用建议换成yolov8s或者yolov8l准确率会有明显提升。对红外小目标场景我的经验是yolov8s是性价比比较高的起点精度不太差训练速度也能接受。训练时注意观察Ultralytics输出的日志。loss曲线里box_loss、cls_loss、dfl_loss会逐渐下降。如果某个loss在几十个epoch后还不降反升先别慌可能是学习率设置的问题Ultralytics默认自带余弦退火策略前期波动是正常的。如果200个epoch跑完loss还是发散那才需要停下来检查数据和标注。4.2 针对红外微小目标的训练细节打工人最关心的还是参数怎么调能让小目标效果更好。我把自己实践过的几个有效手段列出来。第一输入分辨率。官方默认imgsz640对常规目标够用但对红外小目标很多目标就十几个像素640分辨率下信息量太少。我把分辨率调到896甚至1280后mAP有明显提升。代价是训练时间变长、显存占用变大。如果你的数据来源是640×512的红外图直接把imgsz设为640倒也可以但注意Ultralytics会用letterbox填充到正方形640×512的图像会被缩放填充成640×640目标尺寸几乎不变。第二大图切分Tiling。如果图像本身就是高分大图比如1024×768而目标又特别小我建议在进入YOLO之前先做tiling把大图切成一堆512×512或640×640的patch目标在patch里占的比例就会变大检测难度直接下降。代价是同一张被切成了多块推理时要做拼接和后处理。如果数据集发布方已经按小图整理好了这个步骤可以跳过。第三数据增强的设置。YOLOv8的默认增强里有hsv_h、hsv_s、hsv_v这种颜色抖动。对红外数据来说hsv增强意义不大红外的灰度值反映的是热辐射强度你把图像色调随机变一下等于引入了物理上不存在的伪特征。我处理红外数据时倾向于把hsv增强关掉或者调到很小hsv_h: 0.0 hsv_s: 0.0 hsv_v: 0.1同时把mosaic和mixup适当保留。Mosaic在红外小目标上仍然有效因为它能增加背景多样性但如果你发现小目标在Mosaic拼接时被裁掉可以调低mosaic概率。第四类别权重。我用YOLOv8时会在训练命令里加yolo detect train ... class_weights1.0,1.0,1.0,2.0意思是把bird类的权重提高强制模型多关注这个样本少的类别。如果是YOLOv5可以修改数据集配置文件里的nc和names同时用损失函数里的cls_pw参数。4.3 评估指标、训练曲线和模型选择训练结束后看什么指标首要是mAP50和mAP50-95。mAP50是指IoU阈值0.5时各类别AP的平均值对框位置精度要求宽松mAP50-95是IoU从0.5到0.95按0.05步长取平均更严格也更敏感。对小目标检测mAP50-95通常不会太高能到0.3以上就算不错了。分析时务必单独看每一类的AP因为飞鸟类AP会直接把总指标拉下来。训练完在验证集上跑一下yolo detect val datadata.yaml modelruns/detect/train/weights/best.pt会输出一个详细的指标表还有混淆矩阵和预测结果图。我发现红外小目标场景里预测结果图比指标表更直观。把结果图打开检查一下是不是漏检了远处的小点是不是把云层边缘、树叶纹理误检成飞鸟这些case往往能暴露出比mAP数值更关键的问题。模型选型上如果追求速度和精度平衡YOLOv8n在边缘设备上很有优势但在极小目标上表现一般。我做这类任务时的路线是先用yolov8s跑出一版baseline确认数据没问题、训练流程通了再换yolov8m或yolov8l提精度。不要一上来就上大模型等到排查bug时才发现模型大只是把训练速度拖慢了调试成本成倍增加。严格来说如果目标真的只有几个像素YOLO这种纯anchor-free检测器依然不是最优解。有些研究者会在YOLO前面加超分辨率模块或者把特征金字塔的浅层P2层引入检测头。但工程落地阶段先把YOLO调到最优、把数据洗干净往往就能拿到一个可用的模型再上这些高阶玩法更稳妥。5. 常见问题与排查技巧实录5.1 训练报错的排查清单这几个月我在处理这份数据集和训练流程时攒了不少实际排查经验。直接整理成表格方便你对照现象可能原因排查顺序训练启动时报No labels foundimages和labels路径不对/类别索引越界/空txt文件先打印路径拼接结果再用脚本检查labels目录训练能跑但loss一直不降数据集本身脏数据多/学习率过高可视化抽查图片调低lr或用更小模型试跑mAP50很高但mAP50-95很低标注框边界不够准IoU提高后匹配不上检查标注框是否紧紧贴合目标轮廓小目标常见飞鸟几乎检测不到类别不平衡或目标太小加类别权重调高分辨率检查增强策略预测结果全是背景误检背景纹理被当目标/数据划分泄漏看混淆矩阵关闭剧烈增强检查train/val是否有同场景帧解压后图片打不开7z包损坏或下载不完整校验SHA256重新下载有个很典型的案例一位同事训练YOLOv5时训练20个epoch后box_loss降到很低但val的mAP一直为零。排查到最后发现labels里的类别索引是0、1、2、3而data.yaml里的names却是从左到右写的airplane、bird、drone、helicopter模型训练时用的真实标签和数据集语义完全对不上。这个坑在双格式数据集上尤其容易出现因为VOC格式里类名是字符串转成YOLO索引后必须强制规定顺序。5.2 目标太小导致漏检的调试思路如果你的模型在飞鸟这类小目标上总是漏检可以按下面的路径一步步试。第一步检查你的nms阈值和conf阈值。预测置信度阈值默认是0.25小目标因为特征弱置信度普遍偏低可以把conf调低到0.1甚至0.05看看召回率有没有提升yolo detect predict modelbest.pt sourcetest_images conf0.1 iou0.5第二步调整nms的IoU阈值。如果目标密集比如一群飞鸟挤在一起默认的IoU阈值会让两个高度重叠的框被合并成一个导致漏检。把iou0.7调整到0.5左右可以让相邻目标保留更多候选框。第三步回到训练环节提高小目标的样本占比。统计一下你训练集中包含小目标的图片比例如果低于50%小目标检测头就没怎么见过小目标自然学不好。此时可以对小目标样本做重复采样或者过采样。第四步考虑给模型增加浅层特征。YOLOv8虽然本身有P3、P4、P5层但P2层更高分辨率特征并没有默认加进检测头。很多小目标检测研究惯用的做法是把P2层加进来让模型在更高分辨率的特征图上检测小目标。Ultralytics没有现成开关需要改模型yaml工程量略大排在最后再说。5.3 实际踩坑记录红外数据的独有处理细节红外数据和可见光数据相比最容易被忽略的一个问题是图像通道数。标准YOLO流程读图时会用OpenCV的imread如果你保存的是单通道灰度图OpenCV默认会把它读成3通道但每个通道的值是相同的这没问题。问题在于如果数据集里同时存在灰度图和三通道伪彩图模型会把色彩通道当作一种隐含特征导致过拟合到特定的调色板上。遇到这种情况我建议统一转成3通道灰度即每个通道相同的灰度值并且在增强时关闭颜色相关增强只保留几何增强和亮度对比度变化。另一件值得记录的事是红外图像中的非均匀性问题。很多红外相机输出的图像有明显的固定条纹噪声这在某些帧里会形成虚假的强纹理极容易被模型误判为飞鸟或无人机。如果你的数据集中这类条纹明显可以在训练前先做一步简单的去噪或者对比度归一化。在推理阶段也可以做一个预处理对图像做中值滤波去除条纹噪声后再送入模型。肉眼看着变化不大但对小目标的检测稳定性友好很多。最后关于标签顺序的核对我再强调一次。双格式数据集虽然方便但它默认你在使用前已经确认过VOC和YOLO类别索引的一致性。拿到数据后跑一个最简单的转换脚本把XML里第一个目标的name和YOLO label第一行的索引对应起来确认无误再开始训练。这个习惯能帮你躲过一大半的隐性坑。我上次复核时发现文件名虽然一样但有一个XML里类名写成了Bird其他都是bird大小写不一致在字符串匹配时会导致该样本被忽略。这种低级错误在真实数据集里并不罕见预处理脚本里加一个类名映射表就解决了。本文还有配套的精品资源点击获取