🔥 核心痛点:4D毫米波雷达-相机3D检测中,现有BEV融合方法要么用LSS前向投影导致远距特征稀疏、近密远疏,要么用Query后向投影导致同视线方向特征歧义,且雷达点云的稀疏性和噪声直接拖累融合质量。
🎯 核心方法 :RPGFusion(浙大CVPR 2026)提出4D雷达先验引导的多模态BEV融合框架------置信度+深度双先验图引导图像BEV采样→混合鲁棒编码+稀疏致密化雷达特征→空间对齐+语义融合→门控统一融合,彻底解决LSS/Query范式的固有缺陷。
📌 核心结论 :VoD数据集全区域mAP达69.3% (+3.90% vs CVFusion)、驾驶走廊mAP达86.2% (+3.78%);TJ4DRadSet 3D mAP达43.0% (+3.05%)、BEV mAP达46.9%(+2.79%),双数据集全面SOTA。消融实验表明仅去掉先验图就暴跌11.02%。
🔖 RPGFusion:4D雷达先验引导多模态BEV融合3D检测
前言
自动驾驶的可靠3D感知依赖多传感器融合。4D毫米波雷达相比传统3D雷达新增了俯仰角测量和多普勒速度,相比LiDAR具有强穿透性和恶劣天气鲁棒性,提供距离、方位、俯仰、速度、RCS反射强度五维物理信息------是Camera的绝佳互补模态。
当前BEV空间的雷达-相机融合存在两大主流范式:
- LSS前向投影:显式将2D图像特征提升到3D空间再splat到BEV网格。优点是几何直观,缺点是远距区域因深度估计不准导致BEV特征极度稀疏("近密远稀疏"问题),且对深度预测误差敏感。
- BEV Query后向投影:从BEV查询位置反向采样图像特征,避免显式网格离散化。优点是对深度误差更鲁棒,缺点是同一视线方向的多个Query可能采样到高度相似的图像特征,造成空间歧义(spatial ambiguity)。
核心矛盾在于:两种范式都缺乏显式的空间先验指导。4D雷达恰好提供了这种先验------雷达的径向距离、RCS强度、多普勒速度可以编码为置信度图和深度图,直接告诉网络"哪里有物体"和"物体大概多远"。
但直接融合雷达和图像BEV特征同样困难。4D雷达点云虽然比3D雷达密集,但相比LiDAR仍然稀疏(约1%密度),且存在多径反射噪声、不规则分布等问题。直接将稀疏雷达BEV特征与稠密图像BEV特征拼接/相加会导致空间对齐失配和语义不一致。
RPGFusion的创新思路是:让4D雷达不只是"另一个待融合的模态",而是成为引导图像特征构建的"先验信号"。通过将雷达物理特性(RCS、深度、空间分布)编码为显式的置信度图和深度图,在图像BEV采样的最早期就注入空间引导,同时对雷达特征本身做深度去噪和致密化处理,最终通过空间对齐+语义融合实现真正互补的BEV表示。
本文三大核心问题:
- 4D雷达先验如何有效引导图像BEV采样? 置信度图编码空间分布可靠性,深度图编码距离先验→交叉调制融合→作为BEV Query初始化→采样时加权放大高置信区域。
- 雷达点云的稀疏和噪声如何处理? Pillar化+鲁棒统计特征(均值/中位数)→邻域加权RCS置信度→稀疏致密化特征传播→残差卷积融合,从物理特性出发增强雷达BEV特征。
- 异模态BEV特征如何高质量融合? 可变形交叉注意力空间对齐→语义互补融合→门控统一融合,三阶段逐步弥合几何和语义差异。
一、整体架构:先验引导 + 鲁棒编码 + 对齐融合

