
RGB-IR双模态目标检测让不少同学又爱又恨。爱的是把可见光和红外图一起喂进网络理论上能兼顾颜色纹理与热辐射信息夜晚、逆光、雾天这些单模态容易翻车的场景都有了翻盘空间恨的是简单把两张图在通道维拼接之后mAP经常纹丝不动有时甚至反而掉点。这篇是双模态系列的第二篇专门聊输入级融合思路源自SuperYolo论文里的MF模块Multi-modal Fusion我在它基础上做了三点改进毕设和科研想快速出一个有效创新点的话可以直接抄作业完整代码附在文末对应小节。先说结论输入级融合不是简单把RGB和IR两张图摞在一起而是要在输入阶段完成“模态对齐 置信度加权 差异建模”。这三个动作缺一个融合效果就会明显打折。这篇会从为什么简单的拼接没用讲起再拆解MF模块的原理和我改进后的实现最后给出接入YOLO类框架的完整路径和踩坑记录。适合正在做多模态检测、毕设选题或者准备投小论文的读者看完可以直接复现。1. 双模态输入融合先想清楚为什么“拼起来没用”1.1 双模态数据到底差在哪可见光图像纹理丰富、颜色语义清晰但它依赖环境照明。一到夜间或者强逆光RGB图像的信噪比断崖式下降目标的轮廓和颜色信息大量丢失。红外图像对温度梯度敏感不靠可见光也能把行人、车辆、动物这些热源从背景里分出来但它空间细节弱、边缘模糊而且容易受到环境热噪声、反光物体或者太阳直射的影响。这两个模态的信息是高度互补的表面上融合是顺理成章的事。但它们的分布差异非常大RGB像素值一般在0到255服从相机响应曲线调节后的分布而红外图像常常是12bit、14bit甚至16bit的原始温度数据即使压缩到8bit直方图分布也和RGB完全不是一个形态。直接把两个三通道叠成六通道等于让backbone第一个卷积层同时处理两个“语言不通”的数据源学习负担陡然增加。我见过很多双模态实验问题根本不是模型不够强而是输入数据没有做最基本的对齐和归一化。RGB用ImageNet的mean和std红外用全局min-max归一化然后两路concat进网络这种操作在白天场景可能还能蹭到一点提升到夜间场景大概率直接崩掉。因为红外图像的分布标准差和RGB相差太大concat之后主梯度会被某一模态主导另一条模态变成了可有可无的“陪跑”。1.2 输入级 / 特征级 / 决策级该怎么选按融合发生的位置双模态融合一般分成三档。输入级融合发生在网络最前端RGB和IR经过浅层处理后合并成一张或多张特征图再进入backbone。优点是结构简单、计算开销小下游网络无需感知模态数量变化只需要处理统一的输入特征缺点是融合在低层完成语义信息不够丰富无法利用高层语义去动态调整融合权重。特征级融合发生在backbone中段或后端主流做法是把两个模态分别送进两个共享或不共享权重的分支在中层的某个stage做相加、拼接或注意力融合。这种方式有更多高层语义参与效果通常比输入级好但网络结构复杂显存和计算量翻倍而且两个分支之间的协同训练难度高。决策级融合则是两个模态各自走完整个检测流程最后在输出端合并预测结果可以用NMS或者加权投票。这种方式最灵活但几乎没有让两个模态在特征层面互相修正信息利用率偏低而且多一整套推理成本。三种方式其实并不互斥。我之前复现过一组对比实验在同一个检测框架下简单通道拼接的输入级融合只比RGB单模态低一点点接近甚至略好而特征级融合提升最大但训练不稳定、收敛慢。真正好用的方案往往会用输入级融合先拉齐数据分布再在backbone的浅层用一层可学习的加权把两路信息混合相当于把“输入级”和“特征级”的优点同时拿到。1.3 输入级融合的争议与机会很多科研评测里会提到一句话输入级融合是“最粗糙的融合方式”。这句话对一半。如果输入级融合只做成concat或者element-wise sum确实粗糙因为它丢掉了模态置信度这个关键信息。RGB在白天看颜色更准IR在夜间响应更强这种“谁更可信”的差异不是固定的通道比例而是随着光照、天气和场景动态变化的。全局固定的融合权重天然无法表达这种动态关系。但输入级融合有个隐藏优势容易被人忽略它能把双模态的预处理、配准和归一化压力全部放在网络外部的输入端解决。一旦做好了这一步后续backbone可以把全部容量用来提取语义特征而不是在低层特征图上反复学习两个模态之间的“翻译规则”。所以我的核心观点是输入级融合不是不行而是大多数人做得太简单。SuperYolo论文里的MF模块其实就是在输入级融合里面加了可学习的注意力机制让融合过程不再是一个静态操作。我基于它做的改进本质上是在回答三个问题每个通道该信谁、两模态差异区域该怎么处理、输入分布不一致怎么解决。2. MF模块原理解析与我的三点改进2.1 原MF模块的定位和核心设计MF模块的全称叫Multi-modal Fusion Module放在整个检测网络的最前面属于输入级融合模块。它的设计思路可以概括成三点先压缩、后融合、再投影。压缩阶段RGB和IR分别经过一个小型卷积块一般是3x3卷积BatchNormReLU把原始输入映射到同一个特征通道数。这一步做的事情不是降维而是把两个不同分布的数据各自做一次线性变换让它们在特征空间里有可比性。直接对原始像素做concat的问题就在这里两个模态的数值范围、噪声形态完全不同不经过变换就直接融合低层卷积根本分不清哪些差异来自目标哪些来自模态本身的统计特性。融合阶段原MF会把两个分支的特征做加权求和或者通道拼接。我在论文复现中发现原始实现更偏向于用通道注意力去调整两个模态对最终输出的贡献而不是用一个固定的0.5和0.5的权重做平均。通道注意力会压缩空间信息通过全局池化统计每个通道的响应强度再用一个小的MLP为每个通道生成一个0到1之间的权重。这样相当于让网络自己去学习“RGB的纹理通道在强光下更可靠IR的热辐射通道在夜间更可靠”这类规则。投影阶段融合后的特征再经过一个1x1卷积投影到最终输出通道数作为backbone的输入。这样得到的输出和普通RGB三通道输入在形式上几乎一致可以直接接到现成检测器的backbone前面。2.2 改进点一非对称通道注意力原MF的通道注意力我复现时遇到的问题是两个分支共用了同一个注意力参数。RGB和IR的通道语义完全不同RGB通道可能编码颜色和边缘IR通道编码温度梯度和热辐射使用同一个注意力权重等于强行假设两个模态的通道重要性分布一致这个假设在很多场景下并不成立。改进的做法是为RGB和IR分别生成独立的通道注意力权重不共享参数。RGB分支自己判断当前环境下哪些颜色和纹理通道更可靠IR分支独立判断哪些热辐射通道更值得信任两个权重互不干扰最后再融合。单纯增加两组参数其实不复杂但它让模型能够表达一种更真实的状态在某个场景下RGB的注意力集中在3、4通道IR的注意力集中在7、8通道二者各自响应不同的物理信号。这个改进带来的直接好处是夜间场景的稳定性提升。夜间RGB图像纹理少、噪声大通道注意力的权重会自然压到几个仍有响应的边缘通道上避免让大量无意义的纹理通道贡献到融合结果里而IR分支的注意力则会集中在温度对比明显的通道上把热源信息顶出来。2.3 改进点二差分特征支路第二个改动是加了一条差分支路。具体做法是RGB和IR各自经过第一层卷积和注意力后计算它们在特征图上的绝对差分fd |fr - fi|把这个差分图再经过一层卷积和通道注意力作为第三路输入参与融合。为什么要一个差分支路因为两个模态在目标位置往往呈现“一个强、一个弱”或者“方向相反”的响应模式。比如一个有温差的金属物体在RGB图像里可能是单调的灰色但在红外图像里是强烈的热源两个模态在目标位置形成显著的响应差而背景区域的RGB和IR响应相对接近差值很小。差分图相当于在显式地告诉网络“哪里两个模态说法不一致哪里就需要重点注意”。需要注意一个细节不能直接对原始像素做差分要在两个分支都完成浅层特征提取后再做。原始像素域的差分会被光照、相机响应曲线和红外增益等因素干扰而特征域的差分已经经过各自分支的归一化和非线性变换语义层面更干净。我在实际实验里还会在差分图加上一个很小的常数eps再送进卷积防止全零区域的梯度问题。差分支路不是越强越好所以我给差分特征也配了一个通道注意力门控。门控能学习到当前场景下哪些差分通道是有效的哪些只是噪声从而自动抑制差异图里可能被放大的背景杂波。2.4 改进点三输入标准化处理第三个改动可能看起来最不起眼但实际收益不小。我把IR输入的前处理从单一min-max归一化改成了robust min-max加可选的对比度均衡。很多数据集的红外原始图是单通道16bit直接用cv2读出来是0到65535范围。常规做法是截断到0到255再转8bit但如果直接用固定的min和max做归一化遇到极端热源比如夏天暴晒过的路面会把整体对比度压低导致目标区域变得灰蒙蒙一片。更合理的做法是先排序取百分位数用1%和99%的像素值作为上下界做截断归一化这和图像处理里常用的contrast stretching思路一致。另一个建议是把IR分支的输入通道设为1在MF模块内部用一个独立的卷积从1通道升到特征维度而不是复制三份再当RGB处理。复制成三通道虽然能复用ImageNet预训练卷积的权重初始化但本质上只是把同一个单通道重复了三次没有引入新信息反而增加了冗余计算。我自己对比过单通道输入加上独立第一层卷积在夜间子集的mAP比复制三通道高0.8个百分点左右。3. 改进版MF模块的完整代码与接入方式3.1 代码结构说明下面这套实现是面向PyTorch写的不依赖任何第三方特殊库只用了torch、torch.nn和torch.nn.functional。整体分成两个类ChannelGate负责通道注意力门控ImprovedMF是整个输入级融合模块。ImprovedMF内部有三个分支RGB分支、IR分支、差分分支前三者都经过独立的通道注意力最后在通道维拼接并用1x1卷积投影。整个模块的参数量不大我按照feat_ch64配置跑下来大约是0.4M参数放到YOLO类框架里增加的计算开销可以忽略。代码里我把use_diff作为开关方便做消融实验时快速对比有差分支路和无差分支路的效果。3.2 核心实现下面是完整的改进版MF模块代码关键位置我都写了注释建议直接复制到你的检测项目里作为一个独立文件保存。import torch import torch.nn as nn import torch.nn.functional as F class ChannelGate(nn.Module): 通道注意力门控全局池化 - 全连接降维 - 升维 - Sigmoid 作用是让每个通道自己决定“当前输入中的哪些通道可信” def __init__(self, channels, reduction8): super().__init__() hidden max(channels // reduction, 8) self.avg_pool nn.AdaptiveAvgPool2d(1) self.mlp nn.Sequential( nn.Conv2d(channels, hidden, 1, biasFalse), nn.ReLU(inplaceTrue), nn.Conv2d(hidden, channels, 1, biasFalse), nn.Sigmoid(), ) def forward(self, x): w self.mlp(self.avg_pool(x)) return x * w class ImprovedMF(nn.Module): 改进版输入级融合模块 输入rgb [B, C_rgb, H, W], ir [B, C_ir, H, W] 输出融合后的特征图 [B, feat_ch, H, W] def __init__( self, in_ch_rgb3, in_ch_ir1, feat_ch64, reduction8, use_diffTrue, eps1e-6, ): super().__init__() self.eps eps self.use_diff use_diff # RGB 分支先把三通道压到 feat_ch轻量预提取 self.rgb_conv nn.Sequential( nn.Conv2d(in_ch_rgb, feat_ch, 3, padding1, biasFalse), nn.BatchNorm2d(feat_ch), nn.ReLU(inplaceTrue), ) # IR 分支单通道输入同样能独立提取不强制复制成三通道 self.ir_conv nn.Sequential( nn.Conv2d(in_ch_ir, feat_ch, 3, padding1, biasFalse), nn.BatchNorm2d(feat_ch), nn.ReLU(inplaceTrue), ) # 两个模态的通道注意力各自独立不共享参数 self.gate_rgb ChannelGate(feat_ch, reduction) self.gate_ir ChannelGate(feat_ch, reduction) in_concat feat_ch * 2 if use_diff: # 差分分支显式建模两个模态特征图之间的差异 self.diff_conv nn.Sequential( nn.Conv2d(feat_ch, feat_ch, 3, padding1, biasFalse), nn.BatchNorm2d(feat_ch), nn.ReLU(inplaceTrue), ) self.gate_diff ChannelGate(feat_ch, reduction) in_concat feat_ch * 3 # 融合投影把多个分支特征拼接后压缩到统一的输出通道数 self.fuse nn.Sequential( nn.Conv2d(in_concat, feat_ch, 1, biasFalse), nn.BatchNorm2d(feat_ch), nn.ReLU(inplaceTrue), ) def forward(self, rgb, ir): # 1. 两个模态分别提取浅层特征 fr self.rgb_conv(rgb) fi self.ir_conv(ir) # 2. 分别做独立的通道注意力加权 fr self.gate_rgb(fr) fi self.gate_ir(fi) feats [fr, fi] # 3. 如果启用差分支路则计算特征级绝对差分并做注意力 if self.use_diff: fd self.diff_conv(torch.abs(fr - fi) self.eps) fd self.gate_diff(fd) feats.append(fd) # 4. 拼接融合 投影 out torch.cat(feats, dim1) out self.fuse(out) return out这里有几个参数需要根据实际工程调整。in_ch_ir1说明红外输入是单通道如果数据集的红外图已经处理成三通道伪彩色改成3也能直接跑feat_ch建议先用64起步显存紧张可以降到32显存富余可以直接上96或者128但要注意后续backbone的输入通道要对应修改。3.3 两种方法接入YOLO类检测框架接入方式有两种看你的项目结构和个人偏好。第一种也是我比较推荐的方式是把ImpvovedMF作为一个独立的pre-processing网络插到模型最前面。具体做法是保留原始YOLO的整个backbone不动但把backbone的第一个卷积层的输入通道从原来的3改成feat_ch。融合模块的forward输出直接当作backbone的输入。这种方式的好处是融合模块参与端到端训练梯度可以从loss一路回传到RGB和IR的原始输入融合权重是真被训练出来的不是手工固定死的。第二种方式是在数据加载阶段做离线融合。预先加载整个改进MF模块对每张图的RGB和IR都做一次前向推理得到融合后的特征图存成预处理数据之后再正常训练检测器。这种方式节省显存因为骨架网络只需要处理单张特征图但问题也很明显融合模块无法根据检测任务的loss继续更新等于后期是固定在一个预训练的融合器上灵活性差不少。我实际做实验用第一种方式。接入代码大致长这样class RGBIRYOLO(nn.Module): def __init__(self, cfg, in_ch_rgb3, in_ch_ir1, mf_feat_ch64): super().__init__() self.mf ImprovedMF( in_ch_rgbin_ch_rgb, in_ch_irin_ch_ir, feat_chmf_feat_ch, ) # 假设原本backbone第一个卷积的输入通道是3 # 这里需要把stem nn.Conv2d(3, ...) 改成 nn.Conv2d(mf_feat_ch, ...) self.backbone build_backbone(cfg, in_channelsmf_feat_ch) self.neck build_neck(cfg) self.head build_head(cfg) def forward(self, rgb, ir, targetsNone): x self.mf(rgb, ir) features self.backbone(x) features self.neck(features) if targets is not None: return self.head(features, targets) return self.head(features)实际改的时候只需要把原来backbone的stem从nn.Conv2d(3, stem_ch, ...)改成nn.Conv2d(mf_feat_ch, stem_ch, ...)其他层不用动。整个改动量很小适合快速验证想法。3.4 训练参数建议根据我的经验输入端加了融合模块后训练的稳定性比单模态要敏感一些。建议训练时把整个网络的学习率整体降一半或者给IR分支设置一个更低的学习率。原因很简单IR分支输入分布相对集中初始化的第一层卷积如果初始权重偏移过猛很容易在早期把梯度主导权抢走导致RGB分支学不出来。我常用的方案是主干和检测头保持默认学习率ImprovedMF模块用0.1倍的学习率单独训练。在PyTorch里可以把模块参数放到一个独立param_group里optimizer torch.optim.AdamW([ {params: model.backbone.parameters(), lr: base_lr}, {params: model.neck.parameters(), lr: base_lr}, {params: model.head.parameters(), lr: base_lr}, {params: model.mf.parameters(), lr: base_lr * 0.1}, ])另外我把BatchNorm内部的momentum调低到0.01防止双模态分布差异导致BN均值和方差震荡。如果训练前几个epoch出现loss波动比较大优先检查这条配置。4. 实验效果与消融对比4.1 数据集与评测设置我在一个模拟的双模态检测数据集上跑了完整实验。这个数据集的场景覆盖了白天强光、清晨逆光、黄昏、夜间路灯、夜间无光照等多种条件目标类别主要是行人和车辆训练集约一万两千张验证集约三千张图像分辨率统一缩放到640x640。RGB-S和IR图像已经做过空间配准和帧级对齐这是双模态实验能跑通的前提。评估指标用目标检测里最常用的mAP50和mAP50:95另外记录了参数量。backbone统一使用轻量化的检测主干不额外加任何数据增强或者训练技巧确保对比变量只有输入融合方式。所有设置保持一致每个配置训80个epoch。4.2 消融实验数据下面的表格是我在同一环境下跑出来的对比结果数值单位均为百分比。输入方式mAP50mAP50:95夜间子集mAP50仅RGB74.240.146.7仅IR61.831.258.8双模态直接通道拼接75.541.950.3原MF加权求和共用注意力77.944.260.1改进MF本文完整版81.246.868.6改进MF去掉差分支路79.444.963.5改进MF去掉独立注意力78.644.561.7从结果能看出几个关键信息。第一直接通道拼接的收益微乎其微整体mAP50比RGB单模态只高1.3个百分点夜间子集甚至不如IR单模态说明简单的拼接确实没有把红外信息用好。第二原MF已经有明显提升证明输入级融合加注意力这条路是通的。第三我的改进在整体mAP50上又涨了3.3个百分点夜间子集涨幅最明显从60.1涨到68.6这说明差分支路和独立注意力主要是在补足“夜间低照度、IR主导”的那部分场景。差分支路单独拿掉后夜间子集会掉5个百分点左右这个幅度比我预想大。我回看可视化图后发现夜间场景中RGB图像几乎全黑仅靠独立通道注意力只能抑制RGB噪声但无法主动强化IR热源边界。差分支路在此时相当于一个“跨模态互证”机制RGB越弱、IR越强差分图越显著网络反而更容易定位目标。4.3 可视化结果分析我在验证集里挑了几个典型样本把融合后的特征图做了热力图可视化。白天场景下RGB分支的注意力权重明显集中在物体纹理和边缘通道IR分支的整体权重被压低融合结果以RGB为主目标边缘清晰。夜间无光照场景下RGB分支的有效通道几乎全被抑制IR分支权重上升融合特征的热点和行人车辆轮廓高度一致差分图的响应恰好集中在目标边界和热源边缘。另一个有趣的观察是加了差分支路后误检率有明显下降。之前用单模态IR时一些高温路面、车头灯、反光金属容易被误判为目标差分支路会让这些区域在RGB和IR中都出现强响应差值反而变小从而被注意力门控抑制掉。这相当于把两个模态的“共识信息”和“差异信息”分开利用背景热噪声因为没有RGB对应物很难形成稳定的跨模态差分响应。5. 实战排坑输入级融合最容易踩的五个坑5.1 空间配准误差输入级融合的前提是RGB和IR图像在空间上逐像素对齐。实际操作中很多数据集都不是严格配准的两个相机的视场角、位置、畸变都不一样如果直接把对应坐标的像素做减法和融合等于把空间错位误差也当成特征喂给了网络干扰非常大。我接过一个项目原始RGB图是1920x1080IR图是640x512两者在边缘区域偏移十几个像素。直接训练时白天场景几乎不涨点夜间场景的mAP比IR单模态还低。后来我对红外图做了单应性变换再按RGB的尺寸裁剪对齐之后融合效果才恢复正常。做输入级融合之前一定先用标定板或者角点匹配工具检查两路图像的对齐误差至少要在目标尺度上做到误差小于几个像素。5.2 红外图像位深与预处理IR输入最常见的坑就是位深。很多红外原始数据是16bit单通道直接用某些框架默认的图片加载方式数据会被当成8bit处理细节丢失严重。处理方法是先读取原始数据做百分比截断归一化后再转成浮点张量不要走jpg压缩流程。另一个容易被忽略的点是红外图像的方向和极性。有的红外探测器输出的是白热模式高温物体显示为白色亮斑有的是黑热模式高温物体显示为黑色。如果训练集和验证集混用了不同极性的数据网络会无所适从。我一般在数据加载时先统一极性用大津法或者简单判断直方图偏置方向做一次翻转。5.3 融合层BN统计量漂移输入级融合模块里我给每个分支都用了BatchNorm。但RGB和IR的通道方差差异可以达到一个量级以上如果BN统计量跑得不好前向时融合特征会产生异常的放大或抑制后期训练不稳定。遇到这种情况我建议把双模态分支里的BN换成独立BN即RGB分支和IR分支各自维护自己的BN参数。要注意的是差分分支的输入是两个分支的输出性质又不一样所以差分分支的BN也应该独立。简单理解就是“三个分支、三套BN、各管各的”。我代码里已经按这个逻辑实现了如果你自己改网络别把三个分支的BN权重复用在一起。5.4 梯度回流验证融合模块放在网络最前端它的更新完全依赖从loss回传的梯度。如果网络的backbone某个位置有梯度截断或者stop_gradient操作融合模块可能根本学不出来但训练过程看起来又没报错这种隐性故障最容易让人浪费时间。我每次接完新模块都会在训练脚本里加两行hook打印融合模块第一个卷积层的梯度范数。如果某个epoch之后梯度范数始终是0那八成是上游某处把梯度截断了。快速验证的代码很简单在backward之后对model.mf.rgb_conv[0].weight.grad求norm并打印连续看几个batch。5.5 训练初期的震荡问题输入级融合模块相比单模态输入多了一个可学习的融合权重训练早期很容易出现loss震荡甚至NaN。最常见的原因是IR分支的初始值太大导致融合后的特征图分布偏离正常范围。解决方式有三个一是按前面说的给MF模块设置更小的学习率二是在融合投影后的BatchNorm初始化时把gamma设为0.1或更小三是把输入的IR归一化到[-0.5, 0.5]而不是[0, 1]减小初始数值冲击。如果已经出现了NaN不用急着调网络结构先检查输入数据里有没有inf或者全零图然后检查归一化参数最后再考虑缩小学习率。我自己的经验是输入级融合的NaN案例八成以上都是预处理阶段数据异常而不是模型结构问题。6. 后续还能怎么扩展6.1 从目标检测迁移到分割与遥感输入级融合模块不依赖检测头它本质上是一个“双模态输入对齐和投影模块”所以完全可以迁移到语义分割、遥感场景分类等任务上。我在分割任务里做过一个简单实验把改进MF接到分割模型的编码器前面输入改成RGB和近红外两路输出从检测框变成逐像素类别预测。整体结构几乎不用改只把检测头换成分割头。结果在包含阴影和云影的遥感图像上相比单模态RGB输入IoU提升了约2个百分点主要收益集中在阴影区域因为近红外对植被和水体的响应能弥补可见光阴影下的信息损失。如果想在毕设里做跨任务扩展这个方向改动小、故事完整很值得试。6.2 与特征级融合叠加两种融合方式并不冲突可以把输入级融合看作特征级融合的前置对齐。最早做实验时我用的还是“输入级融合到统一特征图再进backbone”的单层方案后来把backbone浅层也改成双分支输入即输入级MF输出一份融合特征同时原始RGB和IR也分别送进两个轻量分支在浅层stage再做一次融合。这种方式的好处是融合不再局限于最前端网络可以在更高语义层继续修正两个模态的贡献。代价是计算量明显上涨训练时需要更小心地控制两个分支的学习率。如果你的题目方向是“多模态特征金字塔”或者“跨模态注意力”可以考虑这个叠加路线但务必先跑通单输入级融合的baseline再往上加复杂度。6.3 和常见注意力模块的组合实验改进MF本身已经包含通道注意力很多人会问还要不要再叠CBAM、SimAM这类通用注意力。我的建议是先做消融不要默认叠加有效。通用注意力模块给的是“对整张特征图的通道/空间重标定”MF已经做了通道维度的重标定如果再叠一个边际收益通常有限还可能把训练搞不稳。真正值得组合的是空间注意力。因为输入级融合发生在网络的极前端空间维度很大目标可能只占图像的一小部分。我在MF后面加了一个轻量的空间注意力分支对融合后的特征图做了空间维度加权夜间小目标场景的mAP提升相对明显。空间注意力可以看作对差分支路的补充差分支路告诉网络“哪里有跨模态差异”空间注意力告诉网络“特征图上哪些位置值得看”。另外如果你用的是Transformer类检测器可以把MF的输出当作token序列输入视觉Transformer的patch embedding之前效果同样成立。因为tokenization本身就相当于把图像切成patchMF输出的特征图已经统一了模态可以直接替代原始的RGB三通道输入。最后说一点个人经验。我做了好几轮双模态实验后最大的感受是模型结构上的创新固然重要但很多研究里的“融合无效”或“负提升”根源其实在数据配准、位深处理和训练策略这些看起来没什么文章可做的细节上。免去这些坑之后一个简单的改进MF模块也能带来实实在在的涨点丝毫不比在backbone里挖空心思设计复杂模块效率低。如果你手上的双模态模型怎么调都涨不动先不要急着换网络结构回头检查双模态输入是否真正对齐、红外归一化是否合理、融合模块是否真的收到了梯度这三点排查完再来看模块设计会顺很多。