#UniAD

UniAD是围绕查询设计的,它的感知、预测、规划任务都使用交叉注意力来将前置任务的查询转换为当前任务的查询。每个任务的查询以及这些查询的组合,都用长度为256的向量表征。最初的表征(BEV元素)通过多个Transformer Decoder,每个Decoder的输出有不同任务的监督数据,这些任务引导了中间表示(dim=256的向量)的演化。

在这个过程中,UniAD对表征做了很多组合和变换,引入了冗余的参数。(与之相比,英伟达的ParaDrive则直接从BEV并行训练多任务,取得了更好的效果。)中间表征在演化过程中有多个名字,如下表中形状中有x256的变量,作为每个模块的输入和输出。在开始关注每个模块的代码前,需要牢记下表中每个查询变量的含义和形状。

如果大家对端到端自动驾驶技术栈还不是很熟悉,可以翻一翻我们前面的端到端技术栈汇总!

对于感知部分,由于已经有很多文章对目标检测、跟踪和建图的论文和代码做过解读,因此我们不再重复。在这篇文章中,我们只对运动预测、占用预测和规划器进行解读。

运动预测模块

这个模块的结构可以在配置文件base_e2e.py中查看。我们忽略了参数部分,只关注模型的前向传播链。我们把写在模块代码的__init__中而不在配置文件中的部分也填充进去,构成完整的前向传播链:

# 配置文件中的前向传播链

motion_head=dict(
        type='MotionHead',
        
        transformerlayers=dict(
            type='MotionTransformerDecoder',

            transformerlayers=dict(
                type='MotionTransformerAttentionLayer',

                attn_cfgs=[
                    dict(
                        type='MotionDeformableAttention',
                    ),
                ],

                operation_order=('cross_attn', 'norm', 'ffn', 'norm')),
        ),
    ),

# 完整的前向传播链

motion_head=dict(
        type='MotionHead',
        
        transformerlayers=dict(
            // 解码器
            type='MotionTransformerDecoder',

            // 对象-目标交互
            intention_interaction_layers = IntentionInteraction()
            // 对象-对象交互
            track_agent_interaction_layers = nn.ModuleList(
            [TrackAgentInteraction() for i in range(self.num_layers)])
            // 对象-地图交互
            map_interaction_layers = nn.ModuleList(
            [MapInteraction() for i in range(self.num_layers)])
            // 对象-目标交互
            bev_interaction_layers = nn.ModuleList(
            [build_transformer_layer(transformerlayers) for i in range(self.num_layers)])

            // 一些对查询进行转换的MLP层
            static_dynamic_fuser = nn.Sequential(
                nn.Linear(self.embed_dims*2, self.embed_dims*2),
                nn.ReLU(),
                nn.Linear(self.embed_dims*2, self.embed_dims),
            )
            dynamic_embed_fuser = nn.Sequential(
                nn.Linear(self.embed_dims*3, self.embed_dims*2),
                nn.ReLU(),
                nn.Linear(self.embed_dims*2, self.embed_dims),
            )
            in_query_fuser = nn.Sequential(
                nn.Linear(self.embed_dims*2, self.embed_dims*2),
                nn.ReLU(),
                nn.Linear(self.embed_dims*2, self.embed_dims),
            )
            out_query_fuser = nn.Sequential(
                nn.Linear(self.embed_dims*4, self.embed_dims*2),
                nn.ReLU(),
                nn.Linear(self.embed_dims*2, self.embed_dims),
            )

            
            transformerlayers=dict(
                // 对象-目标交互
                type='MotionTransformerAttentionLayer',

                attn_cfgs=[
                    dict(
                        type='MotionDeformableAttention',
                    ),
                ],

                operation_order=('cross_attn', 'norm', 'ffn', 'norm')
            ),
        ),
    ),

我们按照UniAD、MotionHead、MotionTransformerDecoder的顺序看前向传播链的forward函数。其中:

  1. UniAD的forward只是简单地串联起了五个模块
  2. MotionHead相当于MotionTransformerDecoder的预处理和后处理,它做了锚点和轨迹首尾点的嵌入,作为MotionTransformerDecoder的输入,之后又将MotionTransformerDecoder的输出查询转换为轨迹点列
  3. MotionTransformerDecoder是最核心的部分,它将锚点和轨迹的嵌入相加构造输入查询,通过三个交叉注意力模块吸收上游模块的查询的信息,再将它们的输出串联并压缩,得到输出查询。

我们对代码中的关键部分进行注释,并省略相对次要的部分。

MotionHead:

这段代码主要实现了以下功能:

  1. 构造并归一化代理级别和场景级别的锚点。
  2. 使用嵌入层将锚点的位置信息转换为嵌入向量。
  3. 通过MotionFormer模型进行前向传播,获取中间状态和参考轨迹。
  4. 计算每个级别的轨迹分数和轨迹,并应用双变量高斯激活。
  5. 构造输出字典,包含轨迹分数、预测轨迹、轨迹查询的有效性掩码等信息,并返回
