news 2026/10/15 18:20:27

【BEV 感知】Lift-Splat-Shoot核心架构:Lift、Splat、Shoot三阶段技术原理解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【BEV 感知】Lift-Splat-Shoot核心架构:Lift、Splat、Shoot三阶段技术原理解析

论文:https://arxiv.org/pdf/2008.05711​​​​​​

项目主页:https://research.nvidia.com/labs/toronto-ai/lift-splat-shoot/

代码链接:https://github.com/nv-tlabs/lift-splat-shoot

一、引言

在自动驾驶领域,感知系统的核心目标是从多传感器数据中提取语义信息,并将其融合到统一的 “鸟瞰图(Bird's-Eye-View, BEV)” 坐标系中,为后续的运动规划模块提供决策依据。传统计算机视觉算法要么输出与坐标系无关的分类结果,要么在输入图像的同一坐标系中进行预测(如目标检测、语义分割等),这与自动驾驶中 “多传感器输入 - 统一 BEV 输出” 的需求存在本质脱节。

为解决这一问题,Jonah Philion 和 Sanja Fidler 提出了一种名为 “Lift, Splat, Shoot” 的端到端架构,能够直接从任意数量的相机图像中提取 BEV 场景表示。该架构通过 “Lift(提升)-Splat(泼洒)-Shoot(投射)” 三步核心流程,在保留多视图感知关键对称性的同时,实现了端到端可微分训练,其性能在多个 BEV 语义分割任务中超越现有基线,并支持可解释的端到端运动规划。

二、核心背景与问题定义

2.1 自动驾驶感知的核心矛盾
  1. 多传感器异构性:不同相机具有独立的坐标系(内参 + 外参),数据分布存在差异;
  2. 坐标系转换需求:感知结果需映射到 ego 车的 BEV 坐标系,才能被规划模块直接使用;
  3. 深度歧义性:单目相机缺乏直接深度信息,多视图融合需解决深度估计与跨相机信息融合的耦合问题。

传统多视图感知方法(如先单图检测再坐标转换)的缺陷的是:后处理阶段的坐标转换导致模型无法从 BEV 输出端反向传播梯度到原始传感器输入,无法通过数据驱动学习最优融合策略,也无法利用规划模块的反馈优化感知系统。

2.2 关键对称性要求
  1. 平移等变性(Translation Equivariance):图像像素坐标整体平移时,输出结果同步平移;
  2. 排列不变性(Permutation Invariance):相机输入顺序不影响最终 BEV 输出;
  3. Ego 帧等距等变性(Ego-frame Isometry Equivariance):Ego 车坐标系旋转 / 平移时,输出结果同步变换。

Lift, Splat, Shoot 架构通过设计天然满足这三个对称性,为多视图融合提供了坚实的结构基础。

三、相关工作综述

论文的相关工作主要围绕单目 3D 目标检测和 BEV 帧推理两大方向展开,其核心贡献在于整合并突破了现有方法的局限:

3.1 单目 3D 目标检测

现有方法可分为三类:

  1. 2D 检测 + 3D 回归:先通过 2D 检测器获取目标框,再回归 3D 位置与尺寸。这类方法依赖 2D 检测精度,且深度估计与边界框预测的误差难以解耦;
  2. 伪激光雷达(Pseudo-Lidar):先通过单目深度估计生成伪点云,再输入 BEV 网络进行检测。这类方法将深度估计与 BEV 检测解耦,利用了 BEV 坐标系中欧式距离的物理意义,但两步法同样存在梯度传播断裂问题;
  3. 3D 几何基元投影:通过生成 3D 体素或目标提案,投影到多相机图像中提取特征后进行检测。这类方法的缺陷是:像素特征与体素深度无关,导致深度歧义性影响融合效果。
3.2 BEV 帧直接推理

近年来直接在 BEV 帧进行推理的方法逐渐兴起:

  1. MonoLayout:通过单目图像推理 BEV 布局,利用对抗损失补全遮挡目标,但仅支持单相机输入,缺乏多视图融合能力;
  2. 金字塔占用网络(PON):采用 Transformer 架构将图像特征转换为 BEV 表示,但未充分利用相机的几何结构;
  3. FISHING Net:支持多视图 BEV 分割与未来预测,但在语义分割精度与泛化性上仍有提升空间。

Lift, Splat, Shoot 的创新点在于:通过 “隐式深度分布 + 几何约束融合”,在端到端框架中同时解决深度估计与多视图融合问题,且天然满足多视图感知的对称性要求。

四、LSS整体架构

在自动驾驶中,通常会在车身周围安装多个传感器(相机、雷达等)以使车辆具备360°感知能力。每个传感器都有自己的一个坐标系,它们的输出数据或者感知结果最终会被汇总到一个统一的坐标系——自车坐标系进行处理。通过标定,我们可以得到车上每个相机的外参矩阵和内参矩阵。内、外参矩阵决定了从自车坐标系到图像坐标系的映射关系。对于从各个相机获取的张图片,LSS算法的目的是在BEV坐标系中找到该场景的栅格化表示,然后在该表示的基础上实现目标分割、地图分割等感知任务。

左:输入多相机图像及内参 / 外参;中左:Lift 步骤生成的视锥体点云;中右:Splat 步骤将点云映射到 BEV 平面;右:BEV CNN 输出语义分割或规划结果。

LSS模型前向推理的大致流程如下图所示:

4.1 模型输入:

给定张相机图像,每张图像对应内参矩阵和外参矩阵(定义 3D 参考坐标到像素坐标的映射)。目标是输出 BEV 坐标系下的栅格化语义表示(为特征通道数,为 BEV 网格尺寸),训练与测试阶段均不依赖激光雷达等深度传感器。

4.2 Lift:隐式深度分布的 3D 特征提升

Lift 步骤的核心目标是将单张 2D 图像提升到 3D 空间,生成包含深度信息的视锥体(Frustum)特征点云,解决单目相机的深度歧义性问题。

4.2.1 深度离散化与视锥体构建

对于每张图像的每个像素 ,定义一组离散深度值

论文中 ,深度范围 4至45m。每个像素对应 个 3D 点 ,所有像素的 3D 点构成该相机的视锥体点云(尺寸为 )。

该结构类似于 “多平面图像(Multi-Plane Image)”,但区别在于:多平面图像存储 RGB 颜色与透明度,而此处存储抽象语义特征。

4.2.2 深度分布与特征加权

为解决深度歧义性,模型不为每个像素预测单一深度,而是预测一个深度分布 ( 表示 simplex 空间,满足 )和一个上下文特征向量 。每个 3D 点 的最终特征为:

该设计的灵活性在于:

若 为 one-hot 向量,等价于伪激光雷达的 “硬深度分配”;
若 为均匀分布,等价于 OFT 方法中 “特征与深度无关” 的处理方式;
模型可通过学习自动选择:深度明确时聚焦单一深度,深度模糊时(如远距离、遮挡区域)分散特征到多个深度。

4.2.3 特征提取网络

采用预训练的 EfficientNet-B0 作为骨干网络,对输入图像进行特征提取,输出每个像素的上下文向量 和深度分布 (通过 softmax 层归一化得到)。该网络在 ImageNet 上预训练,保证了特征的泛化能力。

Lift 步骤的可视化如图 3 所示:

左:像素的深度分布;左上:上下文向量;右:通过外积得到的各深度特征。

接下来我们就结合代码对LSS的每个步骤进行详细解析:

LSS模型被封装在src/model.py文件中的LiftSplatShoot类中,模型用Nuscense数据集进行训练,每次输入车身环视6个相机的图像。Nuscense数据集中的原始图像宽高为1600x900,在预处理的时候被缩放到352x128的大小,6个相机的图像经过预处理后组成一个维度为(B=1,N=6,C=3,H=128,W=352)的张量输入给LSS模型。前向推理时,LiftSplatShoot类的forward函数需要输入以下几个参数:

  • x:6个相机的图像组成的张量,(1,6,3,128,352)
  • rots:6个相机从相机坐标系到自车坐标系的旋转矩阵,(1,6,3,3)
  • trans:6个相机从相机坐标系到自车坐标系的平移向量,(1,6,3)
  • intrins:6个相机的内参矩阵,(1,6,3,3)
  • post_rots:6个相机的图像因预处理操作带来的旋转矩阵,(1,6,3,3)
  • post_trans:6个相机的图像因预处理操作带来的平移向量,(1,6,3)

首先来看LiftSplatShoot类初始化函数:

def __init__(self, grid_conf, data_aug_conf, outC): super(LiftSplatShoot, self).__init__() self.grid_conf = grid_conf self.data_aug_conf = data_aug_conf dx, bx, nx = gen_dx_bx(self.grid_conf['xbound'], self.grid_conf['ybound'], self.grid_conf['zbound'], # grid_conf 从train.py例传进来 ) #dx tensor([0.5000,0.5000,20.000]) #bx tensor([-49.7500,49.7500,0.0000]) #nx tensor([200,200,1]) # bx-dx/2. tensor([-50.,-50.,-10.]) self.dx = nn.Parameter(dx, requires_grad=False) self.bx = nn.Parameter(bx, requires_grad=False) self.nx = nn.Parameter(nx, requires_grad=False) self.downsample = 16 self.camC = 64 # frustum 视锥 self.frustum = self.create_frustum() self.D, _, _, _ = self.frustum.shape self.camencode = CamEncode(self.D, self.camC, self.downsample) #特征提取 background 到深度的估计 对应的lift操作 self.bevencode = BevEncode(inC=self.camC, outC=outC) # 输出结果 # toggle using QuickCumsum vs. autograd self.use_quickcumsum = True

在初始化函数中,主要声明了该类接下来会使用到的一些参数,再来看看该类的forward函数:

def forward(self, x, rots, trans, intrins, post_rots, post_trans): # x:[4,6,3,128,352] 输入图像 # rots:由相机坐标系->车身坐标系的旋转矩阵,rots = (bs, N, 3, 3); # # trans:由相机坐标系->车身坐标系的平移矩阵,trans=(bs, N, 3); # # intrinsic:相机内参,intrinsic = (bs, N, 3, 3); # # post_rots:由图像增强引起的旋转矩阵,post_rots = (bs, N, 3, 3); # # post_trans:由图像增强引起的平移矩阵,post_trans = (bs, N, 3); x = self.get_voxels(x, rots, trans, intrins, post_rots, post_trans) x = self.bevencode(x) # CNN 结构 return x

forward函数首先调用了get_voxels() 函数:

def get_voxels(self, x, rots, trans, intrins, post_rots, post_trans): geom = self.get_geometry(rots, trans, intrins, post_rots, post_trans) # 得到点云从2d到3d的银蛇 x = self.get_cam_feats(x) # 特征提取 x = self.voxel_pooling(geom, x) # splat 操作 return x

在推理阶段,会根据相机的内外参把图像坐标系下的视锥点云转换到自车坐标系下,这个过程在get_geometry函数中实现:

def get_geometry(self, rots, trans, intrins, post_rots, post_trans): """Determine the (x,y,z) locations (in the ego frame) of the points in the point cloud. Returns B x N x D x H/downsample x W/downsample x 3 """ B, N, _ = trans.shape # undo post-transformation 增广 # B x N x D x H x W x 3 # 3 - xs, ys, lamda #消除图像增强以及预处理对象像素的变化 points = self.frustum - post_trans.view(B, N, 1, 1, 1, 3) points = torch.inverse(post_rots).view(B, N, 1, 1, 1, 3, 3).matmul(points.unsqueeze(-1)) # cam_to_ego # xs, ys, lamda -> xs * lamda, ys*lamda, lamda points = torch.cat((points[:, :, :, :, :, :2] * points[:, :, :, :, :, 2:3], points[:, :, :, :, :, 2:3] ), 5) # 对点云中预测的宽度和高度上的栅格坐标,将其乘以深度上的栅格坐标 combine = rots.matmul(torch.inverse(intrins)) # 除以内参矩阵,乘以相机坐标系到车身坐标系的旋转矩阵rots points = combine.view(B, N, 1, 1, 1, 3, 3).matmul(points).squeeze(-1) #加上相机坐标系到车身坐标系的平移矩阵 points += trans.view(B, N, 1, 1, 1, 3) # points -> B*N*D*H*W * 3 3 -> [X,Y,Z] return points

self.frustum是在初始化函数时自动调用了self.create_frustum() 函数:

def create_frustum(self): # 为每一张图片生成一个棱台状(frustum)的点云 # make grid in image plane # 数据增强后图片大小 ogfH:128 ogfW:352 ogfH, ogfW = self.data_aug_conf['final_dim'] # 下采样16倍后图像大小 fH: 128/16=8 fW: 352/16=22 fH, fW = ogfH // self.downsample, ogfW // self.downsample ''' ds: 在深度方向上划分网格 dbound: [4.0, 45.0, 1.0] arange后-> [4.0,5.0,6.0,...,44.0] view后(相当于reshape操作)-> (41x1x1) expand后(扩展张量中某维数据的尺寸)-> ds: DxfHxfW(41x8x22) ''' ds = torch.arange(*self.grid_conf['dbound'], dtype=torch.float).view(-1, 1, 1).expand(-1, fH, fW) D, _, _ = ds.shape # D: 41 表示深度方向上网格的数量 ''' xs: 在宽度方向上划分网格 linspace 后(在[0,ogfW)区间内,均匀划分fW份)-> [0,16,32..336] 大小=fW(22) view后-> 1x1xfW(1x1x22) expand后-> xs: DxfHxfW(41x8x22) ''' xs = torch.linspace(0, ogfW - 1, fW, dtype=torch.float).view(1, 1, fW).expand(D, fH, fW) ''' ys: 在高度方向上划分网格 linspace 后(在[0,ogfH)区间内,均匀划分fH份)-> [0,16,32..112] 大小=fH(8) view 后-> 1xfHx1 (1x8x1) expand 后-> ys: DxfHxfW (41x8x22) ''' ys = torch.linspace(0, ogfH - 1, fH, dtype=torch.float).view(1, fH, 1).expand(D, fH, fW) ''' frustum: 把xs,ys,ds堆叠到一起 stack后-> frustum: DxfHxfWx3 堆积起来形成网格坐标, frustum[d,h,w,0]就是(h,w)位置,深度为d的像素的宽度方向上的栅格坐标 ''' frustum = torch.stack((xs, ys, ds), -1) return nn.Parameter(frustum, requires_grad=False)

可以看到,该函数生成了一个棱台状的点云,生成的锥点是基于图像坐标系的,我的理解是,将原始图像以16下采样后,划分为8x22的栅格,并对每一格分配一个[4,45]的值,即深度,从而将图片从128x352转换成了41x8xx22x3的数据,并将其输出。frustum[d,h,w,0]意味着(h,w) 位置,深度为d的像素在宽度上的栅格坐标,frustum[d,h,w,1]意味着(h,w) 位置,深度为d的像素在高度上的栅格坐标,frustum[d,h,w,2]也就意味着(h,w) 位置,深度为d的像素在深度上的栅格坐标。
get_voxels()函数在调用完了get_geometry后,紧接着调用了get_cam_feats() 函数:

def get_cam_feats(self, x): """Return B x N x D x H/downsample x W/downsample x C """ B, N, C, imH, imW = x.shape x = x.view(B*N, C, imH, imW) x = self.camencode(x) # 生成C*D的lift 矩阵 x:24*64*41*8*22 x = x.view(B, N, self.camC, self.D, imH//self.downsample, imW//self.downsample) # 将前两维切开,4*6*64*41*8*22 x = x.permute(0, 1, 3, 4, 5, 2) # x: 4*6*41*8*22*64 return x

get_cam_feats()调用了self.camencode()函数来提取带有深度的特征,CamEncode类的初始化函数如下:

class CamEncode(nn.Module): def __init__(self, D, C, downsample): super(CamEncode, self).__init__() self.D = D self.C = C self.trunk = EfficientNet.from_pretrained("efficientnet-b0") self.up1 = Up(320+112, 512) self.depthnet = nn.Conv2d(512, self.D + self.C, kernel_size=1, padding=0)

前向函数则如下:

def forward(self, x): depth, x = self.get_depth_feat(x) return x

调用了get_depth_feat():

def get_depth_feat(self, x): x = self.get_eff_depth(x) # Depth x = self.depthnet(x) depth = self.get_depth_dist(x[:, :self.D]) # 前面d个为depth new_x = depth.unsqueeze(1) * x[:, self.D:(self.D + self.C)].unsqueeze(2) # 得到一个[C D] 大小的矩阵 return depth, new_x def get_depth_dist(self, x, eps=1e-20): return x.softmax(dim=1)

其中,get_eff_depth()通过efficient net提取特征,调用了Up函数上采样到了512,输出数据大小为24x512x8x22。随后经过了1x1卷积,将数据维度变化为24x105x8x22,105=C+D,接下来调用了get_depth_dist()函数来对前面的D个维度进行softmax,这里前41个维度为深度维,后面64个代表特征图上不同位置对应的图像特征。返回的depth维度是24x41x8x22。最后在将depth与后面的64维做外积,得到维度为24x64x41x8x22的new_x,并将其返回。回到get_cam_feats中,将前24维拆成4x6,在颠倒顺序,输出一个维度维4x6x41x8x22x64的x。

至此,Lift节点处理完成。

在按照上面流程图描述下模型对输入图像数据的处理。由6个相机的图像组成的张量x的维度为(1,6,3,128,352),推理时首先把维度变换为(1 * 6,3,128,352),然后送入camencode模块中进行处理。在camencode模块中,图像数据首先被送入EfficientNet-B0网络中去提取特征,该网络输出的两层特征x1和x2的维度分别为(6,320,4,11)和(6,112,8,22)。接下来,x1和x2被送入到Up模块中进行处理。在该模块中,对x1进行上采样把维度变为(6,320,8,22),然后与x2拼接到一起,最后经过两层卷积处理,输出维度为(6,512,8,22)的张量。这个张量再经过一个核大小为1x1的卷积层depthnet处理,输出的维度为(6,105,8,22)。在这105个通道中,其中前41个会用SoftMax函数求取表示41个离散深度的概率,另外64个通道则表示前面说过的上下文向量,这41个深度概率与64个上下文特征向量会做一个求外积的操作。整个camencode模块输出的张量维度为(6,64,41,8,22),最终这个张量的维度会被变换为(1,6,41,8,22,64)。

4.3 Splat:柱体池化的多视图特征融合

Splat 步骤的核心是将所有相机的视锥体点云融合到统一的 BEV 网格中,通过柱体池化(Pillar Pooling)实现高效的特征聚合,并满足排列不变性与等变性要求。

4.3.1 柱体定义与点云映射

BEV 网格的尺寸为 (范围 -50m 到 50m,网格分辨率 0.5m × 0.5m)。定义 “柱体(Pillar)” 为 BEV 网格中沿高度方向无限延伸的立方体(即忽略 3D 点的高度信息,仅保留水平坐标 )。

利用相机内参 和外参 ,将每个相机视锥体中的 3D 点 映射到 BEV 坐标系的 位置,进而分配到对应的柱体中。

4.3.2 高效柱体求和池化

为解决大规模点云的池化效率问题,论文采用 “累积和技巧(Cumulative Sum Trick)” 替代传统的填充 - 池化操作,步骤如下:

按柱体 ID 对所有点云特征排序;
对特征进行累积和计算;
通过柱体边界的累积和差值得到每个柱体的求和特征。
该方法的优势在于:

避免填充导致的内存浪费;
可推导解析梯度,训练速度提升 2 倍;
求和池化天然满足排列不变性(相机顺序不影响求和结果)。
最终,Splat 步骤输出 BEV 特征图(尺寸为 ),可直接输入 BEV CNN 进行语义推理

在通过代码的逻辑梳理一下:

Splat操作的第一步是构建BEV空间下的特征,这个过程在voxel_pooling函数中实现。该函数有两个输入,一个自车坐标系下的视锥点云坐标点geom,维度为(1,6,41,8,22,3);另一个是camencode模块输出的图像特征点云x,维度为(1,6,41,8,22,64)。voxel_pooling函数的处理过程如下:

  • 将x的维度变换为(1 * 6 * 41 * 8 * 22,64);
  • 将geom转换到体素坐标下,得到对应的体素坐标,并将参数范围外的点过滤掉;
  • 将体素坐标系下的geom的维度变换为(1 * 6 * 41 * 8 * 22,3),然后给每个点分配一个体素索引,再根据索引值对geom和x进行排序,这样归属于同一体素的点geom及其对应的特征向量x就会被排到相邻的位置;
  • 用累计求和的方式对每个体素中的点云特征进行求和池化;
  • 用unbind对张量沿Z维度进行分离,然后将分离的张量拼接到一起进行输出。由于Z维度的值为1,这样做实际上是去掉了Z维度,这样BEV空间下的特征就构建好了。

作者设置的自车坐标系下的感知范围(以米为单位)为:

  • x:[-50.0, 50.0]
  • y:[-50.0, 50.0]
  • z:[-10.0, 10.0]

在划分体素时,3个坐标轴方向分别以0.5,0.5,20.0的间隔进行划分,所以一共有200x200x1个体素。

图是对BEV特征做可视化的结果:

def voxel_pooling(self, geom_feats, x): B, N, D, H, W, C = x.shape Nprime = B*N*D*H*W # 将特征点云展平,共有B*N*D*H*W个点,每个点包含C维特征向量 x = x.reshape(Nprime, C) # 把自车坐标系下的坐标转换为体素坐标,然后展平 geom_feats = ((geom_feats - (self.bx - self.dx/2.)) / self.dx).long() geom_feats = geom_feats.view(Nprime, 3) # 求每个点对应的batch size batch_ix = torch.cat([torch.full([Nprime//B, 1], ix, device=x.device, dtype=torch.long) for ix in range(B)]) geom_feats = torch.cat((geom_feats, batch_ix), 1) # 过滤点范围外的点 kept = (geom_feats[:, 0] >= 0) & (geom_feats[:, 0] < self.nx[0])\ & (geom_feats[:, 1] >= 0) & (geom_feats[:, 1] < self.nx[1])\ & (geom_feats[:, 2] >= 0) & (geom_feats[:, 2] < self.nx[2]) x = x[kept] geom_feats = geom_feats[kept] # 求每个点对应的体素索引,并根据索引进行排序 ranks = geom_feats[:, 0] * (self.nx[1] * self.nx[2] * B)\ + geom_feats[:, 1] * (self.nx[2] * B)\ + geom_feats[:, 2] * B\ + geom_feats[:, 3] sorts = ranks.argsort() x, geom_feats, ranks = x[sorts], geom_feats[sorts], ranks[sorts] # 累计求和,对体素中的点进行求和池化 if not self.use_quickcumsum: x, geom_feats = cumsum_trick(x, geom_feats, ranks) else: x, geom_feats = QuickCumsum.apply(x, geom_feats, ranks) # final:(B x C x Z x X x Y),(1 x 64 x 1 x 200 x 200) final = torch.zeros((B, C, self.nx[2], self.nx[0], self.nx[1]), device=x.device) # 把特征赋给对应的体素中 final[geom_feats[:, 3], :, geom_feats[:, 2], geom_feats[:, 0], geom_feats[:, 1]] = x # 去掉Z维度 final = torch.cat(final.unbind(dim=2), 1) # final:(1,64,200,200) return final
4.4 Shoot:基于轨迹模板的端到端运动规划

Shoot 步骤的核心是利用 BEV 特征图学习空间代价函数,通过 “投射轨迹模板” 实现可解释的端到端运动规划,将感知与规划紧密结合。

4.4.1 轨迹模板生成

通过对大规模专家轨迹进行 K-Means 聚类(),生成 1000 个轨迹模板 ,每个模板 表示一条 5 秒长(时间步长 0.25s)的 ego 车运动轨迹,如图 所示:

训练与测试阶段均使用该模板集合,通过代价函数选择最优轨迹。

4.4.2 代价函数与概率建模

将规划问题转化为轨迹模板的分类任务:给定 BEV 特征图预测的代价图 ( 位置的通行代价),每条轨迹 的代价为其路径上所有 BEV 网格的代价之和。轨迹的概率分布定义为:

训练目标为最大化专家轨迹的对数概率:

对于每个样本,找到与 ground-truth 轨迹 L2 距离最近的模板作为正样本;
使用交叉熵损失优化模型,使网络学习到符合驾驶规则的代价函数(如车道边界代价高、障碍物区域代价高)。
该设计的优势在于:

可解释性:最优轨迹来自明确的模板集合,便于调试与安全验证;
端到端训练:代价图与轨迹选择共享梯度,感知与规划协同优化;
无需手动设计代价函数:通过数据驱动自动学习驾驶规则。

这个操作是根据前面BEV空间的感知结果学习端到端的轨迹预测代价图用于运动规划。由于我们主要关注感知部分,这部分代码就不做过多介绍。

六、总结

Lift-Splat-Shoot框架通过Lift、Splat、Shoot三个阶段的创新设计,成功实现了从多视角图像到三维空间的高效转换。其核心优势在于:

  • 隐式三维投影:无需显式重建三维点云,直接从图像特征生成三维表示
  • 高效计算:通过体素池化和累积求和技巧实现高效的特征聚合
  • 任意相机配置:支持任意数量和位置的相机阵列,具有良好的灵活性
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 18:20:08

同屏推流实战:从RTSP/RTMP选型到EasyScreenLive调优

简介&#xff1a;EasyScreenLive推流组件是一款集采集、编码、组播、推流和RTSP服务于一体的同屏工具&#xff0c;主要面向需要快速实现大屏投屏、无纸化会议同屏及课堂同屏演示的软件开发者和项目集成人员。资源包共408个文件&#xff0c;总大小约23.64MB&#xff0c;核心部分…

作者头像 李华
网站建设 2026/10/15 18:19:57

MFC导出ListCtrl数据到Excel:免COM、防乱码、控格式

简介&#xff1a;本资源是一份面向MFC中级开发者的实用型代码实践项目&#xff0c;聚焦Windows桌面应用中ListCtrl控件数据导出至Excel的核心需求&#xff0c;适用于需增强报表导出能力的C桌面软件开发场景。压缩包共24个文件&#xff08;156KB&#xff09;&#xff0c;包含11个…

作者头像 李华
网站建设 2026/10/15 18:18:20

不用微软账户,在 Windows 11 中修改管理员名称

给管理员改个名字,能让人觉得这台电脑更属于自己的,但很多人不知道该怎么操作。所以,如果你在不使用微软账户的前提下,折腾半天找不到改 Windows 11 管理员名称的入口,这篇文章就是你的指南。 无论你是接手了一台到处刻着别人名字的电脑,想给本地管理员账户换个个性化的…

作者头像 李华
网站建设 2026/10/15 18:18:19

基于IMU与TinyML的儿童行为状态游戏化反馈系统

1. 项目概述&#xff1a;这不是监控&#xff0c;而是用游戏化思维解决真实育儿痛点“追踪小孩-游戏动画”这个标题乍看像儿童定位设备的UI界面&#xff0c;但实际落地时&#xff0c;它根本不是做硬件定位&#xff0c;也不是开发带GPS的地图App。我接触过多个类似需求的家长和早…

作者头像 李华