资讯动态

红外小目标检测:基于YOLOv5的优化实践与踩坑指南

发布时间:2026/10/18 3:12:24 来源:尧图企业网站定制
红外小目标检测听起来是个挺小众的技术方向但如果你真接过类似的项目——像远距离安防监控、工业热缺陷巡检、野外搜救这类场景——就会明白它对算法模型的刁难程度远超想象。目标小到什么程度在640x512的帧里一辆数公里外的车、一个发热设备上十来个像素的异常热点就是你要检测的全部。常规的通用目标检测模型搬过来效果往往一言难尽。我最近正好在一个边缘端红外探测项目里做性能优化模型主线选了YOLOv5s整体折腾下来把mAP0.5从0.34拉到了0.61mAP0.5:0.95从0.13提到了0.24。过程不算惊天动地但里面很多坑和取舍网上零零散散也有人提缺的是有人把它们串起来讲清楚。这篇文章就按我的实际推进路径来写从基线被打脸开始到结构修改、数据增强、损失函数调整再到训练过程中踩过的雷和落地时的落差。如果你想在自己的红外小目标任务上给YOLOv5提速这条链路可以直接照抄。1. 开箱就跑的基线实测mAP0.5只有0.34先说数据场景。我自建的红外测试集来自某安防巡检项目的多个固定机位和无人机采集片段全部是单通道灰度图共12000帧。目标类别有行人、车辆、小型热源设备以及若干个专门的细小红外目标子类。统计下来标注框面积小于32x32像素的目标占比接近67%小于16x16的也有31%。这类数据扔到COCO预训练模型上本身就属于极端长尾。我跑了三组基线模型统一输入分辨率640、批大小32、SGD优化器、初始学习率0.01、300个epoch、未做任何数据增强改动结果如下模型mAP0.5mAP0.5:0.95召回率0.5前向耗时(单卡V100)YOLOv5s0.340.130.413.2msYOLOv5m0.360.140.435.1msYOLOv5x0.380.150.4410.6ms看到没换大模型带来的收益非常有限从s到x的模型参数量翻了近十倍mAP0.5只涨了4个点。这个现象本身就是个重要信号红外小目标场景的瓶颈不在模型容量而在结构设计、训练策略和数据质量。再把错误类型拆开看发现漏检目标里占比最高的是那些对比度偏低、与背景热辐射噪点融为一体的小目标误检则普遍来自建筑物排气口、阳光反射面这类外形酷似目标的区域。换句话说模型根本没有学到小目标的判别性特征而是在靠有限的上下文线索蒙答案。这个基线结果说不上好看但它把我推向了正确的问题小目标检测的优化不能指望单纯堆模型规模和训练量必须先弄清楚YOLOv5在架构上对小目标有多不友好。2. YOLOv5在小目标任务上三个绕不开的结构性短板很多人调不好红外小目标的第一反应是换更大模型或疯狂调参但真正的问题往往埋在结构里。我对YOLOv5做了逐层分析发现三个绕不开的硬伤。2.1 下采样链路太长小目标的特征在路上就丢了YOLOv5的backbone默认从P1到P5逐层下采样最后输出的特征图只有输入尺寸的1/32。拿输入640x640来说P5层只有20x20的网格。一个32x32像素的小目标映射到该层只占大约1x1个格子几乎失去空间结构信息。更小一点的目标在这个层上甚至连存在一处响应都很难保证。那为什么YOLOv5在COCO上小目标检测还算能打因为COCO里的小目标通常不会小于16x16而且在P31/8下采样那层仍能保留相对完整的轮廓。到了红外场景目标往往只有8到15像素P3层上只剩1到2个特征点信息量左右不过几个卷积核的感受野深层特征图里基本就是噪声。小目标不是模糊而是根本无可辨识的纹理。2.2 IoU度量对小目标的位置偏移近乎零容忍回归损失最终要转化为IoU指标但IoU这个度量对小目标极不友好。举一个直观例子两个15x15像素的真实目标框如果预测框整体偏离3个像素横向重叠区域就只剩下12x12像素IoU直接掉到0.47左右而同样偏移3个像素对100x100的大目标来说IoU仍有0.89。换句话说小目标只需要微小的定位误差就会导致回归Loss剧烈升高训练早期会让梯度被这些苛刻的定位错误主导反而拖慢收敛。这一点直接决定了小目标任务的回归损失函数不能原封不动沿用COCO时期验证好的那套CIoU/GIoU策略。后面第五部分我会说怎么换成对尺寸不敏感的度量。2.3 正样本分配机制天然偏向中大型目标YOLOv5的label assignment策略是根据标注框中心点到anchor中心的距离来匹配正样本的。小目标的中心点扰动能力很弱——因为标注框本身的像素波动、抖动都足以让一个本该匹配到某个anchor的小目标被分给邻桌。实际日志里也可以验证训练中期统计正样本数量小目标类别平均每个GT只能匹配到1到2个正样本anchor而中大目标普遍能匹配到5个以上。梯度稀疏直接导致小目标的特征通道长期欠学习。这三个结构性问题叠加起来结论非常明确不改结构、不动损失、不针对数据做增强在红外小目标上硬跑YOLOv5性能上限就在那里。下面开始讲我实际动刀的顺序注意这个顺序是有讲究的——先数据后结构再损失最后才碰训练策略。3. 数据层面最先见效四种增强手段的取舍很多人一上来就改模型结构忽略了数据。我的经验恰好相反红外小目标任务里数据增强的性价比几乎是最高的风险也是最低的。先看常规做法为什么没用。色彩抖动、随机HSV、水平翻转这些手段都是为三通道可见光图像设计的。红外图像是单通道而且目标亮度分布有极强的物理意义——你不可能把热源的颜色随机拧成蓝色那样就失真了。随机翻转对小目标虽然有一定帮助但作用有限真正有效的是下面四种手段。3.1 Copy-Paste小目标复制粘贴这是我最先试也是最推荐的。把训练集里人工标注好的小目标连同周围一圈背景抠出来随机缩放到0.8~1.2倍旋转5度以内然后粘贴到同一张图中的空区域并同步更新标注框。这个操作直接缓解了小目标样本数量不足的问题——我有意把小目标类别的有效样本规模从12000扩充到了接近25000。需要注意一个细节粘贴前要做一次局部对比度的微调让粘贴目标的灰度和粘贴区域背景尽量接近否则模型会学到凡是边界突兀的块就是目标测试时反而把真正的噪声判成目标。另外一次贴1到3个就好别贪多贴多了模型会在高频特征上过拟合。3.2 Random Erasing模拟真实遮挡红外场景里目标经常被建筑物遮挡、被树枝划过这类遮挡在原始数据集里占比不到5%模型几乎没有见过。我用Random Erasing在训练时随机擦除目标的一小块矩形区域模拟遮挡场景。同时刻意保持擦除面积在目标框面积的20%到60%之间。太小没有干扰效果太大则目标直接消失反而把语义带偏。3.3 多尺度抖动必须手动开YOLOv5的主配置里默认不开启多尺度训练但这对于小目标任务几乎是必需品。我把输入尺寸在320到960之间随机变化batch内图像比例保持一致。这一步看似简单实际效果却很大它让模型学习到同一个小目标在不同尺度下该如何响应对红外多焦距、多视距的测试数据非常有用。需要提醒的是开启多尺度后显存波动很剧烈建议配合批大小自适应策略或者干脆把batch size调低一点保证训练稳定性。3.4 基于难例挖掘的伪标签循环当现有模型在小目标上大量漏检时我会用另一个训练较早的模型在困难区域切片上生成低置信度候选人工筛掉明显错误的剩下的作为额外训练数据进入下一轮。这个环节不能省但必须控制伪标签的规模——只挑模型置信度在0.25~0.35之间的候选置信度太高了说明模型本来就稳添加收益低太低了则噪声过大。同时每次迭代之后需要重新评估伪标签对性能的净影响。我遇到过一次阈值调整后mAP反而掉了2个点就是因为伪标签中混入了一批形状相似的热噪区域把模型的判别边界带偏了。4. 给网络加料P2检测头、轻量加权融合与坐标注意力数据层面的提升大概让mAP0.5从0.34到了0.41这时候才开始动结构。动结构的高频原则是能用小改动解决就绝不上大改因为每个结构改动都会带来训练系统工程量和部署端的额外负担。4.1 增加P2小目标检测头YOLOv5默认是下采样8、16、32倍的三层特征检测头。对小目标来说最有效的做法是再增加一个下采样4倍的P2层。实现并不复杂配置文件中添加一组anchor对应的stride调整为4同时在模型forward返回该层的特征图参与检测。注意anchor尺寸要根据数据集小目标分布重新聚类我用KMeans跑了500轮发现红外小目标的anchor尺寸普遍集中在6~12像素区间和COCO的默认anchor完全不在一个量级。P2层带来的问题是显存和计算量的明显上涨。我的实测结果P2加入后训练显存从单卡11GB升至16GB左右推理前向时间从3.2ms涨到4.1ms。但对于红外小目标来说这个代价是完全值得的它让模型第一次有机会在16x16以上的特征分辨率上看到目标。4.2 用轻量加权融合替代部分PANet结构YOLOv5的PANet只是简单地把特征层相加concatenate或add没有考虑不同层特征对尺度的贡献差异。我参考BiFPN的思路给P3到P5的特征融合路径加了可学习的权重。实现时为了不引入太多额外计算只做了一次加权融合没有像EfficientDet那样反复堆叠。训练完成后观察训练好的权重P2和P3层的融合权重明显高于P5——这验证了一个直觉小目标的主要识别特征来自浅层高层特征提供的上下文在检测大目标时更有增益。换句话说把高层特征同等强度地喂给小目标检测头反而会稀释局部细节。4.3 坐标注意力模块的位置与大小针对红外小目标我尝试过在backbone和neck中插入SE、CBAM和坐标注意力模块。实验坐标注意力效果最稳定它同时编码通道关系和空间坐标信息比如目标在图像左上角和右下角时模型可以通过位置先验获得额外线索这对远处小目标的空间定位有实际提升。注意力模块我只加在P3和P4层没有加到P5理由是小目标检测主要依赖浅层特征高位层加注意力容易把热噪声误认为语义信息。模块数也不宜多我只在C3结构之后插入了4个坐标注意力块参数量增加了约1.8M前向时间增加0.5ms。如果要部署在边缘设备上还得注意算子兼容性问题——部分注意力实现不好移植到TensorRT。5. 损失函数层面的三处调整NWD、Focal调参与分阶段切换结构改完我又花了整整一周和损失函数死磕。这段经验可能对不少刚入坑的同学最有价值因为网上讨论损失函数在小目标上的细节本来就不多。5.1 为什么把IoU系列度量换成NWD前面说过IoU对小目标定位误差极其敏感直接后果是训练早期回归Loss震荡剧烈。这里我用了一个替代度量Normalized Wasserstein DistanceNWD。核心思路不复杂把目标框建模成二维高斯分布用分布之间的Wasserstein距离来衡量框和框的相似度。归一化后它对目标的绝对尺寸不敏感小目标偏移几个像素不会像IoU那样造成Loss陡增。NWD替换逻辑很简单在损失计算里将box_loss部分由CIoU切换为NWD。我实测下来单独替换NWD之后训练loss曲线明显平缓mAP0.5在前50轮就能看到比原来高3个点的优势。5.2 Focal Loss参数alpha/gamma需要重新标定红外小目标的正负样本比例失衡比COCO严重得多默认的bce_logits损失对小目标极其吃力。我在分类分支外加了Focal Loss拿两个关键参数做了消融gamma2.0时对低置信度的假阳性的压制最好但它也会压制小目标初始阶段本就不高的分类分数。alpha从0.25提到0.75能明显提升小目标召回但代价是误检数量同步增加。最终我落在alpha0.5、gamma1.5——这是在我这个数据集上F1最高的一组它不是某个算法都适用的万能参数但至少说明一个路径小目标场景的Focal参数不能照搬COCO那套。5.3 回归损失分阶段切换前NWD后CIoU这是我认为最实用也最容易被忽略的细节。NWD虽然对小目标友好但它的度量语义并不完全等同于location精度。如果全程用NWD后期的框回归精度会留着模糊地带而前期若直接上CIoU小目标会在过渡阶段疯狂震荡收敛极慢。我的做法是把训练分成两段前150轮用NWD把模型拉到小目标大致框准的状态后100轮切回CIoU做精细调整。实际结果比任何一个单独用到底的方案都好mAP0.5几乎全面提升而且没有出现原先那种后期loss反复横跳的情况。如果你嫌两阶段麻烦也可以只在最后50轮切换效果会打点折扣但没那么明显。关键是不要全程只用NWD。6. 训练过程三次翻车与完整排查链路这一节不写结论只写我真实的踩坑过程。三次翻车每次都是搜索引擎和社交平台上一句话带过、但真正遇到时你可能要耗一整天的类型。6.1 混合精度训练中途NAN先锁定范围再动刀开启AMP后某次训练跑到约110轮时loss直接跳成NAN模型当场报废。第一次遇到时只能重新开跑但第二次我做了系统性排查。排查链路分四步。第一步看NAN出现在哪分别打印cls_loss、box_loss、obj_loss发现box_loss先爆了。第二步切回FP32复跑同一轮NAN消失——确认问题出在AMP的梯度缩放特殊情况下。第三步对比了前后几个batch的梯度统计发现某个含大量极小目标batch里groud truth匹配率极低导致部分box回归分支出现异常梯度值。第四步动刀在训练配置中启用梯度裁剪把max_grad_norm调成10.0并把AMP的grad_scaler初始化得更保守。之后再没有出现NAN。这里有个经验补充如果你没有设置梯度裁剪的习惯小目标数据里已经存在很多resize造成的极端样本NAN大概率会随机爆一次早点把裁剪值调下来能省下大量重训时间。6.2 学习率周期策略余弦退火反而不理想默认的cosine lr策略在训练中期会快速降低学习率对小目标这种样本少、出现时间随机的场景并不合适。中期学习率一低遇到一批从未见过的难例小目标时模型几乎无法吸收新信息。我用的是warmup线性衰减前5轮线性warmup从0.0001到0.01之后线性衰减到0.0001。相比cosine线性衰减在这个任务上更稳mAP0.5的方差明显更小。如果你的训练集和我的情况类似建议还是优先试线性衰减它能少吃很多亏。6.3 EMA参数导致小目标记忆丢失YOLOv5自带的EMA指数移动平均可以让模型更平滑但默认衰减参数在红外小目标上也会带来副作用。小目标样本在数据集中本就是少量且分布不均匀的EMA过强的记忆惯性会淡化新学习到的小目标特征导致每个epoch结束测试时性能时好时坏。我的做法是把衰减参数从默认的0.9998下调到0.9990让EMA模型更跟随最新状态。这个直觉很反直觉但实测让最终测试集的mAP上涨约1.8个点代价是训练指标波动大了一些收尾阶段需要掐好保存时机。7. 消融实验汇总与真实落地中的收益落差所有改动做完我补了一轮完整的消融实验确保每项改动都有独立贡献而不是互相抵消。配置mAP0.5mAP0.5:0.95召回率0.5FPS (TensorRT bs1)基线YOLOv5s0.340.130.4162数据增强组合0.410.170.4962P2检测头与加权融合0.530.210.5843坐标注意力0.560.230.6139NWD与分阶段损失0.590.240.6439训练策略修正0.610.240.6639看着还不错对吧但落地到真实边缘端之后我不得不泼一盆冷水。单位是39FPS对实时任务勉强够用但现场部署测试时误检率还是偏高尤其是我前面说过的那类排气口、热反射面——数据增强再巧妙也很难让模型在训练阶段见过所有类型的热噪声。更关键的问题出现在数据采集端我发现的小目标在真实画面里很多目标因为镜头光学散焦、传感器抖动已经模糊成了半像素级或亚像素级亮斑。检测算法在这种输入上无论如何优化上限都会被物理前端卡死。回头推动了一下采集策略——提高机位分辨率、缩小焦距切换间隔、增加多角度标定——后续测试集性能才有质的变化。所以如果你问我YOLOv5能否在红外小目标上做到实用我的答案是可以但要认清真正的瓶颈链条模型结构是必要数据增强是主力物理前端是隐形天花板。与其沉迷把网络的最后几个点抠出来不如先审视你的红外传感器和标注一致性——那才是小目标检测项目最容易被忽略的杠杆点。最后分享一个细节经验我踩过坑之后才总结出来的在标注红外小目标时如果一张图里的目标只有5到8个像素建议直接把它标记为忽略或专门设一个类别特殊处理而不要硬塞进普通类别里。因为这类样本如果占比不高只会作为噪声干扰整个类别的训练占比高了又会把通用类别的语义带偏。宁可让模型在5像素目标上彻底漏检也好过让它把热噪声当成目标的基础特征。这个反直觉的选择在我后来的项目里省掉了大量误报排查时间。

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

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

免费获取报价 →
↑