class MotionHead(BaseMotionHead):

    def forward(self, 
                bev_embed, 
                track_query, 
                lane_query, 
                lane_query_pos, 
                track_bbox_results):
        """
        该函数执行模型的前向传播,用于基于鸟瞰图(BEV)嵌入、轨迹查询、车道查询和轨迹边界框结果进行运动预测。

        参数:

        bev_embed (torch.Tensor):形状为 (h*w, B, D) 的张量,表示鸟瞰图嵌入。
        track_query (torch.Tensor):形状为 (B, num_dec, A_track, D) 的张量,表示轨迹查询。
        lane_query (torch.Tensor):形状为 (N, M_thing, D) 的张量,表示车道查询。
        lane_query_pos (torch.Tensor):形状为 (N, M_thing, D) 的张量,表示车道查询的位置。
        track_bbox_results (List[torch.Tensor]):包含批次中每个图像的跟踪边界框结果的张量列表。
        返回值:

        dict:包含以下键和值的字典:
        'all_traj_scores':形状为 (num_levels, B, A_track, num_points) 的张量,包含每个级别的轨迹分数。
        'all_traj_preds':形状为 (num_levels, B, A_track, num_points, num_future_steps, 2) 的张量,包含每个级别的预测轨迹。
        'valid_traj_masks':形状为 (B, A_track) 的张量,指示轨迹掩码的有效性。
        'traj_query':包含轨迹查询中间状态的张量。
        'track_query':包含输入轨迹查询的张量。s
        'track_query_pos':包含轨迹查询位置嵌入的张量。
        """
        
        ...
        

        # 构造代理级别/场景级别的查询位置嵌入  
        # (num_groups, num_anchor, 12, 2)  
        # 以融入不同组和坐标的信息,并嵌入方向和位置信息 
        agent_level_anchors = self.kmeans_anchors.to(dtype).to(device).view(num_groups, self.num_anchor, self.predict_steps, 2).detach()
        scene_level_ego_anchors = anchor_coordinate_transform(agent_level_anchors, track_bbox_results, with_translation_transform=True)  # B, A, G, P ,12 ,2
        scene_level_offset_anchors = anchor_coordinate_transform(agent_level_anchors, track_bbox_results, with_translation_transform=False)  # B, A, G, P ,12 ,2

        # 对锚点进行归一化
        agent_level_norm = norm_points(agent_level_anchors, self.pc_range)
        scene_level_ego_norm = norm_points(scene_level_ego_anchors, self.pc_range)
        scene_level_offset_norm = norm_points(scene_level_offset_anchors, self.pc_range)

        # 仅使用锚点的最后一个点
        agent_level_embedding = self.agent_level_embedding_layer(
            pos2posemb2d(agent_level_norm[..., -1, :]))  # G, P, D
        scene_level_ego_embedding = self.scene_level_ego_embedding_layer(
            pos2posemb2d(scene_level_ego_norm[..., -1, :]))  # B, A, G, P , D
        scene_level_offset_embedding = self.scene_level_offset_embedding_layer(
            pos2posemb2d(scene_level_offset_norm[..., -1, :]))  # B, A, G, P , D
        
        ...

        outputs_traj_scores = []
        outputs_trajs = []

        # 通过MotionFormer模型进行前向传播
        # 输入各种查询、位置、边界框结果、BEV嵌入、初始参考轨迹等  
        # 以及锚点嵌入和锚点位置嵌入层  
        inter_states, inter_references = self.motionformer(
            track_query,  # B, A_track, D
            lane_query,  # B, M, D
            track_query_pos=track_query_pos,
            lane_query_pos=lane_query_pos,
            track_bbox_results=track_bbox_results,
            bev_embed=bev_embed,
            reference_trajs=init_reference,
            traj_reg_branches=self.traj_reg_branches,
            traj_cls_branches=self.traj_cls_branches,
            # anchor embeddings 
            agent_level_embedding=agent_level_embedding,
            scene_level_ego_embedding=scene_level_ego_embedding,
            scene_level_offset_embedding=scene_level_offset_embedding,
            learnable_embed=learnable_embed,
            # anchor positional embeddings layers
            agent_level_embedding_layer=self.agent_level_embedding_layer,
            scene_level_ego_embedding_layer=self.scene_level_ego_embedding_layer,
            scene_level_offset_embedding_layer=self.scene_level_offset_embedding_layer,
            spatial_shapes=torch.tensor(
                [[self.bev_h, self.bev_w]], device=device),
            level_start_index=torch.tensor([0], device=device))

        # 遍历每个级别,计算轨迹分数和轨迹
        for lvl in range(inter_states.shape[0]):
            outputs_class = self.traj_cls_branches[lvl](inter_states[lvl])
            tmp = self.traj_reg_branches[lvl](inter_states[lvl])
            tmp = self.unflatten_traj(tmp)
            
            # 使用累积和技巧来获取轨迹
            tmp[..., :2] = torch.cumsum(tmp[..., :2], dim=3)

            outputs_class = self.log_softmax(outputs_class.squeeze(3))
            outputs_traj_scores.append(outputs_class)

            # 对每个批次应用双变量高斯激活
            for bs in range(tmp.shape[0]):
                tmp[bs] = bivariate_gaussian_activation(tmp[bs])
            outputs_trajs.append(tmp)

        # 堆叠并输出轨迹分数和轨迹
        outputs_traj_scores = torch.stack(outputs_traj_scores)
        outputs_trajs = torch.stack(outputs_trajs)

        # 获取轨迹查询的有效性掩码
        B, A_track, D = track_query.shape
        valid_traj_masks = track_query.new_ones((B, A_track)) > 0

        # 构造输出字典
        outs = {
            'all_traj_scores': outputs_traj_scores,
            'all_traj_preds': outputs_trajs,
            'valid_traj_masks': valid_traj_masks,
            'traj_query': inter_states,
            'track_query': track_query,
            'track_query_pos': track_query_pos,
        }

        return outs

MotionTransformerDecoder:

这段代码融合了静态意图、动态意图、代理之间的交互、代理与地图的交互以及代理与目标的交互,最终生成了融合了多种信息的查询嵌入query_embed。这里意图(intention)代表目标位置。

class MotionTransformerDecoder(BaseModule):

    def forward(self,
                track_query,
                lane_query,
                track_query_pos=None,
                lane_query_pos=None,
                track_bbox_results=None,
                bev_embed=None,
                reference_trajs=None,
                traj_reg_branches=None,
                agent_level_embedding=None,
                scene_level_ego_embedding=None,
                scene_level_offset_embedding=None,
                learnable_embed=None,
                agent_level_embedding_layer=None,
                scene_level_ego_embedding_layer=None,
                scene_level_offset_embedding_layer=None,
                **kwargs):
        """Forward function for `MotionTransformerDecoder`.
        Args:
            agent_query (B, A, D):代理查询,其中 B 表示批次大小,A 表示代理(agent)的数量,D 表示特征维度。
            map_query (B, M, D):地图查询,其中 M 表示地图中的对象数量。
            map_query_pos (B, G, D):地图查询位置。
            static_intention_embed (B, A, P, D):静态意图嵌入,其中 P 表示意图的数量。代表每个代理的静态或固定的意图。
            offset_query_embed (B, A, P, D):偏移查询嵌入,与意图的偏移或变化有关。
            global_intention_embed (B, A, P, D):全局意图嵌入,代表每个代理的全局或整体意图。
            learnable_intention_embed (B, A, P, D):可学习的意图嵌入,是模型在训练过程中学习的意图表示。
            det_query_pos (B, A, D):检测查询位置,代表与检测任务相关的位置信息。
        Returns:
            None
        """
        intermediate = []    # 用于存储中间输出的列表  
        intermediate_reference_trajs = []    # 用于存储中间参考轨迹的列表

        # 对输入进行广播和扩展,以匹配所需的形状
        B, _, P, D = agent_level_embedding.shape
        track_query_bc = track_query.unsqueeze(2).expand(-1, -1, P, -1)  # (B, A, P, D)
        track_query_pos_bc = track_query_pos.unsqueeze(2).expand(-1, -1, P, -1)  # (B, A, P, D)

        # 计算静态意图嵌入,它在所有层中都是不变的
        agent_level_embedding = self.intention_interaction_layers(agent_level_embedding)
        static_intention_embed = agent_level_embedding + scene_level_offset_embedding + learnable_embed
        reference_trajs_input = reference_trajs.unsqueeze(4).detach()

        # 初始化查询嵌入,其形状与静态意图嵌入相同  
        query_embed = torch.zeros_like(static_intention_embed)
        for lid in range(self.num_layers):
            # 融合动态意图嵌入  
            # 动态意图嵌入是前一层的输出,初始化为锚点嵌入(anchor embedding)
            dynamic_query_embed = self.dynamic_embed_fuser(torch.cat(
                [agent_level_embedding, scene_level_offset_embedding, scene_level_ego_embedding], dim=-1))
            
            # 融合静态和动态意图嵌入  
            query_embed_intention = self.static_dynamic_fuser(torch.cat(
                [static_intention_embed, dynamic_query_embed], dim=-1))  # (B, A, P, D)
            
            # 将意图嵌入与查询嵌入融合
            query_embed = self.in_query_fuser(torch.cat([query_embed, query_embed_intention], dim=-1))
            
            # 代理之间的交互
            track_query_embed = self.track_agent_interaction_layers[lid](
                query_embed, track_query, query_pos=track_query_pos_bc, key_pos=track_query_pos)
            
            # 代理与地图之间的交互
            map_query_embed = self.map_interaction_layers[lid](
                query_embed, lane_query, query_pos=track_query_pos_bc, key_pos=lane_query_pos)
            
            # 代理与目标(BEV,即鸟瞰图)之间的交互,使用可变形Transformer实现  
            # implemented with deformable transformer
            bev_query_embed = self.bev_interaction_layers[lid](
                query_embed,
                value=bev_embed,
                query_pos=track_query_pos_bc,
                bbox_results=track_bbox_results,
                reference_trajs=reference_trajs_input,
                **kwargs)
            
            # 融合来自不同交互层的嵌入
            query_embed = [track_query_embed, map_query_embed, bev_query_embed, track_query_bc+track_query_pos_bc]
            query_embed = torch.cat(query_embed, dim=-1)
            query_embed = self.out_query_fuser(query_embed)
            ...

