🔥 痛点:RGB-T检测器要吃双模态,重型双骨干+全图融合FLOPs飙到上千G,轻量化一直是难题
🎯 方案:SFEDet(哈尔滨工业大学深圳)提出稀疏融合机制——先快速扫描过滤背景,再对稀疏RoI做融合检查精炼
📌 核心:差分增强分组融合(DEGF)+ 滚动卷积 + 去噪训练策略,24.5M参数、69G FLOPs
✅ 结果:M3FD mAP 61.0%、FLIR mAP 43.0%、LLVIP mAP 65.9%,参数量仅为Fu-Mamba的8.5%
前言
RGB-T目标检测通过融合可见光(RGB)和热红外(TIR)两种模态,能够在夜间、雾霾等恶劣光照条件下实现鲁棒检测。近年来,该领域涌现了大量优秀工作:
针对上述问题,哈工大深圳的Chao Tian等人提出SFEDet(Sparse Fusion Efficient Detector),首次在RGB-T检测中实现稀疏融合机制:先用两个轻量级RPN快速扫描图像识别候选区域,再对稀疏的RoI做融合驱动检查与精炼。24.5M参数、69G FLOPs,在三大基准上全面超越288M参数的Fu-Mamba。
一、整体架构
1.1 设计动机
SFEDet的核心洞察来自一个简单事实:大多数图像区域是平滑背景。

