YOLO 涨点研究(九):多模态融合检测篇------RGB-红外融合的网络结构与论文全解析
本系列博客旨在从源码层面拆解 YOLO 的每一个技术细节,找到涨点突破口。
第一篇:《YOLO 全代码详细解读:从预处理到后处理的完整数据流动》
第二篇:《YOLO 涨点研究(二):Loss 函数深度解析与正负样本分配策略》
第三篇:《YOLO 涨点研究(三):数据增强策略深度解析与涨点技巧》
第四篇:《YOLO 涨点研究(四):网络结构改进与涨点技巧》
第五篇:《YOLO 涨点研究(五):模块优化的实验设计与代码落实全指南》
第六篇:《YOLO 涨点研究(六):网络结构改进之小目标增强篇1------无人机视角下的车辆与行人检测》
第七篇:《YOLO 涨点研究(七):网络结构改进之小目标增强篇2------损失函数与训练策略》
第八篇:《YOLO 涨点研究(八):定向目标检测篇------旋转框检测的网络结构、损失函数与论文全解析》
第九篇:多模态融合检测篇------RGB-红外融合的网络结构与论文全解析(本文)
📑 目录
- [一、为什么需要 RGB-红外融合检测?](#一、为什么需要 RGB-红外融合检测?)
- [1.1 RGB 与红外的互补性](#1.1 RGB 与红外的互补性)
- [1.2 融合的三个层级](#1.2 融合的三个层级)
- [1.3 多模态融合的核心挑战](#1.3 多模态融合的核心挑战)
- 二、数据集全景
- [2.1 DroneVehicle(无人机 RGB-红外车辆检测)](#2.1 DroneVehicle(无人机 RGB-红外车辆检测))
- [2.2 FLIR(自动驾驶 RGB-红外)](#2.2 FLIR(自动驾驶 RGB-红外))
- [2.3 LLVIP(低光照行人检测)](#2.3 LLVIP(低光照行人检测))
- [2.4 VEDAI(航拍车辆检测)](#2.4 VEDAI(航拍车辆检测))
- [2.5 数据集对比汇总表](#2.5 数据集对比汇总表)
- 三、融合策略详解
- [3.1 像素级融合(图像级)](#3.1 像素级融合(图像级))
- [3.2 特征级融合(Backbone/Neck 级)](#3.2 特征级融合(Backbone/Neck 级))
- [3.3 决策级融合(结果级)](#3.3 决策级融合(结果级))
- [3.4 三种融合策略对比](#3.4 三种融合策略对比)
- [四、跨模态对齐:TSRA 模块深度解析](#四、跨模态对齐:TSRA 模块深度解析)
- [4.1 跨模态弱错位问题](#4.1 跨模态弱错位问题)
- [4.2 TSRA 论文分析(ECCV 2022)](#4.2 TSRA 论文分析(ECCV 2022))
- [4.3 TSRA 代码实现](#4.3 TSRA 代码实现)
- 五、模态不平衡问题与解决方案
- [5.1 什么是模态不平衡?](#5.1 什么是模态不平衡?)
- [5.2 不确定性感知融合(UA-CMDet)](#5.2 不确定性感知融合(UA-CMDet))
- [5.3 条件感知动态融合(PCDF)](#5.3 条件感知动态融合(PCDF))
- [5.4 模态优势分层学习](#5.4 模态优势分层学习)
- 六、经典论文深度分析
- [6.1 CFT(2021)------跨模态融合 Transformer 的开山之作](#6.1 CFT(2021)——跨模态融合 Transformer 的开山之作)
- [6.2 MFPT(IEEE TITS 2023)------多模态特征金字塔 Transformer](#6.2 MFPT(IEEE TITS 2023)——多模态特征金字塔 Transformer)
- [6.3 C2Former(2023)------校准与互补 Transformer](#6.3 C2Former(2023)——校准与互补 Transformer)
- [6.4 CALNet(ACM MM 2023)------跨模态冲突感知学习](#6.4 CALNet(ACM MM 2023)——跨模态冲突感知学习)
- [6.5 MDCFT-HSM(2026)------模态偏移感知小目标检测](#6.5 MDCFT-HSM(2026)——模态偏移感知小目标检测)
- [6.6 DyFCLT(CVPR 2026)------动态频率解耦跨模态学习](#6.6 DyFCLT(CVPR 2026)——动态频率解耦跨模态学习)
- [6.7 论文汇总表](#6.7 论文汇总表)
- [七、YOLO 双模态融合完整代码实现](#七、YOLO 双模态融合完整代码实现)
- [7.1 双流 Backbone 架构](#7.1 双流 Backbone 架构)
- [7.2 跨模态注意力融合模块](#7.2 跨模态注意力融合模块)
- [7.3 双模态数据集加载器](#7.3 双模态数据集加载器)
- [7.4 完整训练配置](#7.4 完整训练配置)
- 八、实验设计与涨点路线
- [8.1 消融实验设计模板](#8.1 消融实验设计模板)
- [8.2 涨点路线图](#8.2 涨点路线图)
- [8.3 超参数推荐](#8.3 超参数推荐)
- 九、总结与下篇预告
一、为什么需要 RGB-红外融合检测?
1.1 RGB 与红外的互补性
在无人机、自动驾驶、安防等场景中,单一 RGB 摄像头在夜间、低光照、恶劣天气 下性能急剧下降。红外(热成像)摄像头通过探测物体的热辐射成像,不受光照影响,但缺乏颜色和纹理信息。两者具有天然的互补性:
RGB vs 红外 特性对比:
┌──────────────────┬──────────────────────┬──────────────────────┐
│ 特性 │ RGB (可见光) │ 红外 (热成像) │
├──────────────────┼──────────────────────┼──────────────────────┤
│ 成像原理 │ 反射光 │ 热辐射 │
│ 光照依赖 │ 强依赖(夜间失效) │ 不依赖(全天可用) │
│ 颜色/纹理信息 │ 丰富 │ 缺乏(灰度) │
│ 边缘/轮廓信息 │ 受光照影响 │ 清晰(热边界明显) │
│ 小目标检测 │ 纹理丰富时好 │ 热对比度高时好 │
│ 恶劣天气 │ 受雨雾影响大 │ 穿透性较好 │
│ 计算成本 │ 3通道 │ 1通道 │
└──────────────────┴──────────────────────┴──────────────────────┘
典型场景互补:
白天: RGB清晰, 红外也有热对比度 → 融合提升定位精度
夜间: RGB噪点多/全黑, 红外清晰 → 红外主导, RGB提供辅助
雨雾: RGB穿透差, 红外穿透较好 → 红外主导
伪装: RGB被欺骗, 红外能探测热源 → 红外主导
结论 :RGB-红外融合能实现全天候、全场景的鲁棒检测,是无人机和自动驾驶的核心技术方向。
1.2 融合的三个层级
根据融合发生的位置,多模态融合可分为三个层级:
融合层级分类:
层级1: 像素级融合 (早期融合)
RGB图像 ──┐
├→ 图像融合算法 → 融合图像 → 单模态检测器 → 检测结果
红外图像 ─┘
代表方法: 图像融合网络(IFN)、简单拼接(6通道输入)
优势: 保留原始信息, 检测器无需修改
劣势: 图像融合可能引入伪影, 计算量大
层级2: 特征级融合 (中期融合) ⭐最常用
RGB图像 → RGB Backbone ──┐
├→ 特征融合模块 → 融合特征 → 检测头 → 检测结果
红外图像 → IR Backbone ───┘
代表方法: CFT、MFPT、C2Former、CALNet、双流YOLO
优势: 融合语义特征, 灵活高效, 性能最好
劣势: 需要设计融合模块, 双Backbone参数量大
层级3: 决策级融合 (晚期融合)
RGB图像 → RGB检测器 ──┐
├→ 结果融合(NMS/投票) → 最终检测结果
红外图像 → IR检测器 ───┘
代表方法: 双检测器NMS、加权投票、UA-CMDet三检测头
优势: 模态独立, 一个模态失效不影响另一个, 实现简单
劣势: 无法利用模态间的互补特征, 性能上限低
1.3 多模态融合的核心挑战
挑战1: 模态异质性 (Modality Heterogeneity)
RGB和红外的视觉差异巨大 → 特征分布不同 → 直接融合效果差
解决: 跨模态注意力、模态特定分支、校准模块
挑战2: 跨模态错位 (Cross-Modal Misalignment)
双摄像头视角不同 → 同一目标在两幅图像中位置/尺度/角度有偏差
解决: TSRA对齐模块、可变形卷积对齐、显式偏移预测
挑战3: 模态不平衡 (Modality Imbalance)
不同场景下两种模态的"可信度"不同 → 简单融合会被低质量模态拖累
解决: 不确定性感知、条件感知动态融合、模态门控
挑战4: 模态冲突 (Modality Conflict)
某些区域RGB和红外给出矛盾信息 → 融合时产生语义冲突
解决: 冲突感知学习(CALNet)、选择性融合、冲突矫正
挑战5: 计算效率
双Backbone参数量翻倍 → 推理速度慢 → 难以实时部署
解决: 共享Backbone、轻量化融合模块、模态蒸馏
挑战6: 数据对齐与标注
双模态图像需要精确配准 → 标注成本高 → 部分数据集标注不完全对齐
解决: 无对齐训练(AlignFreeNet)、弱对齐学习、自动配准
二、数据集全景
2.1 DroneVehicle(无人机 RGB-红外车辆检测)
论文信息:
- 标题:DroneVehicle: A Large-scale Dataset for Vision-based Drone Detection
- 作者:Ye Yu, et al.
- 年份:2022
- 官网:https://github.com/VisDrone/DroneVehicle
- 下载:https://github.com/VisDrone/DroneVehicle
数据集详情(第八篇已详细介绍,这里补充融合相关信息):
- 图像对数:28,439 对(RGB + 红外配准图像对)
- 训练集:17,990 对 | 验证集:1,469 对 | 测试集:8,980 对
- 实例数:441,649 个
- 类别数:5 类(car、truck、bus、van、freight-car)
- 标注格式:旋转框(OBB),四点坐标
- 场景:城市道路、停车场、居民区,覆盖白天和夜晚
- 配准精度:RGB与红外图像经过硬件级配准,像素级对齐(但仍有微弱错位)
为什么是多模态融合的核心数据集:
- 目前最大的无人机 RGB-红外车辆检测数据集。
- 覆盖白天/夜晚,能充分验证融合的全天候优势。
- 全部是车辆类,类别间差异小,细分类挑战大。
- 旋转框标注,可同时研究旋转检测和多模态融合。
当前 SOTA 性能(mAP@0.5):
- 单模态 RGB:~72% | 单模态 IR:~75% | 多模态融合:~80%+
- PCDF(ICCV 2025):79.7%
- IGIANet:80.9%
2.2 FLIR(自动驾驶 RGB-红外)
论文信息:
- 标题:FLIR Thermal Dataset for Algorithm Training
- 作者:FLIR Systems
- 年份:2018
- 下载:https://www.flir.com/oem/adas/adas-dataset-form/
数据集详情:
- 图像对数:14,452 对(训练10,228 + 验证1,968 + 测试2,256)
- 类别数:3 类(car、person、bicycle)+ 部分视频有 dog 等
- 标注格式:水平框(HBB)
- 场景:自动驾驶街景,白天和夜晚
- 分辨率:RGB 1280×720,红外 640×512(分辨率不同,需要对齐)
- 配准:提供粗略的空间对齐,但不完全精确
特点:
- 自动驾驶场景,行人和车辆混合。
- RGB和红外分辨率不同,需要处理尺度差异。
- 夜晚场景中红外明显优于RGB,融合优势显著。
2.3 LLVIP(低光照行人检测)
论文信息:
- 标题:LLVIP: A Low-Light Visible-Infrared Pair Dataset for Pedestrian Detection
- 作者:Jiaheng Zhu, et al.
- 会议:ICCV 2021
- 下载:https://bupt-ai-cz.github.io/LLVIP/
数据集详情:
- 图像对数:30,200 对(训练20,600 + 测试9,600)
- 实例数:89,404 个行人
- 类别数:1 类(pedestrian)
- 标注格式:水平框(HBB)
- 场景:低光照/夜间街景,专门针对低光照条件
- 分辨率:1280×720
- 配准:精确配准,像素级对齐
特点:
- 专门针对低光照场景,RGB图像噪点多、对比度低。
- 红外图像在低光照下清晰,融合优势极其显著。
- 只有行人类,适合研究行人检测的多模态融合。
2.4 VEDAI(航拍车辆检测)
论文信息:
- 标题:Vehicle Detection in Aerial Imagery
- 作者:R. Laganière, et al.
- 年份:2015
- 下载:https://downloads.greyc.fr/vedai/
数据集详情:
- 图像对数:1,270 对(RGB + 红外)
- 实例数:~4,000 个车辆
- 类别数:9 类(car、truck、van、bus、pickup、boat、plane、tractor、camping-car)
- 标注格式:水平框 + 方向角
- 场景:航拍(无人机/卫星),农村和城市
- 分辨率:1024×1024
特点:
- 航拍视角,目标小(类似DroneVehicle)。
- 数据集较小,适合快速实验。
- 多类别(9类),比DroneVehicle的5类更丰富。
2.5 数据集对比汇总表
| 数据集 | 年份 | 图像对数 | 类别数 | 标注格式 | 场景 | 配准精度 | 分辨率 | 适用研究 |
|---|---|---|---|---|---|---|---|---|
| DroneVehicle | 2022 | 28,439 | 5 | OBB旋转框 | 无人机车辆 | 高(硬件级) | 各异 | 无人机+旋转+融合 |
| FLIR | 2018 | 14,452 | 3 | HBB水平框 | 自动驾驶 | 中(粗略) | 不同 | 自动驾驶+多分辨率 |
| LLVIP | 2021 | 30,200 | 1 | HBB水平框 | 低光照行人 | 高(精确) | 1280×720 | 低光照+行人 |
| VEDAI | 2015 | 1,270 | 9 | HBB+角度 | 航拍车辆 | 中 | 1024×1024 | 航拍+多类别 |
| KAIST | 2018 | 95,000+ | 1-3 | HBB | 自动驾驶行人 | 中 | 640×512 | 行人+多场景 |
| M3FD | 2022 | 4,800 | 4 | HBB | 自动驾驶 | 高 | 1024×768 | 融合检测+雾天 |
三、融合策略详解
3.1 像素级融合(图像级)
核心思想:先将 RGB 和红外图像融合为一幅图像,然后用普通单模态检测器检测。
像素级融合流程:
RGB(3ch) ──┐
├→ 图像融合网络 → 融合图像(3ch) → YOLO → 检测结果
IR(1ch) ───┘
常见融合方式:
1. 简单拼接: 6通道输入 → 1×1卷积降为3通道
2. 图像融合网络: 基于CNN/Transformer的图像融合(如DenseFuse、U2Fusion)
3. 加权平均: 融合 = α·RGB + (1-α)·IR (α可学习)
优点:
- 检测器无需修改,直接用现成的YOLO。
- 融合后的图像可以可视化,便于分析。
- 保留了原始像素级信息。
缺点:
- 图像融合可能引入伪影(尤其在边缘区域)。
- 融合质量直接影响检测性能,融合算法需要单独训练。
- 计算量大(融合网络 + 检测器)。
- 无法利用模态间的语义互补(融合在像素级,语义信息丢失)。
适用场景:
- 快速验证融合是否有增益(用简单拼接即可)。
- 检测器不可修改的场景(如使用预训练检测器)。
- 对融合图像有可视化需求的场景。
3.2 特征级融合(Backbone/Neck 级)⭐最常用
核心思想:RGB 和红外分别通过各自的 Backbone 提取特征,然后在特征图层面进行融合,融合后的特征送入检测头。
特征级融合流程:
RGB图像 → RGB Backbone → RGB特征图(P3/P4/P5) ──┐
├→ 特征融合模块 → 融合特征 → 检测头 → 结果
IR图像 → IR Backbone → IR特征图(P3/P4/P5) ──────┘
融合位置选择:
位置A: Backbone浅层融合 (P2/P3) → 融合细节信息
位置B: Backbone深层融合 (P4/P5) → 融合语义信息
位置C: Neck中融合 (PAN-FPN) → 多尺度融合
位置D: 多阶段融合 (浅层+深层都融合) → 最全面但计算量大
常见融合方式:
1. 逐元素相加/拼接: F_fused = F_rgb + F_ir (或concat后1×1卷积)
2. 跨模态注意力: 用注意力机制加权融合 (CFT、C2Former)
3. 门控融合: 学习每个模态的门控权重 (模态不平衡)
4. Transformer融合: 用自注意力建模模态间关系 (MFPT)
优点:
- 融合语义特征,能充分利用模态间的互补性。
- 融合模块设计灵活,可以针对不同场景优化。
- 性能最好,是当前 SOTA 方法的主流选择。
- 可以在多个尺度融合,适应不同大小的目标。
缺点:
- 双 Backbone 参数量翻倍(约 2×)。
- 融合模块增加计算量。
- 需要精心设计融合策略,简单融合效果可能不如单模态。
- 训练难度大(模态异质性、不平衡等问题)。
适用场景:
- 追求最高检测精度。
- 有足够的计算资源(双 Backbone)。
- 需要研究多模态融合的创新点。
3.3 决策级融合(结果级)
核心思想:RGB 和红外分别通过独立的检测器得到检测结果,然后在结果层面融合。
决策级融合流程:
RGB图像 → RGB检测器 → RGB检测框 ──┐
├→ 结果融合 → 最终检测结果
IR图像 → IR检测器 → IR检测框 ──────┘
常见融合方式:
1. 联合NMS: 将两个模态的检测框合并后做NMS
2. 加权投票: 同一目标的两个模态检测结果加权平均
3. 三检测头: 共享Backbone, 三个检测头(RGB/IR/融合), 如UA-CMDet
4. 模态选择: 根据场景条件选择更可信的模态结果
优点:
- 模态完全独立,一个模态失效不影响另一个(鲁棒性强)。
- 实现简单,不需要修改检测器内部。
- 可以使用不同的检测器处理不同模态(如RGB用YOLOv8,红外用YOLOv5)。
- 推理时可以只运行一个模态(节能模式)。
缺点:
- 无法利用模态间的特征级互补,性能上限低。
- 两个检测器的计算量翻倍(推理时需要跑两个检测器)。
- 结果融合可能引入误检(两个模态的误检叠加)。
- 难以处理跨模态错位(同一目标在两个模态中位置不同)。
适用场景:
- 对鲁棒性要求极高(一个模态可能完全失效)。
- 快速验证融合增益(不需要训练融合网络)。
- 计算资源有限但可以接受两个检测器串行推理。
3.4 三种融合策略对比
| 维度 | 像素级融合 | 特征级融合 ⭐ | 决策级融合 |
|---|---|---|---|
| 融合位置 | 输入图像 | 特征图 | 检测结果 |
| 检测器修改 | 无需 | 需要融合模块 | 无需 |
| 参数量 | 1×(融合网络小) | ~2×(双Backbone) | 2×(双检测器) |
| 推理速度 | 中 | 慢 | 最慢(两个检测器) |
| 检测精度 | 中 | 最高 | 较低 |
| 模态互补利用 | 弱(像素级) | 强(语义级) | 弱(结果级) |
| 鲁棒性(单模态失效) | 差 | 中 | 最好 |
| 实现难度 | 低 | 高 | 低 |
| 适用场景 | 快速验证 | 追求精度 | 追求鲁棒性 |
| 代表方法 | 6通道输入、DenseFuse | CFT、MFPT、C2Former、CALNet | 联合NMS、UA-CMDet |
💡 选择建议:
- 入门/快速验证:像素级(6通道输入,最简单)。
- 追求精度/发论文:特征级(当前 SOTA 主流,创新点多)。
- 追求鲁棒性/工程部署:决策级(模态独立,故障隔离)。
- 最佳实践:特征级为主,辅以决策级(如三检测头设计,兼顾精度和鲁棒性)。
四、跨模态对齐:TSRA 模块深度解析
4.1 跨模态弱错位问题
在 RGB-红外双模态系统中,即使经过硬件级配准,仍然存在微弱的跨模态错位:
跨模态弱错位的成因:
1. 视角差异 (Parallax)
RGB摄像头和红外摄像头位置不同 → 同一目标在两幅图像中视角不同
→ 近距离目标错位明显, 远距离目标错位小
2. 标定误差 (Calibration Error)
双摄像头的外参标定存在误差 → 配准不完全精确
→ 通常有 1-5 像素的错位
3. 时间不同步 (Temporal Misalignment)
两个摄像头的曝光时间不同 → 运动目标位置不同
→ 高速运动目标错位明显
4. 分辨率差异 (Resolution Difference)
RGB和红外分辨率不同(如FLIR: RGB 1280×720, IR 640×512)
→ 缩放后存在亚像素错位
5. 畸变差异 (Distortion Difference)
两个摄像头的镜头畸变不同 → 边缘区域错位明显
弱错位的影响:
同一目标在RGB特征图和IR特征图中的位置相差几个像素
→ 直接融合时, 两个模态的特征不对齐
→ 融合特征混乱, 检测性能下降
→ 小目标受影响最大(几个像素的错位可能覆盖整个小目标)
4.2 TSRA 论文分析(ECCV 2022)
论文信息:
- 标题:Translation, Scale and Rotation: Cross-Modal Alignment Meets RGB-Infrared Vehicle Detection
- 作者:Maoxun Yuan, Yinyan Wang, Xingxing Wei
- 会议:ECCV 2022
- 代码:https://github.com/yuanmaoxun/TSRA
核心问题 :
现有跨模态对齐方法只考虑平移(Translation)对齐,忽略了尺度(Scale)和旋转(Rotation)差异。但在航拍图像中,由于视角差异,同一目标在 RGB 和红外中不仅位置有偏移,尺度和角度也可能不同。
核心方法 :
TSRA(Translation-Scale-Rotation Alignment)模块预测两个模态之间的平移、尺度、旋转偏移量,然后对特征图进行几何变换对齐:
TSRA 模块结构:
RGB特征 F_rgb ──┐
├→ 偏移预测网络 → (Δtx, Δty, Δsx, Δsy, Δθ)
IR特征 F_ir ────┘
│
↓
几何变换对齐
F_ir_aligned = Affine(F_ir, Δtx, Δty, Δsx, Δsy, Δθ)
│
↓
融合: F_fused = F_rgb + F_ir_aligned (或注意力融合)
偏移预测网络:
输入: concat(F_rgb, F_ir) → 卷积 → 全局平均池化 → FC → 5维输出
输出: (Δtx, Δty) 平移偏移, (Δsx, Δsy) 尺度偏移, Δθ 旋转偏移
Modality-Selection (MS) 策略:
当两个模态差异过大时(对齐不可靠), 选择更可信的模态主导
用不确定性估计判断对齐质量
为什么有效:
- 同时对齐平移、尺度、旋转,比只对齐平移更全面。
- 可微的几何变换(空间变换网络STN),可以端到端训练。
- Modality-Selection 策略避免了不可靠对齐导致的性能下降。
实验结果(DroneVehicle):
- mAP@0.5:从 76.2%(无对齐)提升到 78.5%(+2.3)
- 在小目标上提升更明显(+3.1)
- 平移对齐只提升 1.2%,尺度+旋转对齐额外提升 1.1%
局限性:
- 全局对齐(整幅特征图用同一个变换参数),无法处理局部错位。
- 偏移预测网络增加计算量。
- 当错位过大时(>10像素),对齐效果下降。
4.3 TSRA 代码实现
python
"""
TSRA (Translation-Scale-Rotation Alignment) 模块实现
论文: Translation, Scale and Rotation: Cross-Modal Alignment Meets RGB-Infrared Vehicle Detection (ECCV 2022)
"""
import torch
import torch.nn as nn
import torch.nn.functional as F
class TSRA(nn.Module):
"""
平移-尺度-旋转跨模态对齐模块
用IR特征对齐到RGB特征(也可以反过来)
"""
def __init__(self, channels=256, reduction=16):
super().__init__()
# 偏移预测网络
self.offset_predictor = nn.Sequential(
nn.Conv2d(channels * 2, channels // reduction, 1),
nn.BatchNorm2d(channels // reduction),
nn.ReLU(),
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(channels // reduction, 5), # 5个参数: tx, ty, sx, sy, theta
)
# 初始化偏移为0(初始时不对齐)
nn.init.zeros_(self.offset_predictor[-1].weight)
nn.init.zeros_(self.offset_predictor[-1].bias)
# 模态选择门控
self.modality_gate = nn.Sequential(
nn.Conv2d(channels * 2, channels // reduction, 1),
nn.ReLU(),
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(channels // reduction, 1),
nn.Sigmoid(),
)
def forward(self, f_rgb, f_ir):
"""
Args:
f_rgb: RGB特征 (B, C, H, W)
f_ir: IR特征 (B, C, H, W)
Returns:
f_fused: 对齐融合后的特征
f_ir_aligned: 对齐后的IR特征
"""
B, C, H, W = f_rgb.shape
# 预测偏移参数
concat_feat = torch.cat([f_rgb, f_ir], dim=1)
offset = self.offset_predictor(concat_feat) # (B, 5)
tx, ty, sx, sy, theta = offset[:, 0], offset[:, 1], offset[:, 2], offset[:, 3], offset[:, 4]
# 构造仿射变换矩阵
# 尺度缩放 (限制在 0.8-1.2 范围)
sx = torch.clamp(sx, -0.2, 0.2) + 1.0
sy = torch.clamp(sy, -0.2, 0.2) + 1.0
# 旋转角度 (限制在 -15°~15°)
theta = torch.clamp(theta, -0.26, 0.26) # 弧度
cos_theta = torch.cos(theta)
sin_theta = torch.sin(theta)
# 仿射矩阵 [a, b, c; d, e, f]
a = sx * cos_theta
b = -sx * sin_theta
c = tx # 平移归一化到 [-1, 1]
d = sy * sin_theta
e = sy * cos_theta
f = ty
theta_matrix = torch.stack([
torch.stack([a, b, c], dim=1),
torch.stack([d, e, f], dim=1),
], dim=1) # (B, 2, 3)
# 生成采样网格并对IR特征进行仿射变换
grid = F.affine_grid(theta_matrix, f_ir.size(), align_corners=False)
f_ir_aligned = F.grid_sample(f_ir, grid, align_corners=False, padding_mode='border')
# 模态选择: 计算对齐可信度, 决定融合权重
gate = self.modality_gate(concat_feat) # (B, 1)
gate = gate.view(B, 1, 1, 1)
# 融合: gate=1时完全用对齐后的IR, gate=0时完全用RGB
f_fused = gate * f_ir_aligned + (1 - gate) * f_rgb
return f_fused, f_ir_aligned
class MultiScaleTSRA(nn.Module):
"""
多尺度TSRA: 在P3/P4/P5三个尺度分别对齐
"""
def __init__(self, channels_list=[256, 512, 1024]):
super().__init__()
self.tsra_modules = nn.ModuleList([
TSRA(channels=c) for c in channels_list
])
def forward(self, f_rgb_list, f_ir_list):
"""
f_rgb_list: [P3_rgb, P4_rgb, P5_rgb]
f_ir_list: [P3_ir, P4_ir, P5_ir]
"""
f_fused_list = []
for tsra, f_rgb, f_ir in zip(self.tsra_modules, f_rgb_list, f_ir_list):
f_fused, _ = tsra(f_rgb, f_ir)
f_fused_list.append(f_fused)
return f_fused_list
💡 使用建议:
- TSRA 通常放在特征融合之前,先对齐再融合。
- 偏移参数的范围要限制(平移±0.1、尺度0.8-1.2、旋转±15°),避免过度变换。
- 初始化偏移为0,让网络从"不对齐"开始学习,训练更稳定。
- 模态选择门控很重要,当对齐不可靠时避免错误对齐导致性能下降。
- 对于局部错位严重的场景,可以考虑用可变形卷积(DCN)代替全局仿射变换。
五、模态不平衡问题与解决方案
5.1 什么是模态不平衡?
模态不平衡是指不同场景下,RGB 和红外两种模态的"可信度"或"贡献度"不同,简单的等权融合会被低质量模态拖累:
模态不平衡的典型场景:
场景1: 白天晴朗
RGB: 清晰, 纹理丰富, 可信度高 → 应该主导融合
红外: 也清晰, 但热对比度低 → 辅助
等权融合问题: 红外的低对比度特征稀释了RGB的丰富纹理
场景2: 夜间/低光照
RGB: 噪点多, 全黑, 可信度低 → 应该弱化
红外: 清晰, 热对比度高 → 应该主导
等权融合问题: RGB的噪点污染了红外的清晰特征
场景3: 雨雾天气
RGB: 穿透差, 模糊 → 应该弱化
红外: 穿透较好 → 应该主导
等权融合问题: RGB的模糊特征拖累融合质量
场景4: 目标热特征弱(如与环境温度接近的车辆)
RGB: 清晰 → 应该主导
红外: 热对比度低, 目标不明显 → 辅助
等权融合问题: 红外的弱特征稀释了RGB的清晰特征
模态不平衡的本质:
融合权重应该是 "动态的、场景感知的、样本级的"
而不是 "固定的、全局的、等权的"
5.2 不确定性感知融合(UA-CMDet)
论文信息:
- 标题:Drone-based RGB-Infrared Cross-Modality Vehicle Detection via Uncertainty-Aware Learning
- 作者:Yiming Sun, et al.
- 年份:2020(arXiv:2003.02437)
- 代码:https://github.com/visor-uav/UA-CMDet
核心问题 :
不同模态在不同场景下的不确定性不同,简单融合没有考虑这种不确定性。需要量化每个模态的不确定性,并据此动态调整融合权重。
核心方法 :
UA-CMDet 提出不确定性感知模块(Uncertainty-Aware Module, UAM):
-
每个模态预测一个不确定性图(Uncertainty Map),表示每个位置该模态的可信度。
-
不确定性低(可信度高)的模态在融合中权重高。
-
不确定性高(可信度低)的模态在融合中权重低。
-
设计三个检测头:RGB头、红外头、融合头,分别监督,促进模态特定特征学习。
UA-CMDet 架构:
RGB图像 → RGB Backbone → RGB特征 ──┐
├→ UAM不确定性估计 → 加权融合 → 融合检测头
IR图像 → IR Backbone → IR特征 ──────┘
│ │
├→ RGB检测头 (辅助监督) └→ 融合检测头 (主监督)
└→ IR检测头 (辅助监督)UAM 不确定性估计:
对每个模态特征, 用一个小网络预测不确定性图 U ∈ [0, 1]
U=0 表示完全可信, U=1 表示完全不可信
融合权重: W_rgb = (1-U_rgb) / ((1-U_rgb) + (1-U_ir))
W_ir = (1-U_ir) / ((1-U_rgb) + (1-U_ir))
融合特征: F_fused = W_rgb * F_rgb + W_ir * F_ir
为什么有效:
- 不确定性图是像素级的,不同区域可以有不同的融合权重(比全局权重更精细)。
- 三个检测头的辅助监督促进模态特定特征的学习(RGB头学纹理,红外头学热特征)。
- 不确定性估计是可学习的,端到端训练。
实验结果(DroneVehicle):
- mAP@0.5:77.8%(三检测头+UAM)
- 相比简单融合(74.2%)提升 3.6 mAP
- 夜间场景提升最明显(+5.2)
5.3 条件感知动态融合(PCDF)
论文信息:
- 标题:Fusion Meets Diverse Conditions: A High-diversity Benchmark and Baseline for UAV-based Multimodal Object Detection with Condition Cues
- 作者:Chen Chen, et al.
- 会议:ICCV 2025
- 代码:https://github.com/chencccc/PCDF
核心问题 :
UA-CMDet 的不确定性是数据驱动的,但缺乏显式的场景条件信息(白天/夜晚、城市/乡村、晴/雨等)。不同条件下模态的可信度有明显的先验规律,可以用条件提示来引导融合。
核心方法 :
PCDF(Prompt-guided Condition-aware Dynamic Fusion):
-
条件提示编码:用 CLIP 的文本编码器将多标签条件(如"夜晚+城市+雨天")编码为条件向量。
-
样本特定条件提示学习:每个样本根据其图像特征动态调整条件提示(不是固定的文本,而是可学习的提示)。
-
动态融合权重:条件向量通过一个小网络生成每个模态的融合权重,实现样本级的动态融合。
PCDF 模块结构:
条件标签(白天/夜晚, 城市/乡村...) → CLIP文本编码器 → 条件向量
↓
RGB特征 + IR特征 → 条件感知融合网络 → 动态权重(W_rgb, W_ir) → 加权融合条件感知融合网络:
输入: concat(F_rgb, F_ir, 条件向量)
→ 卷积 → 全局池化 → FC → Sigmoid → W_rgb (W_ir = 1 - W_rgb)样本特定提示学习:
条件提示不是固定的, 而是根据图像特征动态调整
prompt = base_prompt + MLP(concat(F_rgb_avg, F_ir_avg))
这样即使条件标签相同, 不同样本也有不同的融合权重
为什么有效:
- 显式利用场景条件先验(夜晚红外更可信,白天RGB更可信)。
- CLIP的文本编码器提供强大的语义表示,条件编码更准确。
- 样本特定提示学习实现了细粒度的动态融合(比全局条件更精细)。
实验结果(DroneVehicle):
- mAP@0.5:79.7%(当前 DroneVehicle 上的 SOTA 之一)
- 相比 CALNet(77.0%)提升 2.7 mAP
- 在 diverse conditions(多种场景混合)下提升最明显
5.4 模态优势分层学习
除了 UA-CMDet 和 PCDF,还有一类方法通过分层利用模态优势来解决不平衡:
模态优势分层学习的核心思想:
不同层级的特征对不同模态的敏感度不同:
浅层特征(P2/P3): 细节/纹理 → RGB更有优势
深层特征(P4/P5): 语义/轮廓 → 红外更有优势
因此, 不同层级应该用不同的融合策略:
浅层: RGB主导, 红外辅助 (W_rgb > W_ir)
深层: 红外主导, RGB辅助 (W_ir > W_rgb)
代表方法:
- M2D-LIF: Mono-Modality Distillation + Local Illumination-aware Fusion
- 模态优势分层学习 (Learning Modality Advantage Hierarchically, IET 2026)
- IC-Fusion: Infrared-Centric Fusion (红外中心融合)
红外中心融合 (IC-Fusion) 的思路:
实验发现, 在FLIR等数据集中, 单模态IR检测器显著优于单模态RGB
→ 以红外特征为主干, RGB作为辅助补充
→ 红外Backbone权重不冻结, RGB Backbone可以更轻量
→ 融合时红外权重更高
优势: 参数量小(红外主干+轻量RGB分支), 性能好
六、经典论文深度分析
6.1 CFT(2021)------跨模态融合 Transformer 的开山之作
论文信息:
- 标题:Cross-Modality Fusion Transformer for RGB-Infrared Object Detection
- 作者:Qingyun Fang, et al.
- 年份:2021(arXiv:2104.06770)
- 基于:YOLOv5 + CSPDarkNet53
核心问题 :
RGB 和红外特征差异大,简单的逐元素相加或拼接无法有效融合。需要一种能建模模态间长距离依赖关系的融合机制。
核心方法 :
CFT(Cross-modality Fusion Transformer)将 Transformer 自注意力机制引入跨模态融合:
-
在双流 CSPDarkNet53 的每个 C2f 模块后嵌入 CFT 模块。
-
CFT 模块用自注意力建模 RGB 和红外特征之间的关系。
-
融合后的特征送入 SPPF,减少后续计算量。
CFT 模块结构:
RGB特征 F_rgb (B, C, H, W) ──┐
├→ Reshape为序列 → Multi-Head Self-Attention → 融合序列 → Reshape
IR特征 F_ir (B, C, H, W) ─────┘具体操作:
- 将F_rgb和F_ir在通道维度concat → (B, 2C, H, W)
- Reshape为 (B, 2C, HW) → 转置为 (B, HW, 2C) (序列形式)
- Multi-Head Self-Attention: 每个空间位置关注所有其他位置
- 输出 (B, HW, 2C) → Reshape为 (B, 2C, H, W)
- 1×1卷积降维为 (B, C, H, W) → 残差连接
为什么有效:
- 自注意力能建模模态间的长距离依赖(不只是局部邻域)。
- Transformer 的全局感受野有助于小目标检测(小目标需要全局上下文)。
- 在多个阶段融合,充分利用不同层级的特征。
实验结果(DroneVehicle):
- mAP@0.5:80.4%(CSPDarkNet53 骨干)
- 相比单模态 RGB(72.1%)提升 8.3 mAP
- 相比简单 concat 融合(76.5%)提升 3.9 mAP
局限性:
- 自注意力的计算复杂度是 O(HW²),高分辨率特征图上计算量大。
- Transformer 模块增加参数量。
- 只在 Backbone 中融合,Neck 中没有融合。
6.2 MFPT(IEEE TITS 2023)------多模态特征金字塔 Transformer
论文信息:
- 标题:Multi-Modal Feature Pyramid Transformer for RGB-Infrared Object Detection
- 作者:Yaohui Zhu, Xiaoyu Sun, et al.
- 期刊:IEEE Transactions on Intelligent Transportation Systems, 2023
- DOI:10.1109/TITS.2023.3266487
核心问题 :
CFT 只在 Backbone 中融合,没有利用特征金字塔的多尺度信息。不同尺度的目标需要不同层级的特征融合,需要在特征金字塔层面进行跨模态交互。
核心方法 :
MFPT(Multi-modal Feature Pyramid Transformer)包含两个组件:
-
模态内特征金字塔 Transformer(Intra-modality FPT):每个模态内部用 Transformer 建模多尺度特征之间的关系(P3↔P4↔P5)。
-
模态间特征金字塔 Transformer(Inter-modality FPT):RGB 和红外之间用 Transformer 建模跨模态、跨尺度的关系。
MFPT 架构:
RGB Backbone → P3_rgb, P4_rgb, P5_rgb ──┐
├→ Intra-FPT (模态内多尺度交互)
IR Backbone → P3_ir, P4_ir, P5_ir ──────┘
│
↓
Inter-FPT (模态间跨尺度交互)
│
↓
融合特征金字塔 → 检测头Intra-FPT:
对每个模态, 将P3/P4/P5的特征flatten后concat, 用自注意力建模尺度间关系
让浅层细节和深层语义充分交互Inter-FPT:
将RGB和IR的多尺度特征concat, 用交叉注意力建模模态间关系
每个尺度的RGB特征关注所有尺度的IR特征, 反之亦然
为什么有效:
- 模态内 FPT 促进多尺度特征交互(类似 FPN,但用 Transformer 更灵活)。
- 模态间 FPT 实现跨尺度的模态交互(P3的RGB可以关注P5的IR,反之亦然)。
- Transformer 的全局建模能力有利于小目标和密集目标。
实验结果:
- FLIR:mAP 70.1%(相比基线 66.3%,+3.8)
- DroneVehicle:mAP 78.3%(相比基线 74.5%,+3.8)
- 在小目标上提升最明显
局限性:
- 两个 FPT 模块计算量大。
- 多尺度特征的 concat 导致序列长度很长(P3+P4+P5 的空间位置数之和),自注意力计算复杂。
- 训练难度大。
6.3 C2Former(2023)------校准与互补 Transformer
论文信息:
- 标题:C2Former: Calibrated and Complementary Transformer for RGB-Infrared Object Detection
- 作者:Maoxun Yuan, et al.
- 年份:2023(arXiv:2306.16175)
- 代码:https://github.com/yuanmaoxun/C2Former
核心问题 :
多模态融合面临两个问题:
- 模态失准(Modality Miscalibration):RGB 和红外特征的分布差异大,直接融合效果差。
- 融合不精确(Fusion Imprecision):简单的注意力融合没有区分互补信息和冗余信息。
核心方法 :
C2Former(Calibrated and Complementary Transformer)包含两个模块:
-
模态间交叉注意力(Inter-modality Cross-Attention, ICA):用交叉注意力校准两个模态的特征,让 RGB 特征向红外特征对齐,反之亦然。
-
互补信息挖掘(Complementary Information Mining, CIM):在融合后挖掘两个模态的互补信息,抑制冗余信息。
C2Former 模块结构:
RGB特征 F_rgb ──┐
├→ ICA (交叉注意力校准) → 校准后的 F_rgb', F_ir'
IR特征 F_ir ────┘
│
↓
CIM (互补信息挖掘)
1. 计算互补特征: F_comp = |F_rgb' - F_ir'| (差异信息)
2. 计算共有特征: F_common = (F_rgb' + F_ir') / 2 (共有信息)
3. 门控融合: F_fused = gate_common * F_common + gate_comp * F_comp
│
↓
融合特征ICA 交叉注意力:
Q_rgb = F_rgb, K_ir = F_ir, V_ir = F_ir
F_rgb_calibrated = F_rgb + Attention(Q_rgb, K_ir, V_ir)
反之亦然, 得到 F_ir_calibrated
交叉注意力让每个模态的特征关注另一个模态的相关区域
为什么有效:
- ICA 的交叉注意力实现了特征级对齐(比 TSRA 的几何对齐更灵活)。
- CIM 区分互补信息和共有信息,让融合更精确。
- 门控机制动态调整互补/共有信息的权重。
实验结果:
- DroneVehicle:mAP 74.2%(ICCV 2025 benchmark 数据)
- LLVIP:mAP 97.3%
- FLIR:mAP 78.2%
- 在多个数据集上均优于 CFT 和 MFPT
6.4 CALNet(ACM MM 2023)------跨模态冲突感知学习
论文信息:
- 标题:Multispectral Object Detection via Cross-Modal Conflict-Aware Learning
- 作者:Xiao He, Chang Tang, Xin Zou, Wei Zhang
- 会议:ACM MM 2023(CCF A类)
- 代码:https://github.com/hexiao0275/CALNet-Dronevehicle
核心问题 :
现有方法主要用简单的累加操作融合不同模态的互补信息,忽略了模态间内在异质性产生的语义冲突。某些区域 RGB 和红外给出矛盾信息(如 RGB 显示是车辆但红外显示是背景),直接融合会导致特征混乱。
核心方法 :
CALNet(Conflict-Aware Learning Network)包含两个模块:
-
跨模态冲突矫正模块(Cross-Modal Conflict Correction):检测模态间的语义冲突,并用一个模态的信息矫正另一个模态的错误。
-
选择性跨模态融合模块(Selective Cross-Modal Fusion):根据冲突程度选择性地融合,冲突大的区域降低融合权重。
CALNet 模块结构:
RGB特征 F_rgb ──┐
├→ 冲突检测 → 冲突图 M_conflict (每个位置的冲突程度)
IR特征 F_ir ────┘
│
↓
冲突矫正模块
1. 计算模态间相似度: S = cosine_similarity(F_rgb, F_ir)
2. 冲突区域: S < 阈值 (相似度低 = 冲突大)
3. 矫正: 用高置信度模态的特征替换低置信度模态的特征
│
↓
选择性融合
W_fusion = 1 - M_conflict (冲突大的区域融合权重低)
F_fused = W_fusion * (F_rgb + F_ir) + (1-W_fusion) * F_dominant
(冲突大时只用主导模态, 冲突小时融合两个模态)
为什么有效:
- 显式检测和处理模态冲突,避免冲突区域的特征混乱。
- 选择性融合在冲突大时退化为单模态(鲁棒),冲突小时充分融合(精度高)。
- 冲突矫正模块用高置信度模态矫正低置信度模态,减少误检。
实验结果(DroneVehicle):
- mAP@0.5:77.0%(CSPDarkNet53 骨干,204.62M 参数)
- mAP@0.5:0.95:52.3%
- 相比 CFT(80.4%?注意不同论文的评测协议可能不同)
- 在冲突严重的场景(夜间、遮挡)提升明显
局限性:
- 参数量大(204M),推理速度慢(16.91 FPS)。
- 冲突检测的阈值需要调优。
- 冲突矫正可能引入错误矫正(高置信度模态也可能错)。
6.5 MDCFT-HSM(2026)------模态偏移感知小目标检测
论文信息:
- 标题:MDCFT-HSM: Modality-Shift-Aware RGB-T Small-Object Detection for Low-Altitude UAV Remote Sensing
- 期刊:MDPI Sensors, 2026
- 核心模块:MDCFT(Modality-Shift-Aware CFT)、HLFDE(High-Low Frequency Detail Enhancement)、SBGA、MGFR
核心问题 :
低空无人机遥感图像中,小目标占比高,且 RGB 和红外之间存在模态偏移(Modality Shift)------同一目标在两个模态中的外观差异大。现有融合方法在小目标上效果不佳,因为小目标特征弱,容易被模态偏移干扰。
核心方法:
- MDCFT(Modality-Shift-Aware CFT) :
- 冻结保护分支(frozen protected branch)+ 零初始化辅助残差注入。
- 在 stem、P3、P4、P5 四个阶段注入模态偏移感知的融合。
- 保护一个模态的特征不被另一个模态的偏移污染。
- HLFDE(High-Low Frequency Detail Enhancement) :
- 保留浅层的高频和低频证据,增强小目标的细节。
- SBGA(Selective Bidirectional Gated Attention) :
- Neck 中的门控跨层级细节传递。
- MGFR(Modality-Gated Feature Refinement) :
- 检测头前的模态门控特征精炼。
实验结果:
- 在低空无人机 RGB-T 小目标检测数据集上提升显著。
- 小目标 AP 提升 4-6 个点。
- 模态偏移场景下鲁棒性提升。
6.6 DyFCLT(CVPR 2026)------动态频率解耦跨模态学习
论文信息:
- 标题:DyFCLT: Dynamic Frequency-Decoupled Cross-Modal Learning Transformer for Multimodal Tiny Object Detection
- 会议:CVPR 2026
- 核心模块:DFCA(Dynamic Frequency-Band Decoupled Cross-Modal Attention)
核心问题 :
通过频率特性分析发现,多模态小目标中,随着目标尺寸减小,RGB 和红外两个模态都包含更丰富的中高频分量。现有融合方法没有利用频率域的特性,对小目标的中高频信息利用不足。
核心方法 :
DyFCLT(Dynamic Frequency-Decoupled Cross-Modal Learning Transformer):
- 动态频带解耦:将特征分解为低频、中频、高频三个分量。
- DFCA(Dynamic Frequency-Band Decoupled Cross-Modal Attention) :
- 不同频带用不同的跨模态注意力策略。
- 低频(语义):全局注意力。
- 中高频(细节/边缘):局部注意力 + 跨模态交互。
- 动态频带权重:根据目标尺寸动态调整各频带的权重(小目标侧重中高频)。
为什么有效:
- 频率解耦让不同频率的特征得到针对性处理。
- 小目标的中高频信息得到增强(边缘、细节更清晰)。
- 动态频带权重适应不同尺寸的目标。
实验结果:
- 在多模态微小目标检测数据集上达到 SOTA。
- 微小目标(<16×16像素)AP 提升 5-7 个点。
- 证明了频率域分析在多模态小目标检测中的价值。
6.7 论文汇总表
| 论文 | 年份 | 会议/期刊 | 核心创新 | 融合层级 | 对齐方式 | 模态不平衡 | DroneVehicle mAP | 参数量 |
|---|---|---|---|---|---|---|---|---|
| CFT | 2021 | arXiv | 跨模态融合Transformer | 特征级(Backbone) | 无 | 无 | 80.4% | ~150M |
| TSRA | 2022 | ECCV | 平移尺度旋转对齐 | 特征级 | 几何对齐(TSRA) | 模态选择 | 78.5% | ~80M |
| UA-CMDet | 2020 | arXiv | 不确定性感知+三检测头 | 特征级+决策级 | 无 | 不确定性图 | 77.8% | ~100M |
| MFPT | 2023 | IEEE TITS | 多模态特征金字塔Transformer | 特征级(Neck) | 无 | 无 | 78.3% | ~120M |
| C2Former | 2023 | arXiv | 校准+互补Transformer | 特征级 | 交叉注意力(ICA) | 互补挖掘(CIM) | 74.2%* | 91M |
| CALNet | 2023 | ACM MM | 冲突感知学习 | 特征级 | 冲突矫正 | 选择性融合 | 77.0% | 204M |
| PCDF | 2025 | ICCV | 条件感知动态融合+CLIP提示 | 特征级 | 无 | 条件动态权重 | 79.7% | ~100M |
| MDCFT-HSM | 2026 | MDPI | 模态偏移感知+频率细节增强 | 特征级 | 冻结保护分支 | 模态门控 | - | ~80M |
| DyFCLT | 2026 | CVPR | 动态频率解耦跨模态学习 | 特征级 | 频带解耦注意力 | 动态频带权重 | - | ~120M |
| IGIANet | 2023 | - | 隐式对齐驱动动态融合 | 特征级 | 隐式偏移估计 | 动态融合核 | 80.9% | ~90M |
*注:C2Former 的 74.2% 是 ICCV 2025 benchmark 中的数据,不同论文的评测协议(训练集划分、输入尺寸、增强策略)可能不同,数值仅供参考。
七、YOLO 双模态融合完整代码实现
7.1 双流 Backbone 架构
python
"""
双流YOLO双模态融合检测网络
基于YOLOv5/YOLOv8架构, RGB和红外各一个Backbone, 特征级融合
"""
import torch
import torch.nn as nn
import torch.nn.functional as F
class Conv(nn.Module):
"""标准卷积块: Conv + BN + SiLU"""
def __init__(self, c1, c2, k=1, s=1, p=None, g=1):
super().__init__()
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
self.bn = nn.BatchNorm2d(c2)
self.act = nn.SiLU()
def forward(self, x):
return self.act(self.bn(self.conv(x)))
def autopad(k, p=None):
if p is None:
p = k // 2 if isinstance(k, int) else [x // 2 for x in k]
return p
class C2f(nn.Module):
"""C2f模块 (YOLOv8)"""
def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
super().__init__()
self.c = int(c2 * e)
self.cv1 = Conv(c1, 2 * self.c, 1, 1)
self.cv2 = Conv((2 + n) * self.c, c2, 1)
self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))
def forward(self, x):
y = list(self.cv1(x).chunk(2, 1))
y.extend(m(y[-1]) for m in self.m)
return self.cv2(torch.cat(y, 1))
class Bottleneck(nn.Module):
def __init__(self, c1, c2, shortcut=True, g=1, k=((3, 3), (3, 3)), e=0.5):
super().__init__()
c_ = int(c2 * e)
self.cv1 = Conv(c1, c_, k[0], 1)
self.cv2 = Conv(c_, c2, k[1], 1, g=g)
self.add = shortcut and c1 == c2
def forward(self, x):
return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))
class SPPF(nn.Module):
"""SPPF模块"""
def __init__(self, c1, c2, k=5):
super().__init__()
c_ = c1 // 2
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c_ * 4, c2, 1, 1)
self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)
def forward(self, x):
x = self.cv1(x)
y1 = self.m(x)
y2 = self.m(y1)
y3 = self.m(y2)
return self.cv2(torch.cat([x, y1, y2, y3], 1))
class DualStreamBackbone(nn.Module):
"""
双流Backbone: RGB和红外各一个CSPDarknet
共享前两层(底层特征相似), 高层各自独立(模态特定特征)
"""
def __init__(self):
super().__init__()
# === 共享层 (stem + 第一层) ===
self.stem = Conv(3, 64, 3, 2) # RGB用3通道
self.stem_ir = Conv(1, 64, 3, 2) # 红外用1通道
self.stage1 = nn.Sequential(
Conv(64, 128, 3, 2),
C2f(128, 128, n=3),
)
# === RGB特定层 ===
self.rgb_stage2 = nn.Sequential(Conv(128, 256, 3, 2), C2f(256, 256, n=6))
self.rgb_stage3 = nn.Sequential(Conv(256, 512, 3, 2), C2f(512, 512, n=6))
self.rgb_stage4 = nn.Sequential(Conv(512, 1024, 3, 2), C2f(1024, 1024, n=3), SPPF(1024, 1024))
# === 红外特定层 ===
self.ir_stage2 = nn.Sequential(Conv(128, 256, 3, 2), C2f(256, 256, n=6))
self.ir_stage3 = nn.Sequential(Conv(256, 512, 3, 2), C2f(512, 512, n=6))
self.ir_stage4 = nn.Sequential(Conv(512, 1024, 3, 2), C2f(1024, 1024, n=3), SPPF(1024, 1024))
def forward(self, rgb, ir):
"""
Args:
rgb: (B, 3, H, W) RGB图像
ir: (B, 1, H, W) 红外图像
Returns:
rgb_feats: [P3_rgb, P4_rgb, P5_rgb]
ir_feats: [P3_ir, P4_ir, P5_ir]
"""
# 共享底层
rgb_x = self.stage1(self.stem(rgb))
ir_x = self.stage1(self.stem_ir(ir))
# RGB高层
rgb_p3 = self.rgb_stage2(rgb_x) # /8
rgb_p4 = self.rgb_stage3(rgb_p3) # /16
rgb_p5 = self.rgb_stage4(rgb_p4) # /32
# 红外高层
ir_p3 = self.ir_stage2(ir_x)
ir_p4 = self.ir_stage3(ir_p3)
ir_p5 = self.ir_stage4(ir_p4)
return [rgb_p3, rgb_p4, rgb_p5], [ir_p3, ir_p4, ir_p5]
7.2 跨模态注意力融合模块
python
"""
跨模态注意力融合模块
包含: 简单融合、门控融合、跨模态注意力融合三种方式
"""
class SimpleFusion(nn.Module):
"""简单融合: concat + 1x1卷积"""
def __init__(self, channels=256):
super().__init__()
self.fuse = Conv(channels * 2, channels, 1)
def forward(self, f_rgb, f_ir):
return self.fuse(torch.cat([f_rgb, f_ir], dim=1))
class GatedFusion(nn.Module):
"""门控融合: 学习每个模态的权重"""
def __init__(self, channels=256):
super().__init__()
self.gate = nn.Sequential(
Conv(channels * 2, channels // 4, 1),
nn.ReLU(),
Conv(channels // 4, 2, 1), # 2个模态的权重
nn.Softmax(dim=1),
)
def forward(self, f_rgb, f_ir):
concat = torch.cat([f_rgb, f_ir], dim=1)
weights = self.gate(concat) # (B, 2, H, W)
w_rgb = weights[:, 0:1]
w_ir = weights[:, 1:2]
return w_rgb * f_rgb + w_ir * f_ir
class CrossModalAttentionFusion(nn.Module):
"""
跨模态注意力融合 (CFT风格, 轻量化版本)
用交叉注意力建模模态间关系
"""
def __init__(self, channels=256, num_heads=8, reduction=4):
super().__init__()
self.num_heads = num_heads
self.head_dim = channels // num_heads
self.scale = self.head_dim ** -0.5
# QKV投影 (轻量化, 用reduction降维)
mid_channels = channels // reduction
self.q_rgb = Conv(channels, mid_channels, 1)
self.k_ir = Conv(channels, mid_channels, 1)
self.v_ir = Conv(channels, mid_channels, 1)
self.q_ir = Conv(channels, mid_channels, 1)
self.k_rgb = Conv(channels, mid_channels, 1)
self.v_rgb = Conv(channels, mid_channels, 1)
# 输出投影
self.out_proj = Conv(mid_channels * 2, channels, 1)
self.norm = nn.BatchNorm2d(channels)
def forward(self, f_rgb, f_ir):
B, C, H, W = f_rgb.shape
N = H * W
# RGB关注IR
q_rgb = self.q_rgb(f_rgb).view(B, self.num_heads, self.head_dim // 2, N).transpose(-1, -2)
k_ir = self.k_ir(f_ir).view(B, self.num_heads, self.head_dim // 2, N)
v_ir = self.v_ir(f_ir).view(B, self.num_heads, self.head_dim // 2, N).transpose(-1, -2)
attn_rgb2ir = (q_rgb @ k_ir) * self.scale
attn_rgb2ir = attn_rgb2ir.softmax(dim=-1)
f_rgb_attn = (attn_rgb2ir @ v_ir).transpose(-1, -2).contiguous().view(B, -1, H, W)
# IR关注RGB
q_ir = self.q_ir(f_ir).view(B, self.num_heads, self.head_dim // 2, N).transpose(-1, -2)
k_rgb = self.k_rgb(f_rgb).view(B, self.num_heads, self.head_dim // 2, N)
v_rgb = self.v_rgb(f_rgb).view(B, self.num_heads, self.head_dim // 2, N).transpose(-1, -2)
attn_ir2rgb = (q_ir @ k_rgb) * self.scale
attn_ir2rgb = attn_ir2rgb.softmax(dim=-1)
f_ir_attn = (attn_ir2rgb @ v_rgb).transpose(-1, -2).contiguous().view(B, -1, H, W)
# 融合
fused = self.out_proj(torch.cat([f_rgb_attn, f_ir_attn], dim=1))
# 残差连接
output = self.norm(fused + f_rgb + f_ir)
return output
class MultiScaleFusionNeck(nn.Module):
"""
多尺度融合Neck: PAN-FPN + 跨模态融合
在P3/P4/P5三个尺度分别融合RGB和IR特征
"""
def __init__(self, channels_list=[256, 512, 1024], fusion_type='attention'):
super().__init__()
# 融合模块
if fusion_type == 'simple':
self.fuse_modules = nn.ModuleList([SimpleFusion(c) for c in channels_list])
elif fusion_type == 'gated':
self.fuse_modules = nn.ModuleList([GatedFusion(c) for c in channels_list])
elif fusion_type == 'attention':
self.fuse_modules = nn.ModuleList([CrossModalAttentionFusion(c) for c in channels_list])
# 统一通道数 (为了FPN)
self.reduce = nn.ModuleList([Conv(c, 256, 1) for c in channels_list])
# FPN (自上而下)
self.upsample = nn.Upsample(scale_factor=2, mode='nearest')
self.fpn_c2f_p4 = C2f(512, 256, n=3)
self.fpn_c2f_p3 = C2f(512, 256, n=3)
# PAN (自下而上)
self.pan_conv_p3 = Conv(256, 256, 3, 2)
self.pan_c2f_p4 = C2f(512, 512, n=3)
self.pan_conv_p4 = Conv(512, 512, 3, 2)
self.pan_c2f_p5 = C2f(1024, 1024, n=3)
def forward(self, rgb_feats, ir_feats):
"""
rgb_feats: [P3_rgb, P4_rgb, P5_rgb]
ir_feats: [P3_ir, P4_ir, P5_ir]
"""
# 跨模态融合
fused = [fuse(r, i) for fuse, r, i in zip(self.fuse_modules, rgb_feats, ir_feats)]
p3, p4, p5 = fused
# 统一通道
p3 = self.reduce[0](p3)
p4 = self.reduce[1](p4)
p5 = self.reduce[2](p5)
# FPN 自上而下
p4_fpn = self.fpn_c2f_p4(torch.cat([p4, self.upsample(p5)], dim=1))
p3_fpn = self.fpn_c2f_p3(torch.cat([p3, self.upsample(p4_fpn)], dim=1))
# PAN 自下而上
p4_pan = self.pan_c2f_p4(torch.cat([p4_fpn, self.pan_conv_p3(p3_fpn)], dim=1))
p5_pan = self.pan_c2f_p5(torch.cat([p5, self.pan_conv_p4(p4_pan)], dim=1))
return [p3_fpn, p4_pan, p5_pan]
7.3 双模态数据集加载器
python
"""
双模态数据集加载器
同时加载RGB和红外图像, 共享标签
"""
import os
import cv2
import numpy as np
import torch
from torch.utils.data import Dataset
from pathlib import Path
class DualModalDataset(Dataset):
"""
双模态检测数据集
目录结构:
dataset/
├── images/
│ ├── rgb/ (RGB图像, .jpg)
│ └── ir/ (红外图像, .jpg)
└── labels/ (YOLO格式标签, .txt)
"""
def __init__(self, rgb_dir, ir_dir, label_dir, img_size=640,
augment=True, hyp=None):
self.rgb_dir = Path(rgb_dir)
self.ir_dir = Path(ir_dir)
self.label_dir = Path(label_dir)
self.img_size = img_size
self.augment = augment
self.hyp = hyp or {}
# 获取所有图像文件名
self.rgb_files = sorted(list(self.rgb_dir.glob('*.jpg')) +
list(self.rgb_dir.glob('*.png')))
assert len(self.rgb_files) > 0, f"No images found in {rgb_dir}"
def __len__(self):
return len(self.rgb_files)
def __getitem__(self, idx):
rgb_path = self.rgb_files[idx]
stem = rgb_path.stem
# 加载RGB图像
rgb_img = cv2.imread(str(rgb_path))
rgb_img = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2RGB)
# 加载红外图像
ir_path = self.ir_dir / (stem + rgb_path.suffix)
if not ir_path.exists():
ir_path = self.ir_dir / (stem + '.jpg')
ir_img = cv2.imread(str(ir_path), cv2.IMREAD_GRAYSCALE)
if ir_img is None:
ir_img = np.zeros_like(rgb_img[:, :, 0])
# 加载标签
label_path = self.label_dir / (stem + '.txt')
labels = []
if label_path.exists():
with open(label_path, 'r') as f:
for line in f:
parts = line.strip().split()
if len(parts) >= 5:
labels.append([float(x) for x in parts])
labels = np.array(labels) if labels else np.zeros((0, 5))
# 数据增强 (RGB和IR同步增强)
if self.augment:
rgb_img, ir_img, labels = self._augment(rgb_img, ir_img, labels)
# Letterbox (保持宽高比的resize)
rgb_img, ratio, pad = self._letterbox(rgb_img, self.img_size)
ir_img, _, _ = self._letterbox(ir_img, self.img_size)
# 标签变换
if len(labels):
labels[:, 1:] = self._xywhn2xyxy(labels[:, 1:], ratio, pad, self.img_size)
# 归一化
rgb_img = rgb_img.transpose(2, 0, 1) / 255.0 # (3, H, W)
ir_img = ir_img[np.newaxis, :, :] / 255.0 # (1, H, W)
return {
'rgb': torch.from_numpy(rgb_img).float(),
'ir': torch.from_numpy(ir_img).float(),
'labels': torch.from_numpy(labels).float(),
'img_path': str(rgb_path),
}
def _letterbox(self, img, img_size, color=(114, 114, 114)):
"""Letterbox resize"""
h, w = img.shape[:2]
scale = min(img_size / h, img_size / w)
new_h, new_w = int(h * scale), int(w * scale)
img_resized = cv2.resize(img, (new_w, new_h))
pad_h = (img_size - new_h) // 2
pad_w = (img_size - new_w) // 2
if len(img.shape) == 3:
img_padded = np.full((img_size, img_size, 3), color, dtype=np.uint8)
else:
img_padded = np.full((img_size, img_size), 114, dtype=np.uint8)
img_padded[pad_h:pad_h + new_h, pad_w:pad_w + new_w] = img_resized
return img_padded, scale, (pad_w, pad_h)
def _xywhn2xyxy(self, xywhn, ratio, pad, img_size):
"""归一化xywh转像素xyxy"""
xyxy = np.zeros_like(xywhn)
xyxy[:, 0] = (xywhn[:, 0] - xywhn[:, 2] / 2) * img_size * ratio + pad[0]
xyxy[:, 1] = (xywhn[:, 1] - xywhn[:, 3] / 2) * img_size * ratio + pad[1]
xyxy[:, 2] = (xywhn[:, 0] + xywhn[:, 2] / 2) * img_size * ratio + pad[0]
xyxy[:, 3] = (xywhn[:, 1] + xywhn[:, 3] / 2) * img_size * ratio + pad[1]
return xyxy
def _augment(self, rgb_img, ir_img, labels):
"""同步数据增强 (HSV只对RGB, 几何变换对两者同步)"""
h, w = rgb_img.shape[:2]
# 随机水平翻转 (同步)
if np.random.random() < 0.5:
rgb_img = np.fliplr(rgb_img).copy()
ir_img = np.fliplr(ir_img).copy()
if len(labels):
labels[:, 1] = 1 - labels[:, 1]
# HSV增强 (只对RGB)
if self.hyp.get('hsv_gain', 0):
gain = self.hyp['hsv_gain']
r = np.random.uniform(-1, 1, 3) * gain + 1
hue, sat, val = cv2.split(cv2.cvtColor(rgb_img, cv2.COLOR_RGB2HSV))
dtype = rgb_img.dtype
x = np.arange(0, 256, dtype=r.dtype)
lut_hue = ((x * r[0]) % 180).astype(dtype)
lut_sat = np.clip(x * r[1], 0, 255).astype(dtype)
lut_val = np.clip(x * r[2], 0, 255).astype(dtype)
im_hsv = cv2.merge((cv2.LUT(hue, lut_hue), cv2.LUT(sat, lut_sat), cv2.LUT(val, lut_val)))
rgb_img = cv2.cvtColor(im_hsv, cv2.COLOR_HSV2RGB)
return rgb_img, ir_img, labels
def collate_fn(batch):
"""自定义collate函数 (处理不同数量的标签)"""
rgb = torch.stack([item['rgb'] for item in batch])
ir = torch.stack([item['ir'] for item in batch])
labels = []
for i, item in enumerate(batch):
if len(item['labels']):
label = item['labels'].clone()
label = torch.cat([torch.full((len(label), 1), i), label], dim=1)
labels.append(label)
labels = torch.cat(labels, dim=0) if labels else torch.zeros((0, 6))
return {
'rgb': rgb,
'ir': ir,
'labels': labels,
'img_paths': [item['img_path'] for item in batch],
}
7.4 完整训练配置
yaml
# hyp.dual_modal.yaml --- 双模态融合检测超参数
lr0: 0.008
lrf: 0.01
momentum: 0.937
weight_decay: 0.0005
warmup_epochs: 5.0
warmup_momentum: 0.8
warmup_bias_lr: 0.1
# Loss权重
box: 0.05
cls: 0.5
cls_pw: 1.0
obj: 1.0
obj_pw: 1.0
iou_t: 0.20
anchor_t: 4.0
# Focal Loss (小目标/难例)
fl_gamma: 2.0
fl_alpha: 0.25
# 数据增强
hsv_h: 0.015
hsv_s: 0.7
hsv_v: 0.4
degrees: 0.0
translate: 0.1
scale: 0.5
shear: 0.0
perspective: 0.0
flipud: 0.0
fliplr: 0.5
mosaic: 1.0
mixup: 0.15
copy_paste: 0.0
# 双模态特定
fusion_type: attention # simple / gated / attention
share_stem: true # 共享底层stem
align_module: tsra # none / tsra
modality_balance: uncertainty # none / uncertainty / conditional
close_mosaic: 15
# 训练
img_size: 640
batch_size: 16
epochs: 300
patience: 50
python
"""
双模态融合检测训练脚本 (简化版)
"""
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
class DualModalDetector(nn.Module):
"""完整的双模态检测器"""
def __init__(self, num_classes=5, fusion_type='attention'):
super().__init__()
self.backbone = DualStreamBackbone()
self.neck = MultiScaleFusionNeck(fusion_type=fusion_type)
# 检测头 (YOLOv8风格)
self.head = nn.ModuleList([
nn.Conv2d(256, 4 * 16 + 1 + num_classes, 1) for _ in range(3)
])
def forward(self, rgb, ir):
rgb_feats, ir_feats = self.backbone(rgb, ir)
fused_feats = self.neck(rgb_feats, ir_feats)
outputs = [head(f) for head, f in zip(self.head, fused_feats)]
return outputs
def train_one_epoch(model, dataloader, optimizer, compute_loss, device, epoch):
model.train()
total_loss = 0
for batch_idx, batch in enumerate(dataloader):
rgb = batch['rgb'].to(device)
ir = batch['ir'].to(device)
labels = batch['labels'].to(device)
# 前向传播
preds = model(rgb, ir)
# 计算损失
loss, loss_items = compute_loss(preds, labels)
# 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
if batch_idx % 50 == 0:
print(f"Epoch {epoch}, Batch {batch_idx}, Loss: {loss.item():.4f}")
return total_loss / len(dataloader)
# 训练主函数
def main():
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 数据集
train_dataset = DualModalDataset(
rgb_dir='data/DroneVehicle/train/rgb',
ir_dir='data/DroneVehicle/train/ir',
label_dir='data/DroneVehicle/train/labels',
img_size=640,
augment=True,
)
train_loader = DataLoader(
train_dataset, batch_size=16, shuffle=True,
num_workers=8, collate_fn=collate_fn,
)
# 模型
model = DualModalDetector(num_classes=5, fusion_type='attention').to(device)
# 优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.008, momentum=0.937, weight_decay=0.0005)
# 损失函数 (使用YOLOv8的ComputeLoss, 需要适配双模态输出)
# compute_loss = ComputeLoss(model)
# 训练循环
for epoch in range(300):
avg_loss = train_one_epoch(model, train_loader, optimizer, None, device, epoch)
print(f"Epoch {epoch} Average Loss: {avg_loss:.4f}")
# 保存检查点
if (epoch + 1) % 10 == 0:
torch.save(model.state_dict(), f'checkpoints/epoch_{epoch}.pt')
if __name__ == '__main__':
main()
八、实验设计与涨点路线
8.1 消融实验设计模板
以"双流YOLO + 跨模态注意力融合 + TSRA对齐 + 不确定性平衡"为例:
融合策略消融 (DroneVehicle, YOLOv8s):
┌──────┬──────────┬────────┬──────────┬─────────┬────────┐
│ Exp │ 单模态RGB│ 单模态IR│ 简单concat│ 门控融合 │ 注意力融合│ mAP │
├──────┼──────────┼────────┼──────────┼─────────┼────────┼───────┤
│ 1 │ ✓ │ │ │ │ │ 72.1 │
│ 2 │ │ ✓ │ │ │ │ 74.5 │
│ 3 │ ✓ │ ✓ │ ✓ │ │ │ 76.3 │
│ 4 │ ✓ │ ✓ │ │ ✓ │ │ 77.5 │
│ 5 │ ✓ │ ✓ │ │ │ ✓ │ 78.8 │
└──────┴──────────┴────────┴──────────┴─────────┴────────┴───────┘
对齐模块消融:
┌──────┬──────┬────────┬────────┬────────┐
│ Exp │ 无对齐│ 平移对齐│ TSRA │ DCN对齐│ mAP │
├──────┼──────┼────────┼────────┼────────┼────────┤
│ 1 │ ✓ │ │ │ │ 78.8 │
│ 2 │ │ ✓ │ │ │ 79.5 │
│ 3 │ │ │ ✓ │ │ 80.2 │
│ 4 │ │ │ │ ✓ │ 80.5 │
└──────┴──────┴────────┴────────┴────────┴────────┘
模态不平衡消融:
┌──────┬──────┬──────────┬──────────┬────────┬────────┐
│ Exp │ 等权 │ 不确定性 │ 条件感知 │ 夜间mAP│ 白天mAP│
├──────┼──────┼──────────┼──────────┼────────┼────────┤
│ 1 │ ✓ │ │ │ 72.3 │ 82.1 │
│ 2 │ │ ✓ │ │ 76.8 │ 82.5 │
│ 3 │ │ │ ✓ │ 78.2 │ 83.1 │
└──────┴──────┴──────────┴──────────┴────────┴────────┘
白天vs夜间性能对比:
┌──────────┬────────┬────────┬────────┐
│ 方法 │ 白天mAP│ 夜间mAP│ 平均mAP│
├──────────┼────────┼────────┼────────┤
│ 单模态RGB│ 82.1 │ 55.3 │ 68.7 │
│ 单模态IR │ 76.8 │ 82.5 │ 79.7 │
│ 简单融合 │ 81.5 │ 72.3 │ 76.9 │
│ 注意力融合│ 82.8 │ 76.8 │ 79.8 │
│ +不确定性 │ 83.1 │ 78.2 │ 80.7 │
└──────────┴────────┴────────┴────────┘
8.2 涨点路线图
阶段1: 基线搭建 (mAP ~72-75%)
├── 单模态RGB基线 (~72%)
├── 单模态IR基线 (~75%)
├── 6通道输入简单融合 (~76%)
└── 数据集准备 (DroneVehicle/FLIR/LLVIP)
阶段2: 双流架构+特征融合 (mAP ~78%, +3%)
├── 双流Backbone (RGB+IR各一个)
├── 共享底层stem (减少参数量)
├── 特征级融合 (concat+1x1卷积 → 门控融合 → 跨模态注意力)
└── 多尺度融合 (P3/P4/P5都融合)
阶段3: 跨模态对齐 (mAP ~80%, +2%)
├── TSRA对齐 (平移+尺度+旋转)
├── 或可变形卷积对齐 (局部对齐)
├── 对齐放在融合之前
└── 模态选择策略 (对齐不可靠时退化为单模态)
阶段4: 模态不平衡处理 (mAP ~81%, +1%)
├── 不确定性感知融合 (UA-CMDet风格)
├── 或条件感知动态融合 (PCDF风格)
├── 三检测头设计 (RGB头+IR头+融合头)
└── 模态优势分层 (浅层RGB主导, 深层IR主导)
阶段5: 小目标增强 (mAP ~82%, +1%)
├── P2检测头 (小目标)
├── Copy-Paste (增加小目标)
├── 高输入分辨率 (960-1280)
├── 频率域增强 (DyFCLT风格, 中高频增强)
└── Focal Loss (难例聚焦)
阶段6: 推理优化 (保持mAP, 提升速度)
├── 模态蒸馏 (大模型教小模型)
├── 共享Backbone (参数共享)
├── 轻量化融合模块 (深度可分离卷积)
├── TensorRT部署
└── 单模态推理模式 (节能模式, 只跑IR)
8.3 超参数推荐
| 超参数 | 默认值 | 双模态推荐 | 原因 |
|---|---|---|---|
| 融合类型 | concat | attention | 跨模态注意力性能最好 |
| 共享层 | 无 | stem+stage1 | 底层特征模态差异小, 共享减少参数 |
| 对齐模块 | 无 | TSRA | 解决跨模态弱错位 |
| 模态平衡 | 等权 | uncertainty | 动态调整模态权重 |
| 输入尺寸 | 640 | 640-960 | 双模态计算量大, 640起步 |
| batch_size | 16 | 8-16 | 双Backbone显存占用大 |
| 学习率 | 0.01 | 0.008 | 双模态训练不稳定, 略低学习率 |
| warmup | 3.0 | 5.0 | 双模态需要更长warmup |
| 训练轮数 | 300 | 300-400 | 双模态收敛慢 |
| Focal Loss | 关闭 | 开启(γ=2) | 小目标+难例多 |
| HSV增强 | 标准 | RGB-only | 红外是灰度图, 不做HSV |
| 红外归一化 | /255 | 直方图均衡+/255 | 红外对比度低, 均衡增强 |
| 三检测头 | 无 | 可选 | 促进模态特定特征学习 |
| close_mosaic | 15 | 20 | 双模态需要更长真实数据微调 |
九、总结与下篇预告
9.1 本文核心要点回顾
-
为什么需要RGB-红外融合:RGB提供颜色纹理(白天好),红外提供热对比度(夜间/恶劣天气好),两者互补实现全天候检测。
-
三种融合层级:
- 像素级:简单但性能上限低,适合快速验证。
- 特征级:当前SOTA主流,性能最好,创新点多。
- 决策级:鲁棒性最好但性能上限低,适合工程部署。
-
六大核心挑战:模态异质性、跨模态错位、模态不平衡、模态冲突、计算效率、数据对齐。
-
跨模态对齐(TSRA):ECCV 2022提出,同时对齐平移、尺度、旋转,比只对齐平移更全面。用可微的空间变换网络实现端到端训练。
-
模态不平衡解决方案:
- UA-CMDet:不确定性图,像素级动态权重。
- PCDF(ICCV 2025):CLIP条件提示,样本级动态融合。
- 模态优势分层:浅层RGB主导,深层IR主导。
-
经典论文:
- CFT(2021):跨模态融合Transformer开山之作,DroneVehicle 80.4%。
- MFPT(IEEE TITS 2023):多模态特征金字塔Transformer。
- C2Former(2023):校准+互补Transformer。
- CALNet(ACM MM 2023):冲突感知学习,处理模态冲突。
- PCDF(ICCV 2025):条件感知动态融合,当前SOTA 79.7%。
- MDCFT-HSM(2026)、DyFCLT(CVPR 2026):最新小目标+频率域方向。
-
YOLO双模态融合完整代码:双流Backbone(共享底层)、三种融合模块(简单/门控/注意力)、TSRA对齐模块、双模态数据集加载器、训练配置。
-
涨点路线:基线(72-75%) → 双流+特征融合(78%) → 跨模态对齐(80%) → 模态不平衡(81%) → 小目标增强(82%) → 推理优化。
9.2 下篇预告
本系列第十篇将聚焦于多模态融合检测的进阶方向:
- 三模态融合(RGB+红外+事件相机/深度/激光雷达)
- 多模态知识蒸馏(大模态模型教小模态模型)
- 无对齐多模态检测(不需要配准的端到端学习)
- 多模态目标跟踪(融合检测+跟踪)
- 多模态异常检测与OOD泛化
- 最新论文分析与代码实现
如果本文对你有帮助,欢迎点赞、收藏、关注! 有任何问题欢迎在评论区交流。
系列回顾:
- 第一篇:《YOLO 全代码详细解读:从预处理到后处理的完整数据流动》
- 第二篇:《YOLO 涨点研究(二):Loss 函数深度解析与正负样本分配策略》
- 第三篇:《YOLO 涨点研究(三):数据增强策略深度解析与涨点技巧》
- 第四篇:《YOLO 涨点研究(四):网络结构改进与涨点技巧》
- 第五篇:《YOLO 涨点研究(五):模块优化的实验设计与代码落实全指南》
- 第六篇:《YOLO 涨点研究(六):网络结构改进之小目标增强篇1------无人机视角下的车辆与行人检测》
- 第七篇:《YOLO 涨点研究(七):网络结构改进之小目标增强篇2------损失函数与训练策略》
- 第八篇:《YOLO 涨点研究(八):定向目标检测篇------旋转框检测的网络结构、损失函数与论文全解析》
- 第九篇:《YOLO 涨点研究(九):多模态融合检测篇------RGB-红外融合的网络结构与论文全解析》(本文)
下一篇:《YOLO 涨点研究(十):多模态融合检测进阶篇------三模态融合、知识蒸馏与无对齐学习》