占用预测:

占用预测模块由5层Transformer构成,每层有一个自注意力和一个交叉注意力模块:

这部分的代码十分简单,因为DetrTransformerDecoder和DetrTransformerDecoderLayer是mmdet3d实现的,这里只是简单调用这个解码器和解码器层。这个模块的配置和前向传播如下,它主要实现了占用预测的任务,通过Transformer解码器对输入的特征图进行处理,生成未来的状态、掩码预测和占用逻辑。

occ_head=dict(
        type='OccHead',

        # Transformer
        transformer_decoder=dict(
            type='DetrTransformerDecoder',
            
            num_layers=5,
            transformerlayers=dict(
                type='DetrTransformerDecoderLayer',
                attn_cfgs=dict(
                    type='MultiheadAttention',
                    ),

                operation_order=('self_attn', 'norm', 'cross_attn', 'norm',
                                 'ffn', 'norm')),
            ),

    ),



class OccHead(BaseModule):
    def forward(self, x, ins_query):
        # 重新排列输入特征图 
        base_state = rearrange(x, '(h w) b d -> b d h w', h=self.bev_size[0])

        # 对特征图进行采样 
        base_state = self.bev_sampler(base_state)
        # 对特征图进行轻量级投影
        base_state = self.bev_light_proj(base_state)
        # 对特征图进行下采样
        base_state = self.base_downscale(base_state)
        base_ins_query = ins_query

        # 初始化最后的状态和查询
        last_state = base_state
        last_ins_query = base_ins_query
        future_states = []    # 存储未来的状态
        mask_preds = []        # 存储掩码预测
        temporal_query = []    # 存储时间查询
        temporal_embed_for_mask_attn = []    # 存储用于掩码注意力的时间嵌入

        # 计算每个块的Transformer层数
        n_trans_layer_each_block = self.num_trans_layers // self.n_future_blocks
        assert n_trans_layer_each_block >= 1
        
        # 遍历未来的块
        for i in range(self.n_future_blocks):
            # 下采样
            cur_state = self.downscale_convs[i](last_state)  # /4 -> /8

            # 注意力
            # 时间感知的ins_query
            cur_ins_query = self.temporal_mlps[i](last_ins_query)  # [b, q, d]
            temporal_query.append(cur_ins_query)

            # 生成注意力掩码 
            attn_mask, mask_pred, cur_ins_emb_for_mask_attn = self.get_attn_mask(cur_state, cur_ins_query)
            attn_masks = [None, attn_mask] 

            mask_preds.append(mask_pred)  # /1
            temporal_embed_for_mask_attn.append(cur_ins_emb_for_mask_attn)

            # 重新排列状态和查询
            cur_state = rearrange(cur_state, 'b c h w -> (h w) b c')
            cur_ins_query = rearrange(cur_ins_query, 'b q c -> q b c')

            # 遍历Transformer层
            for j in range(n_trans_layer_each_block):
                trans_layer_ind = i * n_trans_layer_each_block + j
                trans_layer = self.transformer_decoder.layers[trans_layer_ind]
                cur_state = trans_layer(
                    query=cur_state,  # [h'*w', b, c]
                    key=cur_ins_query,  # [nq, b, c]
                    value=cur_ins_query,  # [nq, b, c]
                    query_pos=None,  
                    key_pos=None,
                    attn_masks=attn_masks,
                    query_key_padding_mask=None,
                    key_padding_mask=None
                )  # out size: [h'*w', b, c]

            # 重新排列状态
            cur_state = rearrange(cur_state, '(h w) b c -> b c h w', h=self.bev_size[0]//8)
            
            # 上采样到/4
            cur_state = self.upsample_adds[i](cur_state, last_state)

            # 输出
            future_states.append(cur_state)  # [b, d, h/4, w/4]
            last_state = cur_state

        # 堆叠未来的状态、时间查询、掩码预测和查询嵌入
        future_states = torch.stack(future_states, dim=1)  # [b, t, d, h/4, w/4]
        temporal_query = torch.stack(temporal_query, dim=1)  # [b, t, q, d]
        mask_preds = torch.stack(mask_preds, dim=2)  # [b, q, t, h, w]
        ins_query = torch.stack(temporal_embed_for_mask_attn, dim=1)  # [b, t, q, d]

        # 将未来状态解码到更大的分辨率
        future_states = self.dense_decoder(future_states)
        ins_occ_query = self.query_to_occ_feat(ins_query)    # [b, t, q, query_out_dim]
        
        # 生成最终输出
        ins_occ_logits = torch.einsum("btqc,btchw->bqthw", ins_occ_query, future_states)
        
        return mask_preds, ins_occ_logits

规划模块

规划模块是3层解码器,在图中由下到上依次为:

  1. 构造查询Q:由跟踪和运动预测模块的输出查询和导航信息的嵌入相加,经过MLP,选择概率最大的单个轨迹(从6个轨迹中),最后加上位置编码
  2. 通过N层解码器融合BEV信息,得到轨迹
  3. 使用占用预测做碰撞优化

代码也比较简单,这个模块的配置和前向传播如下。它实现了基于BEV特征嵌入、占用掩码、驾驶命令等输入,生成SDC(自动驾驶车辆)轨迹的过程。

planning_head=dict(
        type='PlanningHeadSingleMode',
        embed_dims=256,

        planning_steps=planning_steps,
        loss_planning=dict(type='PlanningLoss'),
        loss_collisinotallow=[dict(type='CollisionLoss', delta=0.0, weight=2.5),
                        dict(type='CollisionLoss', delta=0.5, weight=1.0),
                        dict(type='CollisionLoss', delta=1.0, weight=0.25)],
        use_col_optim=use_col_optim,
        planning_eval=True,
        with_adapter=True,
    ),


class PlanningHeadSingleMode(nn.Module):  
    def forward(self,   
                bev_embed,  # BEV(鸟瞰图)特征嵌入  
                occ_mask,   # 占用实例掩码  
                bev_pos,    # BEV位置  
                sdc_traj_query, # SDC轨迹查询  
                sdc_track_query, # SDC轨迹追踪查询  
                command):   # 驾驶命令  
        """  
        前向传播过程。  
  
        参数:  
            bev_embed (torch.Tensor): 鸟瞰图特征嵌入。  
            occ_mask (torch.Tensor): 占用实例掩码。  
            bev_pos (torch.Tensor): BEV位置。  
            sdc_traj_query (torch.Tensor): SDC轨迹查询。  
            sdc_track_query (torch.Tensor): SDC轨迹追踪查询。  
            command (int): 驾驶命令。  
  
        返回:  
            dict: 包含SDC轨迹和所有SDC轨迹的字典。  
        """  
  
        ...  
  
        # 根据驾驶命令获取导航嵌入  
        navi_embed = self.navi_embed.weight[command]  
        navi_embed = navi_embed[None].expand(-1, P, -1)  
        # 融合SDC轨迹查询、SDC轨迹追踪查询和导航嵌入  
        plan_query = torch.cat([sdc_traj_query, sdc_track_query, navi_embed], dim=-1)  
  
        # 使用多层感知机(MLP)融合查询,并取最大值  
        plan_query = self.mlp_fuser(plan_query).max(1, keepdim=True)[0]  
        # 重排plan_query的形状  
        plan_query = rearrange(plan_query, 'b p c -> p b c')  
          
        # 重排bev_pos的形状  
        bev_pos = rearrange(bev_pos, 'b c h w -> (h w) b c')  
        bev_feat = bev_embed + bev_pos  
          
        # 插件适配器  
        if self.with_adapter:  
            bev_feat = rearrange(bev_feat, '(h w) b c -> b c h w', h=self.bev_h, w=self.bev_w)  
            bev_feat = bev_feat + self.bev_adapter(bev_feat)  # 残差连接  
            bev_feat = rearrange(bev_feat, 'b c h w -> (h w) b c')  
          
        # 添加位置嵌入  
        pos_embed = self.pos_embed.weight  
        plan_query = plan_query + pos_embed[None]  
          
        # 使用注意力模块处理plan_query和bev_feat  
        plan_query = self.attn_module(plan_query, bev_feat)  
          
        # 回归分支,生成SDC轨迹  
        sdc_traj_all = self.reg_branch(plan_query).view((-1, self.planning_steps, 2))  
        # 累计求和,生成轨迹点  
        sdc_traj_all[...,:2] = torch.cumsum(sdc_traj_all[...,:2], dim=1)  
        # 对第一条轨迹应用双变量高斯激活  
        sdc_traj_all[0] = bivariate_gaussian_activation(sdc_traj_all[0])  
        # 如果使用碰撞优化且非训练模式,进行后处理  
        if self.use_col_optim and not self.training:  
            assert occ_mask is not None  
            sdc_traj_all = self.collision_optimization(sdc_traj_all, occ_mask)  
          
        # 返回SDC轨迹和所有SDC轨迹  
        return dict(  
            sdc_traj=sdc_traj_all,  
            sdc_traj_all=sdc_traj_all,  
        )

写在最后的话:

UniAD在自动驾驶的每个子任务中使用交叉注意力,显式指定了信息流向,且只能利用nuScenes类的封闭数据集。与之相对的,基于多模态基础模型的自动驾驶架构只使用自注意力层,将视觉信息映射为tokens,和多模态prompt的tokens一起输入自注意力层,多模态prompt隐式指定了信息流向,基础模型也已经用开放数据集进行了预训练。这是一种与UniAD互补的思路。




#Depth Anything v2

论文标题:

Depth Anything V2

论文作者:

Lihe Yang, Bingyi Kang, Zilong Huang, Zhen Zhao, Xiaogang Xu, Jiashi Feng, Hengshuang Zhao

项目地址:https://depth-anything-v2.github.io/

导读:


在单目深度估计研究中,广泛使用的标记真实图像具有很多局限性,因此需要借助合成图像来确保精度。为了解决合成图像引起的泛化问题,作者团队采用了数据驱动(大规模伪标记真实图像)和模型驱动(扩大教师模型)的策略。同时在一个现实世界的应用场景中,展示了未标记真实图像的不可或缺的作用,证明“精确合成数据+伪标记真实数据”比标记的真实数据更有前景。最后,研究团队将可转移经验从教师模型中提炼到更小的模型中,这类似于知识蒸馏的核心精神,证明了伪标签蒸馏更加容易和安全。©️【深蓝AI】编译

这项工作展示了Depth Anything V2, 在不追求技巧的情况下,该项研究的目标是为建立一个强大的单目深度估计模型奠定基础。值得注意的是,与V1相比,这个版本通过三个关键实践产生了更精细,更强大的深度预测:

●用合成图像替换所有标记的真实图像;


●扩大教师模型的能力;


●通过大规模伪标记真实图像的桥梁教授学生模型。

与建立在Stable Diffusion上最新的模型相比,Depth Anything v2的模型效率更高更准确。作者提供不同规模的模型(从25M到1.3B参数),以支持广泛的场景。得益于强大的泛化能力,研究团队使用度量标签对模型进行微调,以获得度量深度模型。除了模型本身之外,考虑到当前测试集的有限多样性和频繁的噪声,研究团队构建了一个具有精确注释和多样化场景的多功能评估基准,以方便未来的研究。

单目深度估计(Monocular Depth Estimation,MDE)因其在广泛的下游任务中的重要作用而受到越来越多的关注。精确的深度信息不仅在经典应用中是有利的,例如3D重建,导航和自动驾驶,而且在其他生成场景中也是可应用的。

从模型建构方面来看,已有的MDE模型可以分为两类,一类基于判别模型,另一类基于生成模型,从图1的比较结果,Depthing Anything是更高效轻巧的。根据表1可得,Depth Anything V2可以实现复杂场景的可靠预测,包括且不局限于复杂布局、透明对象、反射表面等;在预测的深度图中包含精细的细节,包括但不限于薄物体、小孔等;提供不同的模型规模和推理效率,以支持广泛的应用;具有足够的可推广性,可以转移到下游任务。从Depth Anything v1出发,研究团队推出v2,认为最关键的部分仍然是数据,它利用大规模未标记的数据来加速数据扩展并增加数据覆盖率。研究团队进一步构建了一个具有精确注释和多样化场景的多功能评估基准。

51c自动驾驶~合集3_2d

▲图1|Depthing Anything v2与其他模型比较

51c自动驾驶~合集3_配置文件_02

▲表1|强大的单目深度估计模型的优选特性

重新审视Depth Anything V1标记数据的设计,如此大量的标记图像真的有利吗?真实标记的数据有2个缺点:一个是标签噪声,即深度图中的标签不准确。由于各种收集程序固有的局限性,真实标记数据不可避免地包含不准确的估计,例如无法捕捉透明物体的深度,立体匹配算法以及SFM算法在处理动态物体或异常值时受到的影响。另一个是细节忽略,一些真实数据通常会忽略深度图中的某些细节,例如树和椅子的深度往往表示非常粗糙。为了克服这些问题,研究者决定改变训练数据,寻找具有最好注释的图像,专门利用具有深度信息的合成图像进行训练,广泛检查合成图像的标签质量。

合成图像具有以下优势:

●所有精细细节都会得到正确标记,如图2所示;


●可以获得具有挑战性的透明物体和反射表面的实际深度,如图2中的花瓶。

51c自动驾驶~合集3_配置文件_03

▲图2|合成数据的深度

但是合成数据仍然也具有以下局限性:

●合成图像与真实图像之间存在分布偏差。尽管当前的图像引擎力求达到照片级逼真的效果,但其风格和颜色分布与真实图像仍存在明显差异。合成图像的颜色过于“干净”,布局过于“有序”,而真实图像则包含更多随机性;


●合成图像的场景覆盖范围有限。它们是从具有预定义固定场景类型的图形引擎迭代采样的,例如“客厅”和“街景”。

因此在MDE中,从合成图像到真实图像的迁移并非易事。为了缓解泛化问题,一些工作使用真实图像和合成图像的组合训练集,但是真实图像的粗深度图对细粒度预测具有破坏性。另一个潜在的解决方案是收集更多的合成图像,但是这是不可持续的。因此,在本文中,研究者提出一个路线图可以在不进行任何权衡的情况下解决精确性和鲁棒性困境,并且适用于任何模型规模。

51c自动驾驶~合集3_配置文件_04

▲图3|对不同视觉编码器在合成到真实转换方面的定性比较

研究团队提出的解决方案是整合未标记的真实图像。团队最强大的MDE模型基于DINOV2-G,最初仅使用高质量合成图像进行训练,然后它在未标记的真实图像上分配伪深度标签,最后仅使用大规模且精确的伪标记图像进行训练。Depth Anything v1凸显了大规模无标记真实数据的重要性。针对合成标记图像的缺点,阐述整合未标记真实图像的作用:

●弥补差距:由于分布偏移,直接从合成训练图像转移到真实测试图像具有挑战性。但是如果可以利用额外的真实图像作为中间学习目标,这个过程将更加可靠。直观地讲,在对伪标记真实图像进行明确训练后,模型可以更熟悉真实世界的数据分布。与手动注释的图像相比,自动生成的伪标签细粒度和完整度更高。

●增强场景覆盖率:合成图像的多样性有限,没有包含足够的真实场景。然而可以通过合并来自公共数据集的大规模未标记图像轻松覆盖大量不同的场景。此外,由于合成图像是从预定义视频中重复采样的,因此确实非常冗余。相比之下,未标记的真实图像清晰可辨,信息量丰富。通过在足够的图像和场景上训练,模型不仅表现出更强的零样本MDE能力,而且还可以作为下游相关任务更好的训练源。

●将经验从最强大的模型转移到较小的模型:如图5所示,较小的模型本身无法直接从合成到真实的迁移中受益。然而,有了大规模未标记的真实图像,可以学习模仿更强大的模型的高质量预测,类似于知识蒸馏。


51c自动驾驶~合集3_2d_05

▲图4|Depth Anything v2

■3.1 整体框架

基于以上分析,训练Depth Anything v2的流程如下:

●基于高质量合成图像训练基于DINOv2-G的可靠教师模型;


●在大规模未标记的真实图像上产生精确的伪深度;


●在伪标记的真实图像上训练最终的学生模型,实现稳健的泛化。

研究团队发布4种学生模型,分别基于DINOv2的小型,基础,大型和巨型模型。

■3.2 细节

如表2所示,使用5个精确合成的数据集和8个大规模伪标记真实数据集进行训练。与V1相同,对于每个伪标记样本,忽略top-n-largest-loss最大区域,n设为10%。同时,模型可以产生仿射不变的逆深度,因为模型使用2个损失项对标记图像进行优化,分别是平移不变损失和梯度匹配损失。其中梯度匹配损失在使用合成图像时,对深度清晰度优化非常有效。在伪标记图像上,遵循V1添加额外的特征对齐损失,以保留来自预训练的DINOv2编码器的信息语义。

51c自动驾驶~合集3_锚点_06

▲表2|训练数据集

■3.3 DA-2K

考虑到已有噪声数据的限制,该研究的目标是构建一个通用的相对单目深度估计评估基准。该基准可以:

●提供精确的深度关系;


●覆盖广泛的场景;


●包含大多数适合现代使用的高分辨率图像。

事实上,人类很难标注每个像素的深度,尤其是对于自然图像,因此研究员为每个图像标注稀疏深度。通常,给定一幅图像,可以选择其中的2个像素,并确定它们之间的相对深度。

51c自动驾驶~合集3_配置文件_07

▲图5|DA-2K

具体来说,可以采用2个不同的管道来选择像素对。在第一个管道中,如图5(a)所示,使用SAM自动预测对象掩码。但是可能存在模型预测的情况,引入第二个管道,仔细分析图像并手动识别具有挑战性的像素对。DA-2K并不能取代当前的基准,它只是作为准确密集深度的先决条件。

与Depth Anything v1一样,使用DPT作为深度解码器,并且基于DINO v2编码器构造。所有图像均裁剪到518进行训练,在合成图像上训练教师模型时,使用64的批处理大小进行160k次迭代。在伪标记真实图像上训练的第三阶段,该模型使用192的批处理大小进行480k次迭代。使用Adam优化器,分别将编码器和解码器的学习率设置为5e-5和5e-6。

51c自动驾驶~合集3_2d_08

▲表3|零样本深度估计

51c自动驾驶~合集3_配置文件_09

▲表4|DA-2K评估基准上的性能

如表3所示,结果优于MiDaS,稍逊于V1。然而,v2本身是针对薄结构进行细粒度预测,对复杂场景和透明物体进行稳健预测。这些维度的改进无法正确反映在当前的基准测试中。而在DA-2K的测试上,即使是最小的模型也明显优于其他基于SD的大模型。提出的最大模型在相对深度辨别方面的准确率比Margold高出10.6%.

51c自动驾驶~合集3_配置文件_10

▲表5|将Depth Anything V2预训练编码器微调至域内度量深度估计,即训练和测试图像共享同一域。所有比较方法都使用接近ViT-L的编码器大小

如表5所示,将编码器转移到下游的度量深度估计任务上,在NYU-D和KITTI数据集上都比之前的方法取得了显著改进,值得注意的是,即使是最轻量级的基于ViT-S的模型。

51c自动驾驶~合集3_配置文件_11

▲表6|伪标记真实图像上的重要性

如表6所示,消融实验证明了大规模伪标记真实图像的重要性。与仅使用合成图像进行训练相比,模型通过结合伪标记真实图像得到了极大的增强。

在本研究中,作者提出了Depth Anything v2,一种更强大的单目深度估计基础模型。它能够:

●提供稳健且细粒度更大的深度预测;


●支持具有各种模型大小(从25M到1.3B参数)的广泛应用;


●可轻松微调到下游任务,可以作为有效的模型初始化。


研究团队揭示了这项关键发现,此外,考虑到现有测试集中多样性弱,噪声强的特点,团队构建了一个多功能评估基准DA-2K,涵盖具有精确且具有挑战性的稀疏深度标签的各种高分辨率图像。



#Panoptic-FlashOcc

宣传一下小伙伴最新的工作Panoptic-FlashOcc,这是一种高效且易于部署的全景占用预测框架(基于之前工作FlashOcc),在Occ3DnuScenes上不仅取得了最快的推理速度,也取得了最好的精度。

  • 论文地址:https://arxiv.org/pdf/2406.10527v1
  • 论文单位:后摩智能、清华、中科大、大连理工

全景占用(Panoptic occupancy)提出了一个新的挑战,它旨在将实例占用(instance occupancy)和语义占用(semantic occupancy)整合到统一的框架中。然而,全景占用仍然缺乏高效的解决方案。在本文中,我们提出了Panoptic-FlashOcc,这是一个简单、稳健、实时的2D图像特征框架。基于FlashOcc的轻量级设计,我们的方法在单个网络中同时学习语义占用和类别感知的实例聚类,联合实现了全景占用。这种方法有效地解决了三维voxel-level中高内存和计算量大的缺陷。Panoptic-FlashOcc以其简单高效的设计,便于部署,展示了在全景占用预测方面的显著成就。在Occ3D-nuScenes基准测试中,它取得了38.5的RayIoU和29.1的mIoU,用于语义占用,运行速度高达43.9 FPS。此外,它在全景占用方面获得了16.0的RayPQ,伴随着30.2 FPS的快速推理速度。这些结果在速度和准确性方面都超过了现有方法的性能。源代码和训练模型可以在以下github仓库找到:https://github.com/ Yzichen/FlashOCC。

1. Introduction

全景占用在多视图感知中对自主机器人导航[10]、环境映射[27]和自动驾驶系统[2, 29, 30, 34]起着至关重要的作用。由于全景质量指标[19]的引入,它最近受到了极大的关注。全景占用将3D场景从视觉图像中划分为结构化的体素,每个体素都被分配了一个实例ID,其中“thing”类别中的每个体素都通过类别标签和实例ID来识别,而“stuff”类别中的体素仅用类别标签进行标记。

多视图3D全景占用仍然是一个新兴领域,并且仍然是一个开放的研究问题。由于其计算量大,到目前为止,只有一篇论文SparseOcc[19]以稀疏的方式解决了这个问题。3D全景占用在网络设计上提出了挑战,因为它将3D体素的分割分类为语义分割区域,同时也区分了个别实例。此外,全景占用在文章开头提到的领域中找到了其主要应用,所有这些领域都要求实时推理和高准确性,同时能够在各种边缘芯片上部署。这些挑战激励我们寻找一个更合适的架构,能够解决这些问题,并在不牺牲准确性的情况下实现快速推理速度。

受到2D图像全景分割中bottom-up范式成功的启发,在这种范式中,通常首先获得语义分割预测,然后对"thing"像素进行分组以形成聚类来识别实例[3, 7, 13, 26, 32],我们的目标是开发一个简单、有效且可部署的网络来处理全景占用。我们将语义占用与类别感知的实例聚类结合起来处理全景占用。为了确保在不牺牲准确性的情况下的推理速度,我们采用了FlashOcc[34]的架构来估计语义占用。FlashOcc利用通道到高度的转换有效地将扁平化的鸟瞰图(BEV)特征转换为3D占用预测,无需使用计算成本高昂的3D体素级表示。然后,我们结合了一个轻量级的中心度头,灵感来自Panoptic-DeepLab[3],以生成类别感知的实例中心。来自语义占用估计和中心度头的预测通过全景占用处理融合,以生成最终的全景占用。这导致了一种高效的自下而上的全景占用网络设计,我们称之为Panoptic-FlashOcc。

  1. Related Work

Panoptic segmentation. 自从Kirillov等人[13]引入全景分割以来,这一领域出现了众多努力。最初,对现有网络的调整包括添加语义[13]或实例分支[3]到最先进的模型,随后是手工制作的后处理技术[18, 31, 32]。随着Transformer集成到计算机视觉中,研究人员开始探索能够以更统一的方式处理全景分割任务的架构。MaskFormer[4]利用queries预测object masks和stuff masks。Mask2Former[5]引入了masked-attention,通过掩蔽图像中无关的部分,显著提高了对小物体的性能。虽然基于Transformer的方法与以前的模型相比显示出了优越的性能,但它们在各种边缘芯片上的部署方面提出了挑战。最近,高效的MaskConver[23]通过仅使用全卷积层学习"thing"和"stuff"类的实例中心,超越了上述基于Transformer的模型。这激励我们寻找一个高效且易于部署的模型,该模型仅以buttom-up的全卷积方式运行。

高效的全景占用。全景占用代表了一个新的方向,与全景分割的蓬勃发展相比,它仍然没有得到充分的探索。Sparseocc[19]是第一个也是唯一一个专注于提高全景质量和推理速度的研究。它使用A100 GPU提供了质量和延迟的报告。由于语义占用是全景占用的一个子任务,全景理解可以从语义占用中经验性地扩展,我们还探索了语义占用以识别具有高效架构的研究。许多工作[1, 16, 21, 29, 30]采用了密集的3D体素级表示来进行占用计算,尽管这需要计算3D卷积或Transformer模块。因此,一些研究旨在简化模型以减少计算时间。TPVFormer[12]提出使用三视角视图表示来补充垂直结构信息,其中体素级表示被简化。VoxFormer[15]利用稀疏到密集的MAE模块通过从透视图投射的稀疏查询完成占用。SparseOcc进一步以完全稀疏的方式优化占用预测[19]。

  1. Architecture

在本节中,我们概述了如何利用所提出的实例中心将全景属性集成到语义占用任务中。我们首先在第3.1节提供架构的概述。然后,我们在第3.2节深入到占用头,它预测每个体素的分割标签。随后,在第3.3节中,我们详细阐述了中心度头,它被用来生成类别感知的实例中心。最后,在第3.4节中,我们描述了全景占用处理,它作为一个高效的后处理模块,用于生成全景占用。

51c自动驾驶~合集3_锚点_12

3.1. Overview Architecture

51c自动驾驶~合集3_锚点_13

51c自动驾驶~合集3_锚点_13

51c自动驾驶~合集3_锚点_15

3.2. Semantic Occupancy Prediction

51c自动驾驶~合集3_锚点_16

3.3. Centerness Head

我们框架中提出的centerness head,有两个目的:

  1. 加强不同物体之间的区别。通过生成更清晰的语义边界,centerness head作为辅助子模块,提高了语义占用分支的性能。在仅执行语义占用预测时,这种增强在推理过程中不需要任何额外的计算资源。随后的章节将讨论这一实证验证。
  2. 提供全景占用处理的实例中心的类别标签和3D位置。在城市场景中,“thing”对象通常在扁平化的鸟瞰图(BEV)感知中彼此分离,因此从BEV特征生成的“thing”中心与从3D体素特征中识别出的中心一致。

如图2底部中心块所示,中心度头包括中心回归头和中心热图头。两个模块都包含三个卷积层,搭配3×3的核心。

Center Heatmap Head. 中心点表示对于"thing"和"stuff"的重要性已在包括目标检测[9, 14, 25, 33]、实例分割[6]和全景分割[3, 23]等多项研究中得到广泛证明。在训练过程中,gt实例中心度值使用2D高斯分布进行编码,其标准差等于标注实例的对角线大小。focal loss被用来最小化预测的class-aware热力图与对应gt之间的差异

3.4. Panoptic Occupancy Processing

全景占用处理模块充当实例标签的分配模块,设计得既简单又有效。它完全依赖于矩阵运算和逻辑运算,不包含任何可训练参数。这种设计使得全景占用处理的实现直接而高效。

51c自动驾驶~合集3_配置文件_17

51c自动驾驶~合集3_配置文件_17

51c自动驾驶~合集3_2d_19

51c自动驾驶~合集3_2d_20

51c自动驾驶~合集3_配置文件_21

51c自动驾驶~合集3_锚点_22

51c自动驾驶~合集3_2d_23

51c自动驾驶~合集3_配置文件_24

51c自动驾驶~合集3_锚点_25

4. Experiment

51c自动驾驶~合集3_锚点_26

51c自动驾驶~合集3_配置文件_27

总结:本文介绍了Panoptic-FlashOcc,这是一种高效且易于部署的全景占用预测框架。它基于已建立的FlashOcc,通过整合centerness head和全景占用处理,将语义占用增强为全景占用。Panoptic-FlashOcc在具有挑战性的Occ3DnuScenes测试中不仅取得了最快的推理速度,也取得了最好的精度。



#2024自动驾驶论文汇总

汇总链接:https://github.com/autodriving-heart/ECCV-2024-Papers-Autonomous-Driving

We will promptly include more related works in this repository. Please stay tuned!!!

We also kindly invite you to our platform, Auto Driving Heart, for paper interpretation and sharing. If you would like to promote your work, please feel free to contact me.


1) End to End | 端到端自动驾驶

