
简介HIT-UAV红外小目标数据集是面向无人机航拍场景的小目标检测数据集适合计算机视觉研究者、算法工程师用于模型训练与评估。包含从43470帧中选取的2898幅红外热图像覆盖学校、停车场、道路、游乐场等场景标注了行人、自行车、汽车及其他车辆并附有飞行高度60-130米、相机视角30-90度和光照强度白天/夜晚等维度信息。压缩包共2002个文件以1994个XML标注文件为主辅以5个txt数据集划分文件和1个voc2yolo.py格式转换脚本整体大小约192.88MB目录结构清晰方便直接接入常见目标检测框架。已有1511人学习/下载。这份资源能帮助读者快速获得带完整标注的红外小目标数据同时可利用txt划分和转换脚本直接生成训练/验证/测试集节省数据预处理时间适合用于小目标检测、红外视觉等相关课题研究。 拿到HIT-UAV这个数据集很多做无人机视觉的朋友第一反应是不就是个红外目标检测数据集嘛写个yaml丢进YOLO里训练就完事了。结果真跑起来才发现光是把数据从官方格式转成自己习惯的格式就能折腾掉半个周末训练出来的模型在红外小目标上更是脆得一碰就碎。这篇文章我就把从下载、解析、转换、训练到调优的完整链路盘一遍把那些文档里不会写的坑都标出来。1. HIT-UAV到底是什么别把它当成普通红外数据集用HIT-UAV全称是Harbin Institute of Technology Unmanned Aerial Vehicle是哈尔滨工业大学公开的无人机视角热红外目标检测数据集。它解决的核心场景是无人机从几十米到上百米高度俯拍地面用红外成像去找行人、车辆这类小目标。这个场景和平时刷的COCO、VOC完全是两个世界——目标小、对比度低、背景杂模型训练起来特别容易陷入“什么都检测不到”或者“把路灯杆当人”两种极端。先看一组硬指标这决定了你怎么用这个数据集共43,470帧热红外图像分辨率统一为512×640采集自不同天气、不同时间段覆盖学校、停车场、道路、广场等场景目标类型以行人和车辆为主有逐像素的包围框标注Bounding Box不是像素级分割所有标注都包含背景信息、目标遮挡关系、目标类别和帧编号配套提供对应的可见光图像方便做跨模态研究很多人第一次拿到数据集习惯性打开一张图看一眼发现热红外图像是单通道灰度图有人就直接拿它当普通灰度图训练这是最典型的误区之一。HIT-UAV的红外图像虽然肉眼看着只有一维亮度信息但它在像素值分布、动态范围上和自然光灰度图有本质区别目标亮度往往和背景呈正相关或负相关的极端对比这直接影响数据增强策略的选择后面会详细说。还有个特别容易踩的误区是序列划分。HIT-UAV的帧是按视频序列组织的如果你直接random_split把这些帧随机切成训练集和验证集那同一段飞行轨迹的相邻帧会同时出现在两边模型相当于提前背过“答案”验证集指标虚高得离谱换到真实场景马上现原形。正确做法是按序列Sequence划分保证同一个航拍片段完整落在训练集或验证集中不能两边都占。2. 目录结构与标注格式动手转换YOLO格式前的完整拆解HIT-UAV官网下载下来后目录结构看起来很简单但里面的标注格式是有讲究的。每个视频序列对应一个独立的txt文件文件名就是序列名比如Video1_00001.txt这种命名方式里面的每一行描述一个目标框字段顺序带坑我第一次解析时就被绕了。一个典型的标注行是这样排布的345 280 362 296 0 335 1 0.812300 0.556982 0.045386 0.036362从左到右的字段含义是目标的Bounding Box左上角x和y坐标、右下角x和y坐标之后是目标类别编号、帧编号再往后是一个表示“是否对应可见光图像”的标志位最后是归一化的中心点坐标和宽高。这个格式有个很迷惑的地方——同一份标注里既有绝对像素坐标又有归一化坐标而且类别编号没有单独的映射文件你得从论文和说明文档里反推哪类对应0、哪类对应1。还有一个重要细节标注是按“目标”维度存放的不是按“帧”维度。也就是说一个txt文件里同一个frame_id会反复出现多次每次对应那一帧里的一个目标。如果你想按帧把标注聚合起来必须自己遍历整个文件做分组千万别想当然地认为一个txt对应一帧。我把转换到YOLO格式的参考代码写一下可以直接用import os import numpy as np def hit_uav_to_yolo(txt_path, img_w640, img_h512): 将HIT-UAV标注txt转为YOLO格式列表 参数: txt_path: 原始标注文件路径 返回: dict, key为frame_id, value为该帧的YOLO格式标注列表 frames {} class_map {1: 0, 2: 1} # 根据原数据集类别映射调整 with open(txt_path, r) as f: for line in f: parts line.strip().split() if len(parts) 9: continue x1, y1, x2, y2 map(float, parts[:4]) cls_id class_map.get(parts[4], -1) frame_id int(parts[5]) if cls_id -1: continue x_center ((x1 x2) / 2.0) / img_w y_center ((y1 y2) / 2.0) / img_h box_w (x2 - x1) / img_w box_h (y2 - y1) / img_h frames.setdefault(frame_id, []).append( f{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f} ) return frames # 使用示例把转换后的标注写入对应帧名的txt frames hit_uav_to_yolo(Video1_00001.txt) for fid, labels in frames.items(): with open(flabels/{fid}.txt, w) as f: f.write(\n.join(labels))这里有个细节要提醒HIT-UAV发布时官方给的是“规范化坐标”和“像素坐标”混排但某些版本里还可能带上别的字段解析时建议先打印一行来看看格式再写通用解析函数不要直接套网上的代码。2.1 配套可见光图像的使用价值HIT-UAV还提供了对应的可见光图像大多数人忽略了这个配套数据。可见光图像可以用于跨模态训练、图像融合、域适应等方向哪怕你不做多模态研究也可以在数据预处理阶段用可见光做辅助分析——比如判断某个红外目标的真伪或者统计无人机飞行高度和目标尺寸的关系。我做数据分析时发现可见光图像和红外图像在几何对齐上比较好的话甚至能用来做半自动标注——先跑一个可见光预训练检测器把结果投影到红外图上做初筛人工只修正误检和漏检效率能提升好几倍。3. 训练前的尺度分析与锚框设计小目标检测为什么必须单独算Anchor拿HIT-UAV跑YOLO系列一个最直接的问题是如果直接沿用COCO预训练模型的Anchor配置mAP会低得让你怀疑人生。原因很简单HIT-UAV中大量目标的尺寸只有整张图的1%甚至更低像素面积经常小于32×32。COCO的Anchor默认偏大对这类目标基本不敏感。建议训练前先做一次目标尺度分布统计把训练集中所有Bounding Box的宽高聚类一下。具体操作是把所有框的像素宽高收集起来跑一个K-Means或者直接看分布直方图import numpy as np from glob import glob all_wh [] for label_file in glob(labels/train/*.txt): with open(label_file, r) as f: for line in f: parts line.strip().split() if len(parts) 5: box_w float(parts[3]) * 640 box_h float(parts[4]) * 512 all_wh.append((box_w, box_h)) all_wh np.array(all_wh) mean_w np.sqrt(all_wh[:, 0] * all_wh[:, 1]) # 等效边长 print(f共{len(all_wh)}个目标中位等效边长: {np.median(mean_w):.1f}px)我实际跑下来的统计结果是绝大多数行人目标的等效边长在15到30像素之间车辆稍大但也很少超过60像素。这就是典型的极小目标场景如果你用Darknet或YOLOv8默认的Anchor效果不好的根源就在这。针对这个分布我给两点实操建议训练输入分辨率不要盲目降到416或320尽量保持640甚至升到960否则小目标在特征图上只能占据一两个像素几乎不可能被检测出来。Anchor数量可以加到9个以上聚类后小目标要分配到至少4到5个Anchor让浅层特征图有足够的 recall 空间。3.1 输入分辨率与显存的取舍当然升分辨率不是没代价的。HIT-UAV原始图是512×640如果你直接960×1280输入训练显存消耗会直线上升最常见的是RTX 3090这种24G卡都只能勉强跑小batch。我的做法是先用640×640做快速原型验证确认数据管线没问题之后再用960输入做最终训练。如果卡实在不够还有一个方案是用SAHISlicing Aided Hyper Inference这类切片推理工具在推理阶段把大图切成带重叠的小块分别检测把结果融合回去——这比强行提高训练分辨率更省资源对小目标往往有奇效。4. YOLO系列训练HIT-UAV的完整流程与踩坑实录4.1 数据准备与YAML配置HIT-UAV官方没提供YOLO格式的标注你需要先把整个数据集转成以下目录结构dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/注意一点图像文件名必须和labels里的txt文件名一一对应比如Video1_00001.jpg对Video1_00001.txt。如果你从原始视频里抽帧抽帧命名时也要保证这个名字能对上标注里的frame_id。YOLOv8的配置文件里有个很容易忽略的坑degrees、translate、scale这些增强参数默认值在自然图像上没问题但对HIT-UAV这种小目标密集场景要调得很保守。尤其是scale默认的0.5意味着训练时图像会被随机缩放50%到150%这一缩放下去本来就15像素的行人变成7像素你再强的模型也学不出什么特征。我训练的实测配置长这样# hit_uav.yaml path: ./dataset train: images/train val: images/val test: images/test nc: 2 names: [person, vehicle] # 建议的增强参数在ultralytics配置中覆盖默认值 scale: 0.2 # 降低缩放尺度 fliplr: 0.5 # 水平翻转保留 mosaic: 0.5 # 关闭或大幅降低mosaic mixup: 0.0 # 关闭mixup copy_paste: 0.3 # 尝试这个这里最核心的经验是HIT-UAV上mosaic增强是双刃剑。YOLOv5/v8的mosaic把4张图拼成1张每张图被缩到一半尺寸小目标进一步缩小很多直接缩到只有几个像素等于是把标注信息给抹掉了。我建议把mosaic降到0.3到0.5甚至直接关闭换取每个目标在训练时保留足够像素。这个改动比调任何学习率都立竿见影。4.2 类别不平衡与难例问题HIT-UAV里行人和车辆的数量并不平衡细看还会发现不同场景里行人的外观差异很大——有的人在红外图里是一个高温亮点有的人因为环境温度高反而呈现暗色。这种类内差异会让模型训练时震荡得厉害。针对类间不平衡可以用cls损失权重调节但更重要的是难例挖掘。YOLO系列没有内建的难例挖掘机制我的替代方案是用一轮粗训练出的模型去预测训练集把置信度高但IoU不匹配的预测框提出来——这些往往是背景误检——然后手动看几百张图把典型误检场景比如停着的车顶、楼顶的空调外机以负样本的形式加进去。对于HIT-UAV这样的公开数据集实际操作上你可以把某个场景类型整体划为负样本场景在训练时做类似“难负样本采样”的效果。4.3 训练过程中的实时监控训练时除了看mAP我强烈建议你多关注验证集上的F1-Confidence曲线和小目标类别的AP。YOLOv8默认输出的mAP50、mAP50-95是按类别平均的容易被量大的类别拉平。如果person类AP很高vehicle类AP只有20多那整体mAP看起来还能看实际部署时车全检测不到。我在训练过程中会写个小脚本每个epoch结束后统计一次验证集中所有检测目标的最小框尺寸再看这些最小框被检出的比例。这比看总mAP更能反映小目标训练是否在良性进行。如果发现极小目标的检出率随着训练反而下降说明模型过拟合到大目标了需要立刻回退或调增强。5. 小目标AP上不去的深层原因与针对性优化方案红外小目标难检出的原因表面看是“目标小”本质是特征信息量不足。一个行人如果只有20像素宽在8倍下采样的特征图上就只剩2到3个像素卷积核根本没法提取有区分度的纹理模型只能靠对比度“猜”。这就导致三种典型失败模式漏检、误检、检测框抖动。下面按我踩过的坑逐一说。5.1 失败模式一漏检尤其是低对比度目标低对比度漏检是HIT-UAV最头疼的场景。大热天里地面温度高行人的红外辐射和地面接近肉眼都很难分辨模型就更难了。我用YOLOv8s在HIT-UAV上实测低对比度场景下的漏检率比高对比度场景高出一倍多。解决办法里效果最好的是数据增强中增加“对比度扰动”和“高斯噪声”。红外图像本身受热噪声影响模型应该在训练时就见过各种被噪声污染的目标而不是只在干净图像上训练。实测对比加噪声和随机伽马变换后低对比度场景的漏检率能下降15%到20%。注意别加太大否则目标直接被噪声吃掉了。5.2 失败模式二误检把高温点当人HIT-UAV误检的一大来源是太阳照射的地面、车顶、窗户反射等高温区域。模型学到的是“亮的就是人”而不是“人的形状和运动特征”。这时候单纯堆数据已经不够了我建议从两方面入手在训练集里显式包含大量无目标的背景帧。HIT-UAV里有不少帧没有任何标注目标这些帧不要扔掉把它们当负样本放进去。YOLO系列训练时无目标帧也能参与损失计算能有效压低全图误检。推理阶段做帧间过滤。无人机视频是连续的单帧误检在时序上往往是突发的。用简单的IoU轨迹跟踪比如ByteTrack把连续几帧都出现的框保留单帧闪出来的框删掉误检能消掉一大半。5.3 失败模式三检测框抖动与重复检测小目标检测框抖动的根源是特征图上一两个像素的偏移对应到原图就是好几个像素的跳动。YOLO通过回归得到框位置后相邻两帧的打框位置可能跳来跳去视觉上很不舒服。这个虽然不影响mAP指标但直接影响落地效果。我试过有效的方案是测试时增强TTA加加权NMS融合。具体做法是把输入图像做轻微尺度变化和水平翻转分别推理然后把所有框投影回原图坐标用带权重的NMS合并。对于小目标这能把框位置的方差压低不少。缺点是推理速度慢如果你有实时性要求就别全图TTA只对检测出目标的局部区域做TTA就行。6. 数据集的扩展操作从HIT-UAV延伸到自己的红外项目HIT-UAV是一个很标准的学术基准但实际项目里你大概率要检测的目标可能不是行人和车辆而是别的什么——比如电力巡检的绝缘子、森林防火的烟点。这种情况下HIT-UAV的意义主要是三条一是有现成的红外小目标数据练手调参二是它提供了多场景、多高度的覆盖让你测试算法的泛化能力三是它公开了配套可见光图像方便做多模态预研。6.1 用预训练模型做迁移学习如果要迁移到自己的红外目标数据集我建议先在HIT-UAV上预训练一个红外检测模型再在自己的小规模数据上微调。这比直接用COCO预训练权重有效得多因为红外图像域和自然光图像域差异太大——COCO预训练模型对红外图的底层特征提取能力很弱等于要从头学。实际操作中你可以把在HIT-UAV上训练完的模型权重作为初始化权重把最后的检测头类别数改掉然后冻结前几层骨干网络只训练后半部分和检测头。等损失降下来之后再把所有层解冻做全量微调。这样即使你自己的标注数据只有几百张也能得到可用的模型。6.2 自制红外数据集的采集与标注建议采集红外小目标数据时最容易犯的错误是只拍目标清晰的大图忽略了你实际部署时可能遇到的目标极小、遮挡、背景干扰等情况。我建议按以下比例来规划采集60% 目标尺寸正常的常规场景25% 目标极小的远距离场景10% 严重遮挡或复杂背景场景5% 完全没有目标的纯背景场景最后那一类纯背景帧是白送的负样本很多人不屑于标其实它们对降低误检作用巨大。标注工具上我用得比较多的是X-AnyLabeling和Supervisely前者轻量免费适合个人标注后者有自动标注插件对红外灰度图可以先跑一个预训练模型自动标再人工纠正。如果目标尺度特别小建议把图像放大4倍后再标减少每个框只有3、4个像素时的手抖误差这个误差会影响训练时的Anchor匹配。6.3 数据增强的扩展玩法除了常规的翻转、旋转、亮度变化红外图像上有些专属增强值得试热噪声注入。给图像添加高斯噪声或椒盐噪声模拟传感器热噪声。局部高温区域模拟。随机生成一些高亮圆斑并贴到背景上让模型学会忽略它们。红外后像模拟。对于运动目标模拟拖尾效应增强模型在运动模糊下的鲁棒性。这些增强不用全上先单独试看哪些对验证集有正收益再叠加别图省事一把梭以免增强过头把目标特征抹掉。6.4 模型选型与推理效率的平衡如果你要在无人机机载设备上部署不可能跑大模型。以我测试过的几个YOLO版本来看YOLOv8n在HIT-UAV上精度偏低但速度最快YOLOv8s是精度和速度平衡性最好的选择如果卡上资源允许YOLOv8m能进一步涨点但性价比一般。真正能在机载设备上落地的方案是“小模型切片推理”。用YOLOv8n或YOLOv5n然后以256或384的滑窗大小、50%重叠率对输入图切片每个切片独立推理。因为很多小目标在整图尺度上太小切成片之后目标在切片里的相对尺寸变大模型反而更容易检测。切片推理的mAP提升通常能抵消模型缩小带来的精度损失。关于这一块我的个人经验是红外小目标检测没有一劳永逸的通用模型必须在数据、增强、模型结构、推理策略四个环节都针对小目标做调整效果才能有质变。HIT-UAV是一个很适合打磨这些技能的练兵场建议好好利用它把这一整套流程跑通后面换到任何红外项目都不会慌。最后再分享一个小技巧如果你在HIT-UAV上无论怎么调参都涨不动点试着去看一下那些被漏掉的目标到底长什么样。很多时候问题不在模型而在标注——有些目标的红外特征在人类视觉里都难以辨认这种情况下适当合并或调整标注标准反而比堆参数更有效。本文还有配套的精品资源点击获取