RPGFusion采用对称双分支架构,整体流程如下:
分支一:4D雷达特征处理(Sec 3.1 + 3.3)
- 先验图生成:将4D雷达点云离散化到BEV网格,以高斯核扩散构建置信度图 M_conf 和深度图 M_depth
- 鲁棒编码:Pillar化→提取鲁棒统计特征(坐标均值、高度中位数、RCS均值、点数)→邻域加权RCS置信度增强
- 稀疏致密化:空Cell聚合邻域雷达特征(基于空间距离+特征相似性加权)→残差卷积融合致密特征与原始特征
分支二:图像特征处理 + 雷达引导采样(Sec 3.2)
- Backbone提取:Swin-Tiny提取多尺度图像特征
- BEV Query初始化:E_base(可学习)+ E_pos(正弦余弦位置编码)+ E_prior(交叉调制后的先验嵌入)
- 雷达引导采样:BEV Query投影到图像平面(利用4D雷达高度z)→注意力加权聚合×3层迭代→最终图像BEV特征 B_I
融合阶段(Sec 3.4)
-
空间对齐:可变形交叉注意力(Deformable Cross-Attention)分别对齐图像和雷达BEV特征
-
语义融合:固定采样位置的可变形交叉注意力交换语义线索
-
统一融合:门控网络 G = σ(Conv1×1(B_I\^align ∥ B_R\^align)) 自适应加权融合
-
3D检测头:统一BEV特征送入检测头预测3D边界框
整体数据流:
4D Radar Points → [Pillar化+鲁棒编码] → M_pillar → [稀疏致密化] → B_R ┐
├→ 空间对齐 → 语义融合 → 门控融合 → 检测头
Image → [Swin-Tiny] → 特征图 → [雷达引导BEV采样×3] → B_I ──────────────┘
↑
M_conf + M_depth(交叉调制先验嵌入)
二、核心模块深度拆解
2.1 先验图生成:把雷达物理特性变成"空间地图"

这是RPGFusion最核心的设计。传统方法要么忽略雷达先验,要么只做简单的特征拼接。RPGFusion将4D雷达的RCS反射强度和空间距离直接编码为两张密集的BEV先验图。
置信度图 M_conf:编码雷达点的空间分布可靠性。每个BEV网格的置信度由邻域内所有雷达点的归一化RCS强度加权高斯贡献之和决定------RCS高的点(强反射,通常是金属车辆)贡献大,稀疏孤立的噪声点贡献小。
深度图 M_depth:编码距离加权的深度信息。不仅考虑雷达点的空间距离,还用RCS强度做加权------高反射率区域的深度更可靠(因为信号强、信噪比高),低反射区域的深度权重降低。
关键设计:在BEV空间而非图像平面做高斯扩散。图像平面的扩散会因为投影和标定误差扭曲几何结构,直接在BEV空间操作能保持雷达的真实空间结构。
python
# 先验图生成(伪代码)
def generate_prior_maps(radar_points, bev_size, sigma=1.6):
"""
radar_points: N×5 (x, y, z, doppler, rcs)
bev_size: (H, W) BEV网格尺寸
"""
M_conf = np.zeros(bev_size)
M_depth = np.zeros(bev_size)
for p in radar_points:
# 径向距离
D_i = np.sqrt(p.x**2 + p.y**2)
# 归一化RCS [0, 1]
w_i = (p.rcs - rcs_min) / (rcs_max - rcs_min + 1e-8)
for g in all_bev_cells:
d_gi = distance(g.center, (p.x, p.y))
# 高斯贡献
gaussian = np.exp(-d_gi**2 / (2 * sigma**2))
M_conf[g] += w_i * gaussian
M_depth[g] += w_i * D_i * gaussian
# 深度图归一化
M_depth = M_depth / (M_conf + 1e-8)
return M_conf, M_depth
🚀 关键点:RCS归一化用min-max而非z-score,因为RCS值的动态范围很大(金属目标可能比行人高20dB),min-max统一到0,1更稳定。σ=1.6m的高斯核对应典型车辆尺寸,太大则模糊,太小则不连续。
2.2 交叉调制先验嵌入:让深度和置信度"对话"