GenAD: Generative End-to-End Autonomous Driving

  • paper: https://arxiv.org/pdf/2402.11502
  • code: https://github.com/wzzheng/GenAD


2)LLM Agent | 大语言模型智能体

DriveLM: Driving with Graph Visual Question Answering

  • paper: https://arxiv.org/pdf/2312.14150
  • code: https://github.com/OpenDriveLab/DriveLM

ELM: Embodied Understanding of Driving Scenarios

  • paper: https://arxiv.org/pdf/2403.04593
  • code: https://github.com/OpenDriveLab/ELM

Controllable Navigation Instruction Generation with Chain of Thought Prompting

  • paper: coming soon
  • code: https://github.com/refkxh/C-Instructor

Asynchronous Large Language Model Enhanced Planner for Autonomous Driving

  • paper: coming soon
  • code: coming soon

TOD3Cap: Towards 3D Dense Captioning in Outdoor Scenes

  • paper: https://arxiv.org/pdf/2403.19589
  • code: https://github.com/jxbbb/TOD3Cap

Global-Local Collaborative Inference with LLM for Lidar-Based Open-Vocabulary Detection

  • paper: coming soon
  • code: https://github.com/GradiusTwinbee/GLIS


3)SSC: Semantic Scene Completion | 语义场景补全