核心流程:
- Stage 1(快速扫描):两个独立的轻量级RPN(YOLOv8-Small,各8.4M参数)分别处理RGB和TIR图像,快速识别潜在前景区域(RoI)。通过取两个模态RoI的并集,避免遗漏真实目标
- Stage 2(稀疏融合):仅在候选RoI区域内进行昂贵的跨模态融合。FER模块通过差分增强分组融合、辅助特征增强、滚动卷积等技术,对每个RoI进行精细检查和逐步精炼
这种设计使得计算成本主要取决于目标数量而非图像分辨率,天然适合高分辨率场景。
1.2 模块参数分布
| RPN-RGB | 8.4M | YOLOv8-Small |
| RPN-TIR | 8.4M | YOLOv8-Small |
| DEGF | 0.95M | 差分增强分组融合 |
| 辅助增强-1 | 1.11M | 第一阶段辅助特征 |
| FER-Head-1 | 2.27M | 第一阶段检测头 |
| 辅助增强-2 | 1.11M | 第二阶段辅助特征 |
| FER-Head-2 | 2.27M | 第二阶段检测头 |
| 总计 | 24.5M |
二、核心模块拆解
2.1 差分增强分组融合(DEGF)
DEGF是FER模块的核心融合单元,通过分组和差分增强实现高效跨模态融合。
分组融合(Group-wise Fusion):
- 将RGB和TIR的RoI特征沿通道维度分成N组(默认N=8)
- 每组独立计算融合权重,实现细粒度的模态自适应
差分增强(Differential Enhancement):
# 差分增强公式
F_hat_rgb = F_fpn_rgb * Ψ_rgb(F_fu^1 – F_fpn_rgb)
F_hat_tir = F_fpn_tir * Ψ_tir(F_fu^1 – F_fpn_tir)
F_fu^2 = LayerNorm(F_fu^1 + F_hat_rgb + F_hat_tir)
- 通过计算融合特征与原始FPN特征的差值,捕获跨模态互补信息
- 差值操作比拼接(Concatenation)更轻量,比加法(Add)性能更优
- 消融实验显示:差分增强使mAP提升0.4%(M3FD),且不增加FLOPs
2.2 辅助特征增强
FPN特征来自网络深层,包含高级语义但缺少低级空间细节。SFEDet引入骨干网络的浅层特征作为辅助输入:
- 通过RoI Align从骨干网络的第三阶段特征图中重新提取RoI特征
- 两阶段增强:第一阶段用FPN高层特征,第二阶段用骨干浅层特征
- 消融实验:辅助特征使mAP提升0.9%(从59.1%到60.0%)
2.3 滚动卷积(Rolling Convolution)
传统分组卷积(Group Convolution)的级联会导致组间信息交互不足。SFEDet提出滚动卷积:
原始特征 → 按组卷积 → 输出1 ─┐
├→ 拼接 → 1×1卷积 → 最终输出
滚动特征 → 按组卷积 → 输出2 ─┘
- 对特征进行通道维度滚动(偏移量为组内通道数的一半),再做第二组卷积
- 两次卷积结果拼接后通过1×1卷积融合
- 效果:比标准卷积减少22% FLOPs(144.4G → 112.6G),mAP反而提升0.1%
2.4 去噪训练策略
RPN在训练早期可能不够鲁棒,遗漏包含目标的区域。SFEDet借鉴DN-DETR的去噪思想:
- 在训练时向RoI列表中添加N组带噪声的GT框
- 噪声范围:坐标偏移量为框宽/高的±40%
- 作用:增强训练样本多样性,鼓励FER模块学习困难样本
- 消融实验:去噪策略使mAP提升1.1%(从59.9%到61.0%)
三、PyTorch代码实现
3.1 环境配置
# 创建conda环境
conda create -n sfedet python=3.10 -y
conda activate sfedet
# 安装PyTorch(根据CUDA版本选择)
pip install torch torchvision –index-url https://download.pytorch.org/whl/cu121
# 安装依赖
pip install ultralytics # YOLOv8
pip install einops
3.2 DEGF模块完整代码
import torch
import torch.nn as nn
import torch.nn.functional as F
class RollingConv(nn.Module):
"""🚀 滚动卷积:通过通道滚动实现组间信息交互,比标准卷积减少22% FLOPs"""
def __init__(self, in_channels, out_channels, groups=8, kernel_size=3, padding=1):
super().__init__()
self.groups = groups
self.group_size = in_channels // groups
# 第一组卷积
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size,
padding=padding, groups=groups, bias=False)
# 第二组卷积(滚动后)
self.conv2 = nn.Conv2d(in_channels, out_channels, kernel_size,
padding=padding, groups=groups, bias=False)
# 融合卷积
self.conv_fuse = nn.Conv2d(out_channels, out_channels, 1, bias=False)
def forward(self, x):
B, C, H, W = x.shape
# 第一组卷积
out1 = self.conv1(x)
# 通道滚动:每个组内偏移 group_size//2
shift = self.group_size // 2
x_rolled = torch.roll(x, shifts=shift, dims=1)
# 第二组卷积
out2 = self.conv2(x_rolled)
# 拼接并融合
out = torch.cat([out1, out2], dim=1)
out = self.conv_fuse(out)
return out
class DEGF(nn.Module):
"""🚀 差分增强分组融合:通过差值捕获跨模态互补信息,比Add性能更优"""
def __init__(self, in_channels, groups=8):
super().__init__()
self.groups = groups
# 差分增强的卷积块
self.psi_rgb = nn.Sequential(
nn.Conv2d(in_channels, in_channels // groups, 1),
nn.SiLU(),
nn.Conv2d(in_channels // groups, in_channels, 1),
nn.Sigmoid()
)
self.psi_tir = nn.Sequential(
nn.Conv2d(in_channels, in_channels // groups, 1),
nn.SiLU(),
nn.Conv2d(in_channels // groups, in_channels, 1),
nn.Sigmoid()
)
# 滚动卷积
self.rolling_conv = RollingConv(in_channels, in_channels, groups=groups)
self.norm = nn.LayerNorm([in_channels])
def forward(self, fpn_rgb, fpn_tir, fused_prev):
"""
Args:
fpn_rgb: RGB FPN特征 [B, C, H, W]
fpn_tir: TIR FPN特征 [B, C, H, W]
fused_prev: 上一阶段融合特征 [B, C, H, W]
Returns:
fused: 增强后的融合特征 [B, C, H, W]
"""
# 差分增强
diff_rgb = fused_prev – fpn_rgb
diff_tir = fused_prev – fpn_tir
# 自适应门控
gate_rgb = self.psi_rgb(diff_rgb)
gate_tir = self.psi_tir(diff_tir)
# 增强特征
enhanced_rgb = fpn_rgb * gate_rgb
enhanced_tir = fpn_tir * gate_tir
# 融合
fused = fused_prev + enhanced_rgb + enhanced_tir
# 滚动卷积进一步增强
fused = self.rolling_conv(fused)
# LayerNorm
B, C, H, W = fused.shape
fused = fused.permute(0, 2, 3, 1) # [B, H, W, C]
fused = self.norm(fused)
fused = fused.permute(0, 3, 1, 2) # [B, C, H, W]
return fused
class FERModule(nn.Module):
"""🚀 融合驱动检查与精炼模块:FER是SFEDet的核心,仅在稀疏RoI上运行"""
def __init__(self, in_channels=128, num_classes=6, groups=8):
super().__init__()
# DEGF融合
self.degf = DEGF(in_channels, groups=groups)
# 辅助特征增强
self.aux_enhance = nn.Sequential(
nn.Conv2d(in_channels, in_channels, 1),
nn.SiLU(),
nn.Conv2d(in_channels, in_channels, 3, groups=groups, padding=1),
nn.SiLU()
)
# 检测头(分类 + 回归)
self.cls_head = nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(in_channels, 512),
nn.SiLU(),
nn.Linear(512, num_classes)
)
self.reg_head = nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(in_channels, 512),
nn.SiLU(),
nn.Linear(512, 4) # 4个偏移量
)
def forward(self, fpn_rgb, fpn_tir, aux_rgb=None, aux_tir=None):
"""
Args:
fpn_rgb: RGB FPN特征
fpn_tir: TIR FPN特征
aux_rgb: RGB骨干浅层特征(可选)
aux_tir: TIR骨干浅层特征(可选)
Returns:
cls_logits: 分类输出 [B, num_classes]
reg_pred: 回归输出 [B, 4]
"""
# 初始融合(加法)
fused = fpn_rgb + fpn_tir
# DEGF增强
fused = self.degf(fpn_rgb, fpn_tir, fused)
# 辅助特征增强
if aux_rgb is not None and aux_tir is not None:
aux = self.aux_enhance(aux_rgb + aux_tir)
fused = fused + aux
# 检测头
cls_logits = self.cls_head(fused)
reg_pred = self.reg_head(fused)
return cls_logits, reg_pred
3.3 完整SFEDet网络
import torch
import torch.nn as nn
from ultralytics import YOLO
class SFEDet(nn.Module):
"""🚀 SFEDet:稀疏融合高效RGB-T检测器
核心思想:
1. 双轻量级RPN快速扫描,过滤背景
2. 仅在稀疏RoI上做融合驱动检查与精炼
3. 滚动卷积 + 去噪训练,兼顾效率与精度
"""
def __init__(self, num_classes=6, groups=8):
super().__init__()
# 双RPN(使用YOLOv8-Small作为backbone)
self.backbone_rgb = YOLO('yolov8s.yaml').model
self.backbone_tir = YOLO('yolov8s.yaml').model
# FER模块
self.fer_1 = FERModule(128, num_classes, groups) # 第一阶段
self.fer_2 = FERModule(128, num_classes, groups) # 第二阶段
# RoI Align
self.roi_align = nn.RoIAlign(output_size=7, spatial_scale=1/16,
sampling_ratio=2)
def forward(self, rgb, tir, proposals=None):
"""
Args:
rgb: RGB图像 [B, 3, H, W]
tir: TIR图像 [B, 3, H, W]
proposals: 候选框列表(训练时由RPN生成)
Returns:
cls_logits: 分类输出
reg_pred: 回归输出
"""
B = rgb.shape[0]
# Stage 1: 双RPN快速扫描
feat_rgb = self.backbone_rgb(rgb)
feat_tir = self.backbone_tir(tir)
# 生成RoI(训练时从RPN输出,推理时从NMS)
if proposals is None:
proposals = self._generate_proposals(feat_rgb, feat_tir)
# RoI Align提取配对特征
roi_rgb = self.roi_align(feat_rgb, proposals)
roi_tir = self.roi_align(feat_tir, proposals)
# Stage 2: FER融合检查与精炼
cls_1, reg_1 = self.fer_1(roi_rgb, roi_tir)
cls_2, reg_2 = self.fer_2(roi_rgb, roi_tir)
# 逐步精炼(最终预测用第二阶段)
return cls_2, reg_2
def _generate_proposals(self, feat_rgb, feat_tir):
"""从双RPN生成候选框并取并集"""
# 这里简化实现,实际需要NMS和并集操作
# 真实实现参考论文Appendix B
pass
# 测试代码
if __name__ == "__main__":
# 创建模型
model = SFEDet(num_classes=6)
# 模拟输入
rgb = torch.randn(1, 3, 640, 640)
tir = torch.randn(1, 3, 640, 640)
# 前向传播
cls_logits, reg_pred = model(rgb, tir)
print(f"分类输出: {cls_logits.shape}") # [1, 6]
print(f"回归输出: {reg_pred.shape}") # [1, 4]
print(f"总参数量: {sum(p.numel() for p in model.parameters())/1e6:.1f}M")
四、YOLO迁移3 Steps
SFEDet的设计思想可以轻松迁移到YOLO系列,实现高效的双模态检测。
Step 1:双骨干提取特征
# 使用YOLOv8-Small作为双RPN的backbone
from ultralytics import YOLO
# 创建双骨干
backbone_rgb = YOLO('yolov8s.yaml') # 8.4M参数
backbone_tir = YOLO('yolov8s.yaml') # 8.4M参数
# 提取多尺度特征
feat_rgb = backbone_rgb.model.extract_features(rgb) # [P3, P4, P5]
feat_tir = backbone_tir.model.extract_features(tir) # [P3, P4, P5]
Step 2:稀疏RoI提取
# 从双RPN生成候选框
proposals_rgb = backbone_rgb.predict(rgb, conf=0.25) # RGB候选框
proposals_tir = backbone_tir.predict(tir, conf=0.25) # TIR候选框
# 取并集并NMS
proposals_union = torch.cat([proposals_rgb, proposals_tir], dim=0)
proposals = nms(proposals_union, iou_threshold=0.5) # 稀疏候选区域
# RoI Align提取配对特征
roi_rgb = F.roi_align(feat_rgb[–1], proposals, output_size=7)
roi_tir = F.roi_align(feat_tir[–1], proposals, output_size=7)
Step 3:FER融合检测
# 差分增强分组融合
def degf_fusion(fpn_rgb, fpn_tir, groups=8):
"""DEGF融合模块"""
fused = fpn_rgb + fpn_tir
# 差分增强
diff_rgb = fused – fpn_rgb
diff_tir = fused – fpn_tir
# 门控
gate_rgb = torch.sigmoid(conv(diff_rgb))
gate_tir = torch.sigmoid(conv(diff_tir))
# 增强融合
fused = fused + fpn_rgb * gate_rgb + fpn_tir * gate_tir
return fused
# FER检测头
cls_pred = cls_head(fused) # 分类
reg_pred = reg_head(fused) # 回归
五、实验
5.1 数据集与评估指标
- M3FD:4.2K图像对,6类别,1024×768分辨率
- FLIR:对齐的RGB-T数据集,640×512分辨率
- LLVIP:1280×1024高分辨率,低光照场景
5.2 SOTA对比
| ICAFusion | 2024 | CSP-L | 120M | 370G | 88.2 | – | 66.9 | 89.0 | 41.1 | 79.2 |
| EI2Det | 2025 | CSP-L | 116M | 391G | 86.2 | – | 66.3 | 89.4 | – | 80.2 |
| Fu-Mamba | 2025 | CSP-L | 288M | 1133G | 88.0 | – | – | – | 45.9 | 84.9 |
| COFNet | 2025 | CSP-L | 90.2M | 197G | – | – | – | – | 44.6 | 83.6 |
| SFEDet (Ours) | 2026 | CSP-S | 24.5M | 69G | 61.0 | 89.8 | 43.0 | 81.7 | 65.9 | 96.8 |
⚠️ 注意:SFEDet的mAP(61.0%)是针对稀疏RoI的精炼结果,而其他方法的mAP是全图检测结果。SFEDet的优势在于效率:24.5M参数、69G FLOPs,仅为Fu-Mamba的8.5%参数量和6%计算量。
5.3 消融实验
| Base(无分组融合) | 57.2 | 85.4 | 41.9 | 79.9 |
| + 分组融合 | 58.4 | 87.1 | 41.6 | 79.9 |
| + 差分增强 | 58.6 | 87.2 | 41.9 | 80.3 |
| + 辅助特征 | 59.9 | 88.5 | 42.1 | 80.8 |
| + 逐步精炼 | 61.0 | 89.8 | 43.0 | 81.7 |
5.4 ✅ 亮点总结
- ✅ 稀疏融合范式:首次在RGB-T检测中实现"先扫描后融合",计算成本与目标数量线性相关
- ✅ 滚动卷积:比标准卷积减少22% FLOPs,mAP反升0.1%,轻量化新思路
- ✅ 参数效率碾压:24.5M参数(8.5% of Fu-Mamba),69G FLOPs(6% of Fu-Mamba),性能持平
- ✅ 高分辨率可扩展:稀疏融合天然适合高分辨率图像,FLOPs增长亚线性
- ✅ 去噪训练:借鉴DN-DETR,解决RPN早期训练不稳定问题