RGB-IR 双模态目标检测系列三|3 种特征级融合方法全解析(附可运行代码 + 顶刊创新思路)
全文包含可直接运行的代码建议点赞收藏 关注后续持续更新双模态检测改进创新系列内容。本文是双模态系列的第9篇收藏文集持续跟进顶刊创新思路。跨模态特征融合主要面向可见光 - 红外、RGB - 多光谱、雷达 - 图像等互补数据核心流程为特征对齐、模态交互、自适应融合与精炼。首先采用双分支结构利用 CNN 或 Transformer 分别对不同模态进行独立特征提取在保留红外抗干扰、RGB 纹理细节等独有信息的同时输出空间尺寸相近的特征图。随后通过 1×1 卷积实现通道维度统一完成特征空间对齐为后续交互奠定基础。融合核心在于跨模态注意力交互通过通道注意力筛选关键特征通道借助空间注意力强化目标区域并抑制背景干扰结合查询 - 键值机制实现模态间信息互补与自适应加权。特征融合常采用通道拼接、逐元素相加或门控加权等方式动态分配不同模态的贡献度。最后利用 3×1 卷积或残差结构对融合特征进行精炼降低信息混叠与噪声干扰输出鲁棒性更强的联合特征用于后续目标检测任务。下面的模块可以用来取代特征级融合中简单的Concat操作1.DEYOLO: Dual-Feature-Enhancement YOLO for Cross-Modality Object Detectionimport torch import torch.nn as nn class DEA(nn.Module): x[0] -- RGB feature map, x[1] -- IR feature map 已修改接口以适配 YOLOv11 tasks.py 的 parse_model # 接口修改 1: 增加 c1, c2 参数 def __init__(self, c1, c2, kernel_size80, p_kernelNone, m_kernelNone, reduction16): super().__init__() # 接口修改 2: YOLO 传入的跨模态 c1 是列表 [ch_rgb, ch_nir]提取单流通道数 channel c1[0] if isinstance(c1, list) else c1 self.deca DECA(channel, kernel_size, p_kernel, reduction) self.depa DEPA(channel, m_kernel) self.act nn.Sigmoid() def forward(self, x): # 接收 YAML 传来的列表 x [RGB, IR] result_vi, result_ir self.depa(self.deca(x)) # 保持原逻辑输出单一融合张量 return self.act(result_vi result_ir) # # 下方的 DECA 和 DEPA 严格保持原样一行未改 # class DECA(nn.Module): x0 -- RGB feature map, x1 -- IR feature map def __init__(self, channel512, kernel_size80, p_kernelNone, reduction16): super().__init__() self.kernel_size kernel_size self.avg_pool nn.AdaptiveAvgPool2d(1) self.fc nn.Sequential( nn.Linear(channel, channel // reduction, biasFalse), nn.ReLU(inplaceTrue), nn.Linear(channel // reduction, channel, biasFalse), nn.Sigmoid() ) self.act nn.Sigmoid() self.compress Conv(channel * 2, channel, 3) convolution pyramid if p_kernel is None: p_kernel [5, 4] kernel1, kernel2 p_kernel self.conv_c1 nn.Sequential(nn.Conv2d(channel, channel, kernel1, kernel1, 0, groupschannel), nn.SiLU()) self.conv_c2 nn.Sequential(nn.Conv2d(channel, channel, kernel2, kernel2, 0, groupschannel), nn.SiLU()) self.conv_c3 nn.Sequential( nn.Conv2d(channel, channel, int(self.kernel_size/kernel1/kernel2), int(self.kernel_size/kernel1/kernel2), 0, groupschannel), nn.SiLU() ) def forward(self, x): b, c, h, w x[0].size() w_vi self.avg_pool(x[0]).view(b, c) w_ir self.avg_pool(x[1]).view(b, c) w_vi self.fc(w_vi).view(b, c, 1, 1) w_ir self.fc(w_ir).view(b, c, 1, 1) glob_t self.compress(torch.cat([x[0], x[1]], 1)) glob self.conv_c3(self.conv_c2(self.conv_c1(glob_t))) if min(h, w) self.kernel_size else torch.mean( glob_t, dim[2, 3], keepdimTrue) result_vi x[0] * (self.act(w_ir * glob)).expand_as(x[0]) result_ir x[1] * (self.act(w_vi * glob)).expand_as(x[1]) return result_vi, result_ir class DEPA(nn.Module): x0 -- RGB feature map, x1 -- IR feature map def __init__(self, channel512, m_kernelNone): super().__init__() self.conv1 Conv(2, 1, 5) self.conv2 Conv(2, 1, 5) self.compress1 Conv(channel, 1, 3) self.compress2 Conv(channel, 1, 3) self.act nn.Sigmoid() convolution merge if m_kernel is None: m_kernel [3, 7] self.cv_v1 Conv(channel, 1, m_kernel[0]) self.cv_v2 Conv(channel, 1, m_kernel[1]) self.cv_i1 Conv(channel, 1, m_kernel[0]) self.cv_i2 Conv(channel, 1, m_kernel[1]) def forward(self, x): w_vi self.conv1(torch.cat([self.cv_v1(x[0]), self.cv_v2(x[0])], 1)) w_ir self.conv2(torch.cat([self.cv_i1(x[1]), self.cv_i2(x[1])], 1)) glob self.act(self.compress1(x[0]) self.compress2(x[1])) w_vi self.act(glob w_vi) w_ir self.act(glob w_ir) result_vi x[0] * w_ir.expand_as(x[0]) result_ir x[1] * w_vi.expand_as(x[1]) return result_vi, result_ir1. 该模块通过**通道级与空间级的双向注意力交互**让RGB与红外特征实现相互加权、互补增强而非简单拼接的无差别堆叠能主动筛选关键特征、抑制背景噪声大幅提升跨模态有效信息的聚合效率。2. 模块内置**多尺度卷积金字塔与自适应空间融合结构**可动态捕捉不同尺寸目标的空间特征解决了简单拼接无法感知目标尺度与位置差异的问题让融合特征更适配多尺度目标检测任务。3. 采用**自适应门控加权融合机制**网络可自主学习不同模态的特征贡献度相比固定不变的拼接方式在光照变化、目标遮挡等复杂场景下具备更强的鲁棒性与泛化能力更适配实际跨模态检测需求。2.C2DFF-Net for Object Detection in Multimodal Remote Sensing Imagesimport torch import torch.nn as nn import torch.nn.functional as F class CPCA_ChannelAttention(nn.Module): # 此类无须修改接口原封不动保留 def __init__(self, input_channels, internal_neurons): super(CPCA_ChannelAttention, self).__init__() self.fc1 nn.Conv2d(in_channelsinput_channels, out_channelsinternal_neurons, kernel_size1, stride1, biasTrue) self.fc2 nn.Conv2d(in_channelsinternal_neurons, out_channelsinput_channels, kernel_size1, stride1, biasTrue) self.input_channels input_channels def forward(self, inputs): x1 F.adaptive_avg_pool2d(inputs, output_size(1, 1)) x1 self.fc1(x1) x1 F.relu(x1, inplaceTrue) x1 self.fc2(x1) x1 torch.sigmoid(x1) x2 F.adaptive_max_pool2d(inputs, output_size(1, 1)) x2 self.fc1(x2) x2 F.relu(x2, inplaceTrue) x2 self.fc2(x2) x2 torch.sigmoid(x2) x x1 x2 x x.view(-1, self.input_channels, 1, 1) return inputs * x #通道层的结果权重X与原输入相乘 class CPCA(nn.Module): # 接口修改使用 c1, c2 以适配 YOLO def __init__(self, c1, c2, channelAttention_reduce4): super().__init__() # 接口适配因为你的 forward 里用了 torch.cat通道数会翻倍 # 所以这里的 channels 必须是双路通道之和以防 conv1 报错 channels sum(c1) if isinstance(c1, list) else c1 * 2 out_channels c2 # 下面所有代码保持绝对原汁原味 self.conv1 nn.Conv2d(channels, channels, kernel_size(1, 1), padding0) self.ca CPCA_ChannelAttention(input_channelschannels, internal_neuronschannels // channelAttention_reduce) self.dconv5_5 nn.Conv2d(channels, channels, kernel_size5, padding2, groupschannels) self.dconv1_7 nn.Conv2d(channels, channels, kernel_size(1, 7), padding(0, 3), groupschannels)#groupschannels 表示每个输入通道独立进行卷积而不是将所有通道一起卷积。代表深度可分离 self.dconv7_1 nn.Conv2d(channels, channels, kernel_size(7, 1), padding(3, 0), groupschannels) self.dconv1_11 nn.Conv2d(channels, channels, kernel_size(1, 11), padding(0, 5), groupschannels) self.dconv11_1 nn.Conv2d(channels, channels, kernel_size(11, 1), padding(5, 0), groupschannels) self.dconv1_21 nn.Conv2d(channels, channels, kernel_size(1, 21), padding(0, 10), groupschannels) self.dconv21_1 nn.Conv2d(channels, channels, kernel_size(21, 1), padding(10, 0), groupschannels) self.conv2 nn.Conv2d(channels, out_channels, kernel_size(1, 1), padding0) self.act nn.GELU() def forward(self, x): #####原版########################################### inputs torch.cat((x[0], x[1]), dim1) #把输入的可见光、红外图像通道级联 # Global Perceptron 全局感知 #inputs x[0]-x[1] inputs self.conv1(inputs) inputs self.act(inputs) inputs self.ca(inputs) x_init self.dconv5_5(inputs) x_1 self.dconv1_7(x_init) x_1 self.dconv7_1(x_1) x_2 self.dconv1_11(x_init) x_2 self.dconv11_1(x_2) x_3 self.dconv1_21(x_init) x_3 self.dconv21_1(x_3) x x_1 x_2 x_3 x_init spatial_att self.conv1(x) out spatial_att * inputs out self.conv2(out) return out class CDFIM(nn.Module): # 接口修改使用 c1, c2 以适配 YOLO def __init__(self, c1, c2, channelAttention_reduce4): super().__init__() # 接口适配因为你的 forward 里用了减法 x[0]-x[1]通道数保持不变 # 所以这里的 channels 提取单路通道数即可 channels c1[0] if isinstance(c1, list) else c1 out_channels c2 # 下面所有代码保持绝对原汁原味 self.conv1 nn.Conv2d(channels, channels, kernel_size(1, 1), padding0) self.ca CPCA_ChannelAttention(input_channelschannels, internal_neuronschannels // channelAttention_reduce) self.dconv5_5 nn.Conv2d(channels, channels, kernel_size5, padding2, groupschannels) self.dconv1_7 nn.Conv2d(channels, channels, kernel_size(1, 7), padding(0, 3), groupschannels) self.dconv7_1 nn.Conv2d(channels, channels, kernel_size(7, 1), padding(3, 0), groupschannels) self.dconv1_11 nn.Conv2d(channels, channels, kernel_size(1, 11), padding(0, 5), groupschannels) self.dconv11_1 nn.Conv2d(channels, channels, kernel_size(11, 1), padding(5, 0), groupschannels) self.dconv1_21 nn.Conv2d(channels, channels, kernel_size(1, 21), padding(0, 10), groupschannels) self.dconv21_1 nn.Conv2d(channels, channels, kernel_size(21, 1), padding(10, 0), groupschannels) self.conv2 nn.Conv2d(channels, out_channels, kernel_size(1, 1), padding0) self.act nn.GELU() def forward(self, x): #####原版########################################### #inputs torch.cat((x[0], x[1]), dim1) #把输入的可见光、红外图像通道级联 # Global Perceptron 全局感知 #inputs x[0]-x[1] inputsx[0]-x[1] inputs self.conv1(inputs) inputs self.act(inputs) inputs self.ca(inputs) inputs0inputsx[0] inputs1 inputs x[1] inputsinputs0inputs1 x_init self.dconv5_5(inputs) x_1 self.dconv1_7(x_init) x_1 self.dconv7_1(x_1) x_2 self.dconv1_11(x_init) x_2 self.dconv11_1(x_2) x_3 self.dconv1_21(x_init) x_3 self.dconv21_1(x_3) x x_1 x_2 x_3 x_init spatial_att self.conv1(x) out spatial_att * inputs out self.conv2(out) return out该模块通过通道注意力与多感受野空间注意力的联合建模实现跨模态特征的深度增强与自适应加权相比简单拼接仅进行特征堆叠的方式能够有效筛选关键目标信息、抑制背景噪声显著提升融合特征的表达能力。模块采用多尺度深度可分离卷积构建空间感知结构可捕捉不同尺寸、不同形状目标的空间依赖关系解决了简单拼接无法感知目标空间结构与尺度差异的缺陷让融合特征更适配复杂场景下的目标检测任务。CDFIM 引入模态差异特征引导融合通过差异信息强化目标区域并实现双向特征增强相比简单拼接的无差别融合能够更高效地利用跨模态互补信息在光照变化、遮挡、低能见度等复杂环境下具备更强的鲁棒性与检测稳定性。3.A Cross-Modality Feature Adaptive Interaction Approach for RGB-Infrared Object Detection in Aerial Imageryimport torch import torch.nn as nn class CIFusion(nn.Module): 跨交互融合模块 (列表输出版) 完美适配原版 FeatureAdd。 输出格式为 [rgb_delta, ir_delta]分别对应 branch0 和 branch1 的残差补偿。 def __init__(self, c1, c2, r16, dimension1): super().__init__() # c1 是列表 [ch_rgb, ch_nir]提取单流通道数 self.c1_single_stream c1[0] if isinstance(c1, list) else c1 self.c_total_concat self.c1_single_stream * 2 self.avg_pool nn.AdaptiveAvgPool2d(1) # 防止通道数极小时 r 除以 0 导致报错 mid_channels max(1, self.c_total_concat // r) self.fc nn.Sequential( nn.Linear(self.c_total_concat, mid_channels, biasFalse), nn.ReLU(inplaceTrue), nn.Linear(mid_channels, self.c_total_concat, biasFalse), nn.Sigmoid(), ) def forward(self, x): # 1. 拼接双路输入特征 if isinstance(x, list): x_cat torch.cat(x, dim1) else: x_cat x b, _, _, _ x_cat.size() y self.avg_pool(x_cat).view(b, self.c_total_concat) y self.fc(y).view(b, self.c_total_concat, 1, 1) x1 x_cat * y # 2. 跨模态错位特征提取 (Cross-Modal Swap) # x1 的前半部分是 RGB 特征后半部分是 NIR 特征 # 为了实现错位互补RGB 需要 NIR 的特征NIR 需要 RGB 的特征 ir_feature_for_rgb x1[:, self.c1_single_stream:, ...] # 拿后半部分 (给 branch0) rgb_feature_for_ir x1[:, :self.c1_single_stream, ...] # 拿前半部分 (给 branch1) # 核心修改打包成列表返回 # 这样你的 FeatureAdd 里的 x[1][self.branch] 就能完美、精准地取走属于自己的那一半 return [ir_feature_for_rgb, rgb_feature_for_ir]CIFusion 模块通过自适应通道注意力机制实现跨模态特征的全局加权优化能够自动学习 RGB 与红外特征的重要性权重精准强化互补信息并抑制冗余噪声相较于简单拼接的无差别特征堆叠大幅提升了有效特征的聚合精度与表达能力。该模块创新采用跨模态错位交互策略将不同模态的关键特征进行互补传递使 RGB 特征获得红外的抗干扰信息、红外特征获得 RGB 的纹理细节信息突破了简单拼接仅能实现特征叠加、无法实现模态间深度交互的局限实现了真正意义上的跨模态信息增强。模块以残差补偿形式输出双向特征保持了模态独立性与检测框架的兼容性无需改变原有网络结构即可实现轻量化融合相比简单拼接带来的通道倍增问题有效降低了计算开销同时在复杂环境下具备更强的鲁棒性与检测稳定性。4.总结与反思三个跨模态融合模块均摒弃简单拼接的浅层特征堆叠方式通过通道注意力、空间注意力或自适应加权机制实现 RGB 与红外特征的深度交互。相比直接拼接这类结构能自主筛选关键信息、抑制背景干扰使融合特征更具判别性显著提升复杂场景下目标特征的表达能力。各模块均设计了针对性的跨模态信息交互方式DEA 实现双向模态加权增强CPCA 与 CDFIM 通过多尺度深度卷积捕捉空间结构CIFusion 采用错位互补实现特征传递。它们均能有效利用模态间互补优势解决拼接无法建模依赖关系的问题让小目标与遮挡目标检测更鲁棒。三类模块均保持轻量化与高兼容性可直接嵌入 YOLO 等检测框架在提升融合效果的同时不显著增加计算负担。与简单拼接导致通道剧增、信息冗余的问题不同这些结构通过自适应融合实现高效信息聚合更适合端侧部署与实际工程化应用。后续将进行更新以及进行二次创新发顶刊必备。。。敬请关注笔者整理双模态检测的专属论文资料免费分享给粉丝需要关注后领取。