Hierarchical Temporal Context Learning for Camera-based Semantic Scene Completion

  • paper: https://arxiv.org/pdf/2407.02077
  • code: https://github.com/Arlo0o/HTCL


4)OCC: Occupancy Prediction | 占用感知

Fully Sparse 3D Occupancy Prediction

  • paper: https://arxiv.org/pdf/2312.17118
  • code: https://github.com/MCG-NJU/SparseOcc

GaussianFormer: Scene as Gaussians for Vision-Based 3D Semantic Occupancy Prediction

  • paper: https://arxiv.org/pdf/2405.17429
  • code: https://github.com/huang-yh/GaussianFormer

Occupancy as Set of Points

  • paper: https://arxiv.org/pdf/2407.04049
  • code: https://github.com/hustvl/osp


5) World Model | 世界模型

OccWorld: 3D World Model for Autonomous Driving

  • paper: https://arxiv.org/pdf/2311.16038
  • code: https://github.com/wzzheng/OccWorld

Modelling Competitive Behaviors in Autonomous Driving Under Generative World Model

  • paper: coming soon
  • code: coming soon

DriveDreamer: Towards Real-world-driven World Models for Autonomous Driving

  • paper: https://arxiv.org/pdf/2309.09777
  • code: https://github.com/JeffWang987/DriveDreamer


