资讯动态

HIT-UAV红外小目标数据集实战:从数据体检到YOLO训练全流程

发布时间:2026/10/14 16:24:23 来源:尧图企业网站定制
简介HIT-UAV红外小目标数据集是一份面向目标检测、红外图像分析与无人机视觉研究的高质量标注数据适合计算机视觉学习者、科研人员及算法工程师用于小目标检测模型的训练与验证。数据源自无人机在不同场景学校、停车场、道路、游乐场等拍摄的红外热像覆盖人员、自行车、汽车及其他车辆并记录飞行高度60至130米、相机视角30至90度与昼夜光照条件为多维度算法评测提供了坚实基础。资源包共2002个文件压缩后约192.88MB以1994个XML标注文件为主体包含每幅图像的边界框与类别信息另含5个TXT文件提供训练集、验证集和测试集的划分以及1个voc2yolo.py脚本可将VOC格式标注一键转换为YOLO格式省去手动整理的繁琐流程。对于需要直接使用标准红外数据集开展实验的研究者这套数据已覆盖不同高度、角度和光照的场景便于评估模型泛化能力。目前已有1520人学习下载适合具备一定目标检测基础、希望在小目标场景下快速验证或微调模型的开发者使用。1. HIT-UAV 红外小目标数据集无人机视角下的红外目标检测到底难在哪第一次拿到 HIT-UAV 红外小目标数据集时我犯过新人都会犯的错把它当普通可见光检测任务通道改成 3、分辨率 640 就开跑。跑了一天mAP 卡在 0.3 上不去。问题不在模型而在数据本身无人机高度带来的低分辨率、热成像单通道灰度、背景里大量与目标温度相近的干扰物让红外小目标检测成为一个独立算法分支。这个数据集正是为这个分支准备的公开基准它逼你回答一个问题低分辨率热成像下目标可能只有 8×8 像素你怎么把它找出来。做算法预研、论文对比实验、带新人练手它都合适想直接拿它训练业务系统去部署得先看清标注覆盖面和场景单调性。下面从数据体检讲起把最容易浪费时间的环节一个个拆开。2. 先搞懂这批红外图像数据特性与标注格式决定后续一切2.1 无人机高度和热成像带来的三个数据特性无人机视角的红外图像有三个共性这三个特性不是背景知识而是后续每一步参数选择的决策依据。第一个是小。以 640 宽的图像为例一个行人可能只占 12×8 像素目标框面积不到 100 像素。主流检测器对输入做多次下采样到最低层特征图上这个目标只剩不到半个像素的响应几乎等于被抹掉。这就是很多通用检测模型在 HIT-UAV 上 mAP 极低的直接原因不是模型“笨”而是目标的感知粒度在深层特征图上已经不存在了。第二个是背景复杂。红外图里地面、树木、建筑边缘会形成明显的高温热梯度这些区域的局部纹理和目标边缘非常接近。模型很容易把背景高频边缘当成目标产生一堆虚警。我第一轮实验里统计过误检分布大多集中在屋檐、道路白线和树冠边缘真目标反而因为轮廓不够“锐利”被漏掉。第三个是单通道。红外灰度图没有颜色信息只有热辐射强度。可见光预训练模型在 RGB 数据上学到的通道统计完全不匹配直接加载权重会有一段明显的冷启动期前几十个 epoch 的 loss 下降看起来像没在训练。这一点决定了我们在 3.2 节怎么处理输入通道。放到一起这三个特性把 HIT-UAV 和一个普通可见光检测数据集彻底区分开目标小到难以感知、背景难到难以区分、输入信息量还少一个维度。后面所有决策包括切图、高分辨率训练、小目标子集评估全从这三个特性推导出来而不是从模型结构推导。2.2 标注格式拿到手先判断是 XML 还是 txt不少人在拿到数据集后的第一反应是找训练脚本这最容易翻车。不同渠道流通的版本里标注格式、目录组织、类别编号都不一定一致可能是 PASCAL VOC 的 XML可能是 YOLO 的 txt也可能只有 JSON。所以第一步不是训练而是数据体检。下面这套命令我会先跑一遍# 数据集目录体检 tree -L 2 /data/hit-uav | head -50 echo --- XML 标注数量 --- find /data/hit-uav -name *.xml | wc -l echo --- YOLO txt 标注数量 --- find /data/hit-uav -name *.txt | wc -l echo --- 图像数量 --- find /data/hit-uav \( -name *.jpg -o -name *.png -o -name *.bmp \) | wc -l数量关系直接告诉你标注格式XML 和图像数量持平基本是 VOCtxt 和图像数量持平基本是 YOLO两者都不是就去翻 json。数量对不上也不用慌红外数据集常有缺标注情况少几个文件不代表数据坏了但要把缺标注的图像从训练目录里排除而不是让加载器报错。确定为 VOC 后我还会打开一个 XML 看内容head -40 /data/hit-uav/annotations/00001.xml重点看三个字段name的实际取值这决定类别映射表bndbox里的坐标是整数还是小数这决定转换脚本用整数还是浮点size节点是否存在如果存在且准确可以做归一化分母如果缺失必须像 3.1 节那样从原图读尺寸。这三个字段哪怕只有一个和预期不同后续标签转换的输出都会错得无声无息。2.3 数据划分按序列切别按帧随机切HIT-UAV 这类数据的图像来自飞行视频抽帧同一目标经常连续出现在几十帧里。按帧随机划分训练集和验证集等价于把同一个目标同时放进训练和验证验证指标会明显虚高落到新场景视频上立刻原形毕露。我在这上面吃过亏之后处理无人机数据一律按序列切分不再按帧切。先确认每个图像的序列归属常见做法是用上级目录名作为序列 ID。序列长度往往很不均匀有的序列只有十几帧有的几百帧如果按目录个数直接 8:2 切验证集可能只有几百帧。所以我一般先统计每个序列的帧数from pathlib import Path data_root Path(/data/hit-uav) seq_count {} for img_path in data_root.rglob(*.jpg): seq_id img_path.parent.name seq_count[seq_id] seq_count.get(seq_id, 0) 1 for seq_id, n in sorted(seq_count.items(), keylambda x: x[1], reverseTrue): print(seq_id, n)统计完帧数后按帧数累计分配把序列按帧数从大到小排序依次放入训练集直到达到总帧数的 80%剩下给验证集。这样两头样本量都足。如果数据集里还带飞行轨迹或时间戳元信息优先按“拍摄地点/飞行架次”切分那比按目录名更严格能进一步避免同一片区域在不同架次里被重复采集导致的跨集合泄露。3. 把 HIT-UAV 跑进检测器从标签转换到训练的最小可复现流程3.1 标签转换从 XML 到 YOLO 的适配脚本确认标注为 VOC 格式后第二步是把 XML 转成 YOLO 格式。YOLO 系列的标签行格式是 class_id x_center y_center width height坐标全部归一化到 0~1VOC 保存的是绝对像素坐标。转换脚本的难点不在解析而在异常数据处理。下面这个版本我沿用很久主要胜在有两层防御import xml.etree.ElementTree as ET from pathlib import Path from PIL import Image xml_root Path(/data/hit-uav/annotations) img_root Path(/data/hit-uav/images) out_root Path(/data/hit-uav/labels) class_map {person: 0} # 以 2.2 节核查到的 name 实际取值为准 def convert_one(xml_path: Path): tree ET.parse(xml_path) root tree.getroot() img_file img_root / (xml_path.stem .jpg) with Image.open(img_file) as im: w, h im.size # 用真实图尺寸不依赖 XML 的 size 节点 lines [] for obj in root.findall(object): name obj.findtext(name) if name not in class_map: continue bbox obj.find(bndbox) x1, y1 map(float, (bbox.findtext(xmin), bbox.findtext(ymin))) x2, y2 map(float, (bbox.findtext(xmax), bbox.findtext(ymax))) box_w, box_h x2 - x1, y2 - y1 if box_w 1 or box_h 1: # 丢弃宽或高不足 1 像素的退化框 continue xc (x1 x2) / 2 / w yc (y1 y2) / 2 / h bw box_w / w bh box_h / h if not (0 xc 1 and 0 yc 1 and 0 bw 1 and 0 bh 1): continue lines.append(f{class_map[name]} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) out_path out_root / (xml_path.stem .txt) out_path.write_text(\n.join(lines)) for xml_path in xml_root.glob(*.xml): convert_one(xml_path)两处防御必须保留。第一个是box_w 1过滤红外小目标数据里真的有宽或高只有 1~2 像素的标注这类框进入损失计算会产生剧烈数值抖动过滤后训练更稳定。第二个是归一化后的范围检查坐标必须落在 (0,1) 区间一旦出现 0 或 1 说明某个坐标算错要立即排查而不是忽略。class_map的取值必须来自 2.2 节打开的 XML 真值不要凭印象填写。转换完成后做一次可视化自查把生成的 txt 标签画回原图肉眼确认框的位置和目标边缘对得上。这一步推荐用 OpenCV 的rectangle直接画不要依赖标注软件因为我们要检查的是转换结果不是原始标注。3.2 训练配置单通道、小目标的参数调整进入训练之前有几组参数需要针对 HIT-UAV 专门调整。第一个是输入分辨率我习惯 640 起步第二个是锚框小目标数据集的框面积分布非常集中通用锚框策略在小目标上不高效常见做法是先对训练集真实框做 k-means 聚类用聚类结果替换默认锚框第三个是单通道输入问题。红外单通道和预训练权重的 RGB 输入不匹配。常见做法是读取后复制成三通道能跑通但会引入冗余计算而且预训练权重里本来就没有红外知识。我更推荐在数据加载层声明单通道在模型入口用一层 1-3 卷积完成通道扩展。YOLO 系框架里改数据配置和模型输入层就能做到并不复杂。下面是一份 baseline 阶段的最小数据集配置# dataset.yaml path: /data/hit-uav train: images/train val: images/val nc: 1 names: [person] imgsz: 640 batch: 16 epochs: 150 patience: 20 workers: 8nc和单类别对应。如果另一份版本里包含多类别names要按 label 文件里的 id 顺序对齐不要只看名称排序。imgsz640是一个平衡点分辨率提高对小目标检测立竿见影但显存和训练时间同步上涨从 640 换到 1280 可能提升 5 个点以上的 mAP训练耗时也可能翻倍。所以 baseline 固定 640后续用切图方式获取高分辨率收益。模型结构方面我在小目标任务上一般对比下面几个配置这张表不是绝对结论但它反映了一个经验排序配置显存占用训练速度小目标表现yolov8n 640低快一般漏检偏多yolov8s 640中中略好yolov8n 切图中中提升明显yolov8s 切图高慢通常最优小目标场景里先切图后升模型性价比最高。如果资源只允许你动一个变量选切图。常见的反面教材是把可见光任务里那一套“换大模型、加数据增强”直接搬过来最后发现训练时间翻倍mAP 只涨零点几个点本质上是目标在特征图里根本站不稳换再大的模型也没用。3.3 训练启动与资源估算配置就绪后训练命令本身很简洁yolo train data/data/hit-uav/dataset.yaml \ modelyolov8n.pt \ imgsz640 batch16 epochs150 \ project/data/exp namehit_uav_baseline \ device0batch16能否跑起来取决于显存。640 分辨率、yolov8n 在 16GB 显存显卡上比较宽松8GB 卡建议降到 8同时把workers调低避免数据加载成为瓶颈。单卡足够覆盖 HIT-UAV 这种规模的 baseline不需要一上来就分布式。patience20会触发早停验证指标连续 20 个 epoch 无改善时自动停止建议始终打开。训练启动后不要只盯 loss。我在这个环节会固定训练随机种子并把数据划分、分辨率、batch 写进实验名。HIT-UAV 这类小数据集对随机种子非常敏感同一个配置不同种子跑两次mAP 可能差 2~3 个点不记录种子的实验几乎无法复现。观察曲线的重点也放在验证集 mAP 上而不是训练 loss训练 loss 下降到平稳只能说明模型记住了训练集。4. 在 HIT-UAV 上训练最容易碰到的五个坑与排查顺序4.1 小目标在多次下采样后直接消失现象训练 loss 下降正常验证集 mAP 却是 0或者只有零星几个检测框。原因模型经过多次下采样后最低层特征图上 8×8 的目标连一个点都占不满特征在前向传播中被抹掉。HIT-UAV 里这类目标占比高很多通用配置下训练流程看起来一切正常检测结果却像坏了一样全无响应。解决先用分辨率干预把imgsz提高到 1280不改网络结构。目标像素被放大后能在深层特征图上留下足够响应mAP 通常立刻回升。如果显存不够先用第 5 章的切图方案。4.2 归一化坐标算错导致训练不收敛现象训练 loss 一直很大且不降验证集上完全没有框。原因标签转换脚本出错常见两类。一是整数除法把宽高截断成 0二是不小心把x_center写成了x_min。这类错误不报异常模型只是安静地学习错误坐标表现就像训练坏了但又看不出坏在哪。解决转换完成后打印几行标签文件手动反算回像素坐标确认和原图标注一致再开训练。我通常把可视化自查做成转换脚本的一部分每次转完顺手画一批图几分钟检查能省下数小时无效训练。4.3 单通道灰度图被强行复制成三通道的隐性代价现象训练冷启动特别慢收敛后 mAP 也比同配置预期低一截。原因多数框架默认输入三通道如果直接在加载时把灰度复制三次网络前面几层花大量参数学习冗余表达来自可见光预训练权重的通道统计完全派不上用场。解决在数据加载层声明使用单通道并通过网络入口层完成通道扩展。没有时间改网络结构时可以先按三通道跑通流程但把“三通道复制”记成一个变量调优阶段再换单通道方案对比收益。4.4 验证集和训练集共享同一目标序列现象验证 mAP 高得反常能到 0.85 以上但拿到任何新场景视频上检测效果都明显打折扣。原因数据划分时没有按序列切分同一个目标的多帧被随机分到训练和验证模型事实上见过验证目标。解决回到 2.3 节的按序列划分做法按帧数加权分配。这是底线要求不是可选优化。凡是无人机视频抽帧构成的数据集都应该先做序列划分再做随机增强。4.5 背景高频边缘与目标特征相似导致虚警现象漏检不算多但地面建筑边缘、树冠、道路标线附近冒出一堆小框。原因红外图里背景高频边缘和目标局部纹理高度相似模型区分不开。小目标本身的语义信息太少能用于判别的特征几乎只有亮度和与周围的对比度。解决评估时把虚警数量单独统计不能只看 mAP。调优时着眼难例挖掘比如修改损失对背景难分样本的权重或者切图时把边缘丰富区域保留在训练集里。5.3 节的 PD/FA 统计在这种场景下比 mAP 更接近业务感受。5. HIT-UAV 进阶打法切图、P2 检测层和红外指标验证5.1 切图把 16×16 的目标变成 32×32切图是红外小目标检测里最直接的提点手段。把 640 图像切成 320 子图目标像素面积等于放大一倍。切图的关键是同步修正框坐标子图里的框坐标必须减去左上角偏移。下面是一个带重叠的切图逻辑def crop_with_shift(img, box, block_size320, stride256): h, w img.shape[:2] out [] for y0 in range(0, h - block_size 1, stride): for x0 in range(0, w - block_size 1, stride): x1, y1, x2, y2 box if x2 x0 or x1 x0 block_size: continue if y2 y0 or y1 y0 block_size: continue new_box (x1 - x0, y1 - y0, x2 - x0, y2 - y0) out.append(((x0, y0), new_box)) return outstride256让相邻切块有 64 像素重叠防止目标恰好在切块边缘被截断。切图后务必再跑一次可视化自查我见过有人忘记修正坐标结果模型输出位置整体偏移。相比直接拉高训练分辨率切图对显存友好得多。5.2 P2 检测层把特征图分辨率翻倍切图解决输入粒度P2 检测层解决网络自身的空间粒度。在检测头增加高分辨率特征图输出对小目标是实打实的增益代价是训练时间变长而且高分辨率特征图会放大背景纹理虚警可能上升。我的建议是先在切图基础上加 P2再对比 5.3 节的小目标 mAP 和虚警数。两个指标都变好才留下 P2否则在精度和部署成本之间不值得。5.3 验证看整体 mAP 不如看小目标子集和 PD/FA整体 mAP 经常被中大型目标拉高掩盖小目标漏检。我现在习惯按面积切子集单独评价。用 COCO 工具可以这样from pycocotools.coco import COCO from pycocotools.cocoeval import COCOeval gt COCO(/data/hit-uav/val_gt.json) dt gt.loadRes(/data/hit-uav/val_pred.json) ev COCOeval(gt, dt, bbox) ev.params.imgIds [i for i in gt.getImgIds() if any(a 1024 for a in [o[area] for o in gt.loadAnns(gt.getAnnIds(imgIdsi))])] ev.evaluate() ev.accumulate() ev.summarize()这段代码把验证限制在至少含有一个面积小于 1024 像素目标的图像上得到的是小目标子集 mAP。红外任务还习惯同时统计 PD 和 FAPD 是真目标被检出的比例FA 是虚警数量两者放一起比 mAP 更贴近实际部署感受。我现在拿到一个新红外数据集固定动作永远是先体检、再按序列划分、做完标签可视化这三步没做扎实之前不会让训练脚本占上显存。小目标检测的差距往往不在模型结构而在这些基础环节的较真程度希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