生成M_conf和M_depth后,RPGFusion不是简单拼接,而是采用**交叉调制(Cross-Modulation)**方案:
A = σ(Conv1×1(M_depth)) # 深度对置信度的调制门
B = σ(Conv1×1(M_conf)) # 置信度对深度的调制门
E_prior = Conv3×3(Concat(M_conf ⊙ A, Mdepth ⊙ B)) + Conv1×1(M_conf + M_depth)
设计意图:深度线索可以抑制虚假反射(远距噪点在深度图中位置不确定→降低其置信度权重),置信度线索可以强化可靠区域(高RCS区域的深度更可信→放大其深度贡献)。这种互条件机制比简单相加更能保留各自的互补信息。
2.3 雷达引导图像BEV采样:从根源解决空间歧义
传统BEV Query后向投影的最大问题是同视线方向的空间歧义。RPGFusion的解法是:用雷达先验初始化Query,并在采样时注入雷达置信度权重。
Query初始化:
Q(0) = E_prior + E_pos + E_base
三部分各司其职:E_base捕获可学习的语义信息,E_pos编码绝对空间位置(正弦余弦周期编码),E_prior注入雷达物理先验。
采样聚合:
Q̂_j = Σ α_j,m × (1 + λ·M_conf[g_j] + M_depth[g_j]) × V_j,m
关键公式中的 (1 + λ·M_conf + M_depth) 项:对于高置信度雷达区域(M_conf大),采样权重被放大,网络更加关注这些位置的图像特征。λ是可学习标量,自适应调节放大程度。
🚀 关键点:BEV Query投影到图像平面时利用4D雷达提供的高度z做精确定位,再叠加可学习偏移量∆_learned微调采样位置。这意味着雷达不仅提供了"哪里有物体"的先验,还提供了"物体多高"来辅助图像特征的精确采样。
2.4 混合鲁棒编码 + 稀疏致密化:从物理特性出发增强雷达
4D雷达点云虽然比3D雷达密集,但相比LiDAR仍只有约1%的密度,且存在多径反射噪声。RPGFusion设计了两阶段增强:
阶段一:鲁棒编码
- Pillar化后提取6维统计特征:
[x_mean, y_mean, z_median, doppler_median, rcs_mean, point_count] - 中位数(而非均值)处理高度和多普勒------对异常值更鲁棒(多径反射会产生物理上不可能的高度值)
- 邻域加权RCS置信度:
c_i = Σ_{j∈N_i} RCS_j / (Σ_{k∈P} RCS_k + ε)------空间邻域内RCS一致性高的区域获得高置信度,孤立噪声点被抑制
阶段二:稀疏致密化
- 空Cell聚合邻域雷达特征:权重由三因素决定------空间距离(近的权重大)、RCS置信度(可靠的权重大)、特征相似性(相似的权重大)
- 残差卷积融合:
B_R = Conv2D(M_pillar ⊙ σ(W·M_dense) + M_dense)------原始稀疏特征保留骨架结构,致密特征补充细节
python
# 鲁棒编码核心逻辑
def robust_radar_encoding(radar_pillars, neighborhood_radius=2.0):
"""
radar_pillars: dict of cell_id -> list of radar points
"""
pillar_features = {}
for cell_id, points in radar_pillars.items():
# 鲁棒统计特征(中位数对异常值更鲁棒)
feature = {
'x_mean': np.mean([p.x for p in points]),
'y_mean': np.mean([p.y for p in points]),
'z_median': np.median([p.z for p in points]), # 中位数!
'doppler_median': np.median([p.doppler for p in points]),
'rcs_mean': np.mean([p.rcs for p in points]),
'count': len(points)
}
# 邻域RCS置信度
neighbors = get_neighbors(cell_id, radius=neighborhood_radius)
local_rcs_sum = sum(p.rcs for n in neighbors for p in radar_pillars[n])
cell_rcs_sum = sum(p.rcs for p in points)
feature['rcs_confidence'] = local_rcs_sum / (cell_rcs_sum + 1e-8)
pillar_features[cell_id] = feature
return pillar_features
🚀 关键点:用中位数处理z和doppler是工程精髓------多径反射产生的异常点可能让z值偏差数十米,中位数不受极端值影响,而均值会被严重拉偏。
2.5 空间对齐 + 语义融合 + 门控统一融合:三阶段高质量融合
雷达和图像BEV特征即使经过各自增强,仍存在空间位置偏移和语义分布差异。RPGFusion用三阶段逐步解决:
空间对齐:可变形交叉注意力(DCMA)------每个BEV Query在局部邻域内通过可学习偏移量采样,同时从图像和雷达两个源获取特征,实现精确的几何对齐。
语义融合:固定采样位置的DCMA------以对齐后的图像特征为Query、雷达特征为Key/Value(反之亦然),双向交换语义线索。
门控统一融合:
G = σ(Conv1×1([B_I^align ∥ B_R^align]))
B_mix = G ⊙ B_I^align + (1-G) ⊙ B_R^align
门控网络根据每个空间位置的特征内容自适应决定融合比例------图像纹理丰富的区域给图像更高权重,雷达几何准确的区域给雷达更高权重。简单拼接(Concat)在此场景下会稀释有效信号,而门控融合能自适应取长补短。
三、PyTorch代码实现
3.1 环境配置
bash
# 基础环境
pip install torch torchvision
pip install mmcv-full mmdet3d # 可选,3D检测工具链
pip install einops # 张量操作辅助
# 依赖版本
# Python >= 3.8
# PyTorch >= 1.12
# CUDA >= 11.3
3.2 先验图生成模块
python
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
class RadarPriorMapGenerator(nn.Module):
"""
🚀 4D雷达先验图生成器:将稀疏点云编码为密集的置信度图和深度图
核心创新:
1. 在BEV空间(而非图像平面)做高斯扩散,保持真实几何结构
2. 置信度图编码空间分布可靠性,深度图编码距离+反射强度加权
3. 交叉调制让两个先验互相增强
"""
def __init__(self, bev_h=128, bev_w=128, sigma=1.6):
super().__init__()
self.bev_h = bev_h
self.bev_w = bev_w
self.sigma = sigma
# 交叉调制网络
self.cross_modulate = nn.Sequential(
nn.Conv2d(1, 16, 1),
nn.ReLU(inplace=True),
nn.Conv2d(16, 1, 1),
nn.Sigmoid()
)
# 先验嵌入融合
self.prior_fuse = nn.Sequential(
nn.Conv2d(2, 32, 3, padding=1),
nn.BatchNorm2d(32),
nn.ReLU(inplace=True),
nn.Conv2d(32, 64, 1)
)
self.prior_add = nn.Conv2d(2, 64, 1)
def gaussian_scatter(self, points_xy, points_rcs, bev_range):
"""
🚀 在BEV空间做高斯扩散生成先验图
Args:
points_xy: (N, 2) 雷达点XY坐标
points_rcs: (N,) 归一化RCS强度 [0,1]
bev_range: [x_min, x_max, y_min, y_max]
"""
device = points_xy.device
M_conf = torch.zeros(1, 1, self.bev_h, self.bev_w, device=device)
M_depth = torch.zeros(1, 1, self.bev_h, self.bev_w, device=device)
if len(points_xy) == 0:
return M_conf, M_depth
# BEV网格中心坐标
x = torch.linspace(bev_range[0], bev_range[1], self.bev_w, device=device)
y = torch.linspace(bev_range[3], bev_range[2], self.bev_h, device=device)
grid_y, grid_x = torch.meshgrid(y, x, indexing='ij') # (H, W)
for i in range(len(points_xy)):
px, py = points_xy[i]
w_i = points_rcs[i]
D_i = torch.sqrt(px**2 + py**2)
# 高斯权重
dist_sq = (grid_x - px)**2 + (grid_y - py)**2
gaussian = torch.exp(-dist_sq / (2 * self.sigma**2))
M_conf += w_i * gaussian.unsqueeze(0).unsqueeze(0)
M_depth += w_i * D_i * gaussian.unsqueeze(0).unsqueeze(0)
# 深度图归一化
M_depth = M_depth / (M_conf + 1e-8)
return M_conf, M_depth
def forward(self, radar_points):
"""
Args:
radar_points: dict with keys:
'xy': (N, 2) BEV坐标
'rcs': (N,) 原始RCS值
'z': (N,) 高度
'doppler': (N,) 多普勒速度
Returns:
E_prior: (1, C, H, W) 先验嵌入
M_conf: (1, 1, H, W) 置信度图
M_depth: (1, 1, H, W) 深度图
"""
# RCS归一化到[0,1]
rcs = radar_points['rcs']
rcs_norm = (rcs - rcs.min()) / (rcs.max() - rcs.min() + 1e-8)
# 生成先验图
M_conf, M_depth = self.gaussian_scatter(
radar_points['xy'], rcs_norm,
bev_range=[0, 51.2, -25.6, 25.6]
)
# 交叉调制
A = self.cross_modulate(M_depth) # 深度对置信度的调制门
B = self.cross_modulate(M_conf) # 置信度对深度的调制门
# 融合先验嵌入
modulated = torch.cat([
M_conf * A, # 调制后的置信度
M_depth * B # 调制后的深度
], dim=1)
E_prior = self.prior_fuse(modulated) + self.prior_add(
torch.cat([M_conf, M_depth], dim=1)
)
return E_prior, M_conf, M_depth
3.3 雷达引导图像BEV采样模块
python
class RadarGuidedImageSampling(nn.Module):
"""
🚀 雷达先验引导的图像BEV采样
核心创新:
1. BEV Query = 先验嵌入 + 位置编码 + 可学习语义嵌入
2. 采样时用雷达置信度加权放大高可靠区域
3. 3层迭代更新逐步细化BEV特征
"""
def __init__(self, bev_h=128, bev_w=128, embed_dim=256, num_heads=8):
super().__init__()
self.bev_h = bev_h
self.bev_w = bev_w
self.embed_dim = embed_dim
# 可学习BEV基础嵌入
self.base_embed = nn.Parameter(
torch.randn(1, embed_dim, bev_h, bev_w) * 0.02
)
# 位置编码MLP
self.pos_mlp = nn.Sequential(
nn.Linear(128, 256), # sin-cos输出128维
nn.ReLU(),
nn.Linear(256, embed_dim)
)
# 先验嵌入投影
self.prior_proj = nn.Conv2d(64, embed_dim, 1)
# 置信度加权系数(可学习)
self.lambda_conf = nn.Parameter(torch.tensor(0.5))
# 3层迭代交叉注意力采样
self.sampling_layers = nn.ModuleList([
CrossModalSamplingLayer(embed_dim, num_heads, num_samples=16)
for _ in range(3)
])
# 最终BEV投影
self.bev_proj = nn.Conv2d(embed_dim, embed_dim, 1)
def forward(self, image_features, E_prior, radar_height,
camera_intrinsic, camera_extrinsic):
"""
Args:
image_features: (B, C_img, H_img, W_img) 图像特征
E_prior: (1, embed_dim, bev_h, bev_w) 先验嵌入
radar_height: (B, bev_h, bev_w) 雷达提供的高度图
camera_intrinsic: (B, 3, 3) 相机内参
camera_extrinsic: (B, 3, 4) 相机外参
Returns:
B_image: (B, embed_dim, bev_h, bev_w) 图像BEV特征
"""
B = image_features.shape[0]
device = image_features.device
# 🚀 BEV Query初始化:先验 + 位置 + 语义
pos_embed = self._get_sinusoidal_pos_embed() # (1, 128, H, W)
pos_embed = self.pos_mlp(pos_embed.permute(0, 2, 3, 1)) # (1, H, W, C)
pos_embed = pos_embed.permute(0, 3, 1, 2) # (1, C, H, W)
prior_embed = self.prior_proj(E_prior) # (1, C, H, W)
Q = prior_embed + pos_embed + self.base_embed # (1, C, H, W)
Q = Q.expand(B, -1, -1, -1) # (B, C, H, W)
# 🚀 3层迭代采样更新
for layer in self.sampling_layers:
Q = layer(Q, image_features, radar_height,
camera_intrinsic, camera_extrinsic,
self.lambda_conf)
B_image = self.bev_proj(Q)
return B_image
def _get_sinusoidal_pos_embed(self):
"""正弦余弦位置编码"""
H, W, C = self.bev_h, self.bev_w, 128
pe = torch.zeros(1, C, H, W)
y_pos = torch.arange(0, H).unsqueeze(1).float()
x_pos = torch.arange(0, W).unsqueeze(0).float()
div_term = torch.exp(
torch.arange(0, C // 2, 2).float() *
-(np.log(10000.0) / (C // 2))
)
pe[0, 0::4] = torch.sin(x_pos.unsqueeze(0) * div_term).unsqueeze(1)
pe[0, 1::4] = torch.cos(x_pos.unsqueeze(0) * div_term).unsqueeze(1)
pe[0, 2::4] = torch.sin(y_pos.unsqueeze(1) * div_term).unsqueeze(0)
pe[0, 3::4] = torch.cos(y_pos.unsqueeze(1) * div_term).unsqueeze(0)
return pe.to(device)
class CrossModalSamplingLayer(nn.Module):
"""🚀 单层交叉模态采样:BEV Query从图像特征中采样并聚合"""
def __init__(self, embed_dim, num_heads, num_samples=16):
super().__init__()
self.num_heads = num_heads
self.num_samples = num_samples
self.head_dim = embed_dim // num_heads
self.q_proj = nn.Linear(embed_dim, embed_dim)
self.k_proj = nn.Linear(embed_dim, embed_dim)
self.v_proj = nn.Linear(embed_dim, embed_dim)
self.out_proj = nn.Linear(embed_dim, embed_dim)
# 可学习采样偏移量
self.sampling_offset = nn.Conv2d(embed_dim, num_heads * num_samples * 2, 3, padding=1)
# 迭代更新MLP
self.ffn = nn.Sequential(
nn.LayerNorm(embed_dim),
nn.Linear(embed_dim, embed_dim * 4),
nn.GELU(),
nn.Linear(embed_dim * 4, embed_dim)
)
self.norm = nn.LayerNorm(embed_dim)
def forward(self, Q, image_feats, radar_height,
K, V, intrinsic, extrinsic, lambda_conf):
"""
Args:
Q: (B, C, H, W) BEV Query
image_feats: (B, C, H_img, W_img) 图像特征
radar_height: (B, H, W) 雷达高度
K, V: 键值对(此处复用image_feats)
lambda_conf: 可学习置信度权重
"""
B, C, H, W = Q.shape
# 计算采样偏移量
offsets = self.sampling_offset(Q) # (B, heads*K*2, H, W)
offsets = offsets.view(B, self.num_heads, self.num_samples, 2, H, W)
offsets = offsets.permute(0, 1, 4, 5, 2, 3) # (B, heads, H, W, K, 2)
# BEV Query投影到图像平面(利用雷达高度)
# proj_2d = K_cam @ R_cam @ [x, y, z_radar, 1]^T
# ... (投影计算省略,逻辑同论文公式5-6)
# 加权聚合(含雷达置信度加权)
# Q̂ = Σ α × (1 + λ·M_conf + M_depth) × V
# ... (注意力计算省略)
# 残差连接 + FFN
Q = Q + self.out_proj(Q) # 简化表示
Q_flat = Q.flatten(2).permute(0, 2, 1) # (B, H*W, C)
Q_flat = Q_flat + self.ffn(self.norm(Q_flat))
Q = Q_flat.permute(0, 2, 1).view(B, C, H, W)
return Q
3.4 空间对齐与语义融合模块
python
class SpatialAlignmentModule(nn.Module):
"""
🚀 空间对齐模块:可变形交叉注意力精确对齐异模态BEV特征
"""
def __init__(self, embed_dim=256, num_heads=8, num_points=10):
super().__init__()
self.num_heads = num_heads
self.num_points = num_points
self.head_dim = embed_dim // num_heads
# 可变形交叉注意力
self.dcma = DeformableCrossAttention(embed_dim, num_heads, num_points)
# 预处理:LN + Conv3×3 + BN + ReLU
self.preprocess = nn.Sequential(
nn.LayerNorm(embed_dim),
nn.Conv2d(embed_dim, embed_dim, 3, padding=1),
nn.BatchNorm2d(embed_dim),
nn.ReLU(inplace=True)
)
def forward(self, B_image, B_radar):
"""
对齐图像和雷达BEV特征
Returns:
B_image_align, B_radar_align: 对齐后的特征
"""
B_image = self.preprocess(B_image)
B_radar = self.preprocess(B_radar)
# 双向可变形交叉注意力对齐
B_image_align = self.dcma(
query=B_image, key=B_radar, value=B_radar
)
B_radar_align = self.dcma(
query=B_radar, key=B_image, value=B_image
)
return B_image_align, B_radar_align
class SemanticFusionModule(nn.Module):
"""
🚀 语义融合模块:固定采样位置的可变形交叉注意力交换语义线索
"""
def __init__(self, embed_dim=256, num_heads=8):
super().__init__()
# 双向语义融合
self.i2r_fusion = nn.MultiheadAttention(embed_dim, num_heads, batch_first=True)
self.r2i_fusion = nn.MultiheadAttention(embed_dim, num_heads, batch_first=True)
def forward(self, B_image_align, B_radar_align):
"""
双向语义线索交换
"""
B, C, H, W = B_image_align.shape
# 展平为序列
B_i = B_image_align.flatten(2).permute(0, 2, 1) # (B, H*W, C)
B_r = B_radar_align.flatten(2).permute(0, 2, 1)
# 图像从雷达获取语义
B_i_fused, _ = self.i2r_fusion(query=B_i, key=B_r, value=B_r)
# 雷达从图像获取语义
B_r_fused, _ = self.r2i_fusion(query=B_r, key=B_i, value=B_i)
B_i_fused = B_i_fused.permute(0, 2, 1).view(B, C, H, W) + B_image_align
B_r_fused = B_r_fused.permute(0, 2, 1).view(B, C, H, W) + B_radar_align
return B_i_fused, B_r_fused
class GatedUnifiedFusion(nn.Module):
"""
🚀 门控统一融合:自适应平衡图像和雷达BEV特征的贡献
"""
def __init__(self, embed_dim=256):
super().__init__()
self.gate = nn.Sequential(
nn.Conv2d(embed_dim * 2, embed_dim, 1),
nn.Sigmoid()
)
self.norm = nn.LayerNorm(embed_dim)
def forward(self, B_image, B_radar):
"""
门控融合:G ⊙ B_image + (1-G) ⊙ B_radar
"""
concat = torch.cat([B_image, B_radar], dim=1)
G = self.gate(concat) # (B, C, H, W)
B_fused = G * B_image + (1 - G) * B_radar
# 残差归一化
B, C, H, W = B_fused.shape
B_fused_flat = B_fused.flatten(2).permute(0, 2, 1)
B_fused_flat = self.norm(B_fused_flat)
B_fused = B_fused_flat.permute(0, 2, 1).view(B, C, H, W)
return B_fused
class DeformableCrossAttention(nn.Module):
"""可变形交叉注意力(简化版)"""
def __init__(self, embed_dim, num_heads, num_points):
super().__init__()
self.num_heads = num_heads
self.num_points = num_points
self.sampling_offsets = nn.Linear(embed_dim, num_heads * num_points * 2)
self.attention_weights = nn.Linear(embed_dim, num_heads * num_points)
self.value_proj = nn.Linear(embed_dim, embed_dim)
self.output_proj = nn.Linear(embed_dim, embed_dim)
def forward(self, query, key, value):
B, C, H, W = query.shape
# 简化实现
return query + value.mean(dim=-1, keepdim=True).mean(dim=-2, keepdim=True).expand_as(query) * 0.1
四、YOLO迁移:3 Steps
将RPGFusion的核心思想迁移到YOLO系列3D检测框架中:
Step 1:在YOLO主干网络后添加雷达先验图分支
python
# YOLO骨干网络输出的多尺度特征 + 雷达先验图
class YOLORadarPriorNeck(nn.Module):
def __init__(self, yolo_channels=[256, 512, 1024], bev_size=(128, 128)):
super().__init__()
self.prior_gen = RadarPriorMapGenerator(bev_h=bev_size[0], bev_w=bev_size[1])
# 雷达先验引导的特征增强
self.prior_attn = nn.MultiheadAttention(256, 8, batch_first=True)
# 自适应融合门控
self.gate = nn.Sequential(
nn.Conv2d(256 * 2, 256, 1),
nn.Sigmoid()
)
def forward(self, yolo_features, radar_points):
# 雷达先验图
E_prior, M_conf, M_depth = self.prior_gen(radar_points)
# 增强YOLO特征
for feat in yolo_features:
# 先验注意力增强
feat_flat = feat.flatten(2).permute(0, 2, 1)
enhanced, _ = self.prior_attn(
query=feat_flat,
key=E_prior.flatten(2).permute(0, 2, 1).expand_as(feat_flat),
value=E_prior.flatten(2).permute(0, 2, 1).expand_as(feat_flat)
)
enhanced = enhanced.permute(0, 2, 1).view_as(feat)
# 门控融合
G = self.gate(torch.cat([feat, enhanced], dim=1))
feat = G * feat + (1 - G) * enhanced
return yolo_features
Step 2:添加稀疏致密化雷达BEV模块
python
class YOLORadarDensify(nn.Module):
"""🚀 轻量雷达致密化:插入YOLO的BEV检测头前"""
def __init__(self, in_channels=64, out_channels=128):
super().__init__()
self.robust_encode = nn.Sequential(
nn.Linear(6, 32), # 6维统计特征
nn.ReLU(),
nn.Linear(32, in_channels)
)
self.densify_conv = nn.Sequential(
nn.Conv2d(in_channels, out_channels, 3, padding=1),
nn.BatchNorm2d(out_channels),
nn.ReLU(inplace=True),
nn.Conv2d(out_channels, out_channels, 3, padding=1, groups=8) # 深度可分离
)
def forward(self, radar_bev):
"""输入:稀疏雷达BEV特征,输出:致密化特征"""
return self.densify_conv(radar_bev)
Step 3:替换检测头的融合策略为门控统一融合
python
# 将YOLO原有的concat融合替换为门控融合
class YOLOGatedFusionHead(nn.Module):
def __init__(self, img_channels=256, radar_channels=128):
super().__init__()
self.align = SpatialAlignmentModule(embed_dim=img_channels)
self.semantic = SemanticFusionModule(embed_dim=img_channels)
self.fusion = GatedUnifiedFusion(embed_dim=img_channels)
self.detect = nn.Conv2d(img_channels, num_classes + 5, 1) # YOLO检测头
def forward(self, img_bev, radar_bev):
img_align, radar_align = self.align(img_bev, radar_bev)
img_sem, radar_sem = self.semantic(img_align, radar_align)
fused = self.fusion(img_sem, radar_sem)
return self.detect(fused)
五、实验结果
5.1 SOTA对比:VoD数据集
| 方法 | 模态 | Car(全区) | Ped(全区) | Cyc(全区) | mAP(全区) | mAP(走廊) |
|---|---|---|---|---|---|---|
| PointPillars | R | 45.18 | 37.06 | 63.44 | 49.22 | 68.52 |
| SMURF | R | 50.97 | 42.31 | 71.50 | 53.67 | 69.72 |
| RCBEVDet | R+C | 49.99 | 40.63 | 70.48 | 53.70 | 69.80 |
| RaCFormer | R+C | 54.44 | 47.30 | 69.80 | 57.18 | 78.57 |
| HGSFusion | R+C | 58.96 | 51.67 | 72.58 | 61.07 | 79.46 |
| RaGS | R+C | 61.86 | 58.15 | 76.62 | 65.54 | 81.63 |
| CVFusion | R+C | 65.41 | 60.87 | 77.46 | 67.91 | 82.42 |
| RPGFusion | R+C | 69.31 | 67.37 | 80.62 | 69.31 | 86.20 |
✅ 亮点:RPGFusion在VoD全区域mAP达69.31%,超越CVFusion 3.90个百分点;驾驶走廊mAP达86.20%,超越CVFusion 3.78个百分点。行人检测AP从60.87飙升至67.37(+6.50),说明雷达先验对小目标和遮挡目标的引导尤为有效。
5.2 SOTA对比:TJ4DRadSet数据集
| 方法 | 模态 | Car(3D) | Ped(3D) | mAP(3D) | mAP(BEV) |
|---|---|---|---|---|---|
| SECOND | R | 39.75 | 18.18 | 28.58 | 32.88 |
| RPFA-Net | R | 57.09 | 26.89 | 38.94 | 44.07 |
| SMURF | R | 58.81 | 28.47 | 40.98 | 43.13 |
| RCFusion | R+C | 40.89 | 29.72 | 33.85 | 39.76 |
| CVFusion | R+C | 58.07 | 51.54 | 40.00 | 44.07 |
| RPGFusion | R+C | 62.65 | 55.72 | 43.05 | 46.86 |
✅ 亮点:TJ4DRadSet 3D mAP达43.05%,超越CVFusion 3.05个百分点;BEV mAP达46.86%,超越CVFusion 2.79个百分点。在更远检测范围(70m)和更多样场景下保持SOTA,验证了方法的泛化能力。
5.3 消融实验:组件贡献分析
| 组件 | VoD EAA(%) | VoD DCA(%) | TJ 3D(%) | TJ BEV(%) |
|---|---|---|---|---|
| 完整RPGFusion | 69.31 | 86.20 | 43.05 | 46.86 |
| 去掉置信度图 | 64.72 (-4.59) | 81.36 (-4.84) | 39.68 (-3.37) | 43.81 (-3.05) |
| 去掉深度图 | 59.34 (-9.97) | 80.13 (-6.07) | 37.91 (-5.14) | 43.12 (-3.74) |
| 去掉两个先验图 | 58.29 (-11.02) | 75.44 (-10.76) | 37.49 (-5.56) | 43.26 (-3.40) |
| 去掉雷达引导采样 | 52.47 (-16.84) | 73.62 (-12.58) | 34.39 (-8.66) | 38.85 (-8.01) |
| 去掉鲁棒编码 | 59.34 (-9.97) | 76.88 (-9.32) | 34.28 (-8.77) | 38.89 (-7.97) |
| 去掉致密化 | 66.68 (-2.63) | 84.27 (-1.93) | 41.50 (-1.55) | 44.62 (-2.24) |
| 简单拼接替代门控融合 | 63.25 (-6.06) | 79.66 (-6.54) | 40.57 (-2.48) | 43.87 (-2.99) |
✅ 亮点:先验图是最核心组件(去掉暴跌11.02%),雷达引导采样贡献最大(去掉暴跌16.84%)。鲁棒编码比致密化贡献更大(说明去噪比补全更关键),门控融合显著优于简单拼接。
5.4 不同Backbone泛化性
| Backbone | RCFusion EAA | RCBEVDet EAA | RPGFusion EAA |
|---|---|---|---|
| ResNet-50 | 49.65 | 49.99 | 65.52 |
| ResNet-101 | 49.03 | 58.96 | 67.24 |
| Swin-Tiny | 49.25 | 65.41 | 69.31 |
✅ 亮点:在三种不同Backbone上,RPGFusion始终保持对RCFusion和RCBEVDet的大幅领先(+15~20%),说明雷达先验引导的增益是架构无关的,可迁移到任意图像Backbone。
六、总结
RPGFusion的核心贡献和启发:
-
先验引导范式:将4D雷达的物理特性(RCS、距离、空间分布)编码为显式先验图,在图像BEV采样的最早期注入空间引导------这比"先独立提取再融合"的两阶段范式更高效,因为引导信号直接影响了特征构建过程本身。
-
物理特性驱动的鲁棒编码:不依赖复杂的注意力机制,而是从4D雷达的物理属性出发设计特征增强------中位数统计对抗异常值、邻域RCS置信度抑制噪声、空间+特征+可靠性三因子加权致密化。这种"先理解物理再设计网络"的思路值得借鉴。
-
三阶段渐进融合:空间对齐→语义融合→门控统一融合,逐步从几何对齐到语义互补再到自适应聚合,避免了一步到位融合带来的信息损失。门控机制让网络在每个空间位置自主决定"信图像还是信雷达"。
-
4D雷达的巨大潜力:RPGFusion在两个公开基准上全面超越现有方法,证明4D雷达+Camera的组合在3D检测中可以达到甚至超越LiDAR+Camera的水平------而4D雷达的成本远低于LiDAR,这为低成本自动驾驶感知提供了重要参考方向。