6)HD-Mapping

MapTracker: Tracking with Strided Memory Fusion for Consistent Vector HD Mapping

  • paper: https://arxiv.org/pdf/2403.15951
  • code: https://github.com/woodfrog/maptracker

ADMap: Anti-disturbance framework for reconstructing online vectorized HD map

  • paper: coming soon
  • code: https://github.com/hht1996ok/ADMap

Accelerating Online Mapping and Behavior Prediction via Direct BEV Feature Attention

  • paper: coming soon
  • code: https://github.com/alfredgu001324/MapBEVPrediction

Leveraging Enhanced Queries of Point Sets for Vectorized Map Construction

  • paper: https://arxiv.org/pdf/2402.17430
  • code: https://github.com/HXMap/MapQR


7)Foundation Model

PartGLEE: A Foundation Model for Recognizing and Parsing Any Objects

  • paper: coming soon
  • code: coming soon


8)Robust Perception

Rethinking Data Augmentation for Robust LiDAR Semantic Segmentation in Adverse Weather

  • paper: https://arxiv.org/pdf/2407.02286
  • code: https://github.com/engineerJPark/LiDAR-DataAug4Weather

R2-Bench: Benchmarking the Robustness of Referring Perception Models under Perturbations

  • paper: coming soon
  • code: https://github.com/lxa9867/r2bench


9)3D Object Detection | 三维目标检测

Weakly Supervised 3D Object Detection via Multi-Level Visual Guidance

  • paper: https://arxiv.org/pdf/2312.07530
  • code: https://github.com/KuanchihHuang/VG-W3D

GraphBEV: Towards Robust BEV Feature Alignment for Multi-Modal 3D Object Detection

  • paper: https://arxiv.org/pdf/2403.11848
  • code: https://github.com/adept-thu/GraphBEV

RecurrentBEV: A Long-term Temporal Fusion Framework for Multi-view 3D Detection

  • paper: coming soon
  • code: https://github.com/lucifer443/RecurrentBEV

Ray Denoising: Depth-aware Hard Negative Sampling for Multi-view 3D Object Detection

  • paper: https://arxiv.org/pdf/2402.03634
  • code: https://github.com/LiewFeng/RayDN

MonoWAD: Weather-Adaptive Diffusion Model for Robust Monocular 3D Object Detection

  • paper: coming soon
  • code: https://github.com/VisualAIKHU/MonoWAD

DualBEV: CNN is All You Need in View Transformation

  • paper: https://arxiv.org/pdf/2403.05402
  • code: https://github.com/PeidongLi/DualBEV

OPEN: Object-wise Position Embedding for Multi-view 3D Object Detection

  • paper: coming soon
  • code: https://github.com/AlmoonYsl/OPEN

Make Your ViT-based Multi-view 3D Detectors Faster via Token Compression

  • paper: coming soon
  • code: coming soon

SEED: A Simple and Effective 3D DETR in Point Clouds

  • paper: coming soon
  • code: coming soon

Towards Stable 3D Object Detection

  • paper: https://arxiv.org/pdf/2407.04305
  • code: https://github.com/jbwang1997/StabilityIndex


10)Domain Adaptation & Test-Time Adaptation

Enhancing Source-Free Domain Adaptive Object Detection with Low-Confidence Pseudo-Label Distillation

  • paper: coming soon
  • code: https://github.com/junia3/LPLD

Fully Test-Time Adaptation for Monocular 3D Object Detection

  • paper: coming soon
  • code: https://github.com/Hongbin98/MonoTTA

Progressive Classifier and Feature Extractor Adaptation for Unsupervised Domain Adaptation on Point Clouds

  • paper: https://arxiv.org/pdf/2303.01276
  • code: https://github.com/xiaoyao3302/PCFEA


11)Cooperative Perception | 协同感知

Plug and Play: A Representation Enhanced Domain Adapter for Collaborative Perception

  • paper: coming soon
  • code: https://github.com/luotianyou349/PnPDA


12)SLAM

13)Scene Flow Estimation | 场景流估计

4D Contrastive Superflows are Dense 3D Representation Learners

  • paper: coming soon
  • code: https://github.com/Xiangxu-0103/SuperFlow


14)Point Cloud | 点云

T-CorresNet: Template Guided 3D Point Cloud Completion with Correspondence Pooling Query Generation Strategy


15)  Efficient Network

16) Segmentation

17)Radar | 毫米波雷达

18)Nerf Gaussian Splatting

Street Gaussians: Modeling Dynamic Urban Scenes with Gaussian Splatting

  • paper: https://arxiv.org/pdf/2401.01339
  • code: https://github.com/zju3dv/street_gaussians

MVSplat: Efficient 3D Gaussian Splatting from Sparse Multi-View Images

  • paper: https://arxiv.org/pdf/2403.14627
  • code: https://github.com/donydchen/mvsplat

GScream: Learning 3D Geometry and Feature Consistent Gaussian Splatting for Object Removal

  • paper: https://arxiv.org/pdf/2404.13679
  • code: https://github.com/W-Ted/GScream

BeNeRF: Neural Radiance Fields from a Single Blurry Image and Event Stream

  • paper: coming soon
  • code: https://github.com/WU-CVGL/BeNeRF

PreSight: Enhancing Autonomous Vehicle Perception with City-Scale NeRF Priors

  • paper: https://arxiv.org/pdf/2403.09079
  • code: https://github.com/yuantianyuan01/PreSight

GaussianImage: 1000 FPS Image Representation and Compression by 2D Gaussian Splatting

  • paper: https://arxiv.org/pdf/2403.08551
  • code: https://github.com/Xinjie-Q/GaussianImage

SG-NeRF: Neural Surface Reconstruction with Scene Graph Optimization

  • paper: coming soon
  • code: https://github.com/Iris-cyy/SG-NeRF

Disentangled Generation and Aggregation for Robust Radiance Fields

  • paper: coming soon
  • code: https://github.com/GaoHchen/Robust-Triplane


19)MOT: Muti-object Tracking | 多物体跟踪

Beyond MOT: Semantic Multi-Object Tracking

  • paper: coming soon
  • code: https://github.com/HengLan/SMOT


20)Multi-label Atomic Activity Recognition

21) Motion Prediction | 运动预测

22) Trajectory Prediction | 轨迹预测

23) Depth Estimation | 深度估计Leveraging Synthetic Data for Real-Domain High-Resolution Monocular Metric Depth Estimation

  • paper: coming soon
  • code: https://github.com/zhyever/PatchRefiner


24) Event Camera | 事件相机

25) Odometry

DVLO: Deep Visual-LiDAR Odometry with Local-to-Global Feature Fusion and Bi-Directional Structure Alignment

  • paper: coming soon
  • code: https://github.com/IRMVLab/DVLO




#FastBEV

 一个快速和强大的BEV基线

车端感知算法,作为自动驾驶技术的核心构成之一,近年来经历了显著的技术飞跃与数次迭代更新。其发展历程可概括为如下几个阶段:

  1. 2D感知与属性识别:初期,感知算法主要依赖于2D图像,专注于物体的检测与分类,并试图提取基本属性。
  2. 单目3D感知:随着技术进步,逐步发展出基于单目摄像头的3D感知算法,这些算法试图从单一图像中恢复深度信息。
  3. 环视3D感知:随后,技术进一步演进至利用多个摄像头实现环视3D感知,通过多视角数据融合提升感知的准确性与鲁棒性。
  4. 时序环视3D感知:在环视3D感知的基础上,引入了时间维度的考量,通过连续帧的变化融合,增强了对动态环境的感知能力。
  5. 多传感器融合:此阶段结合了雷达、摄像头等多种传感器数据,通过数据融合提升了感知系统的综合性能。
  6. 端到端模型:最新的发展趋势在于开发端到端的感知模型,这些模型直接从原始传感器输入预测规划结果,简化了处理流程并提高了运行效率。

车端感知算法的持续进步是自动驾驶技术发展的重要标志,尤其是模型方向的发展。随着模型规模的增大,如何在车端高效部署这些模型已成为一个亟待解决的问题。本文将介绍TPAMI 2024《FastBEV: A Fast and Strong Bird’s-Eye View Perception Baseline》,其主要作者之一现就职于哪吒汽车,负责量产项目的感知模型研发工作。

显式BEV转换的加速需求

针对BEV网络加速的需求,我们首先需要审视当前BEV环视感知的主流技术路径。BEV环视感知技术主要分为两大流派:其一,是以DETR3D和PETR为代表的基于Transformer的稀疏方法,它们通过融合3D位置编码与2D特征,并依托Transformer解码器实现query式的环视感知,而无需显式构建密集的BEV特征;其二,则是以BEVDet和FastBEV等算法为代表的密集方法,它们首先从多相机透视图像中提取2D特征,进而基于投影关系融合成dense的显式BEV特征,这种方案在时序融合、多传感器融合和多任务处理等方面表现出色,因而广泛应用于多种算法中。

然而,随着感知任务要求的不断提高,车端模型的网络结构日益庞大,对BEV感知的范围和分辨率需求亦日益增加。在此背景下,基于稠密BEV特征的方案在算力与感知性能之间往往难以取得平衡,因此,BEV网络的加速显得尤为重要。

FastBEV 如何解决加速问题

FastBEV作为一种前沿的环视感知技术,其在继承m2bev投影方案精髓的基础上,对特征融合效率进行了显著的性能优化。与LSS方法有所区别,FastBEV并不预测2D图像中的深度分布,而是基于一种更为直接的假设:在相机射线方向上,不同深度层次上的像素点特征具有一致性。此假设极大地简化了特征处理流程,有效规避了基于深度分布的特征叉乘操作,进而显著降低了计算复杂性。通过结合静态查找表和多合一的优化策略,FastBEV能够高效地将不同视角下的特征进行整合,从而构建出一个全面且精确的BEV特征表示。该技术不仅在部署速度上达到了极致,同时结合多尺度融合等模型设计和训练trick确保了相当的精度水平。

51c自动驾驶~合集3_配置文件_28

具体而言,相较于其他view transform方法,如LSS,它们要求为每个相机视角生成多个特征副本,并通过sum pooling进行整合。然而,FastBEV通过深入分析nuscenes数据集中不同相机视角重叠区域的占比情况,揭示了这些重叠区域实际上占比相对较小。进一步地,FastBEV发现每个相机仅在其特定的视野范围内填充有效的特征信息,而其余区域则保持为零值状态。基于这一关键观察,FastBEV提出了一种优化的特征融合策略,即直接将多个特征副本按照内外参数精准地采样并填充到共享的volume特征中。在处理重叠区域时,FastBEV提供了两种选择:保留任意一份特征或进行特征融合。通过实验验证,这种策略在精度上的损失几乎可以忽略不计。

51c自动驾驶~合集3_2d_29

FastBEV在性能优化方面采取了查找表优化技术,该技术通过构建查找表,实现了对目标voxel的2D特征的高效采样。具体而言,该技术仅需根据voxel的索引在查找表中查找对应的2D特征,从而完成一次采样即可实现完整的view transform,此举显著减少了冗余计算和显存的占用。此外,FastBEV还结合了3D neck部分的s2c技巧以及模型量化加速策略,使其在CPU和GPU平台上均能达到实时的感知性能,同时保持了算子的简洁性和跨平台部署的便捷性。

FastBEV基于深度均匀假设,通过改进特征融合策略和查找表优化,结合3D neck优化及模型量化加速等举措,构建了一个高效、实时且易于部署的环视感知系统。该系统专为自动驾驶车辆的环境理解而设计,对自动驾驶技术的持续发展发挥了显著推动作用。