文章目录
-
- 1. 标准卷积与Sparse Conv对比
-
- (1)普通卷积
- (2) 稀疏卷积
- (3) 改进的稀疏卷积(subm)
- 2 Sparse Conv 官方API
- 3. Sparse Conv 计算
-
- 3. 1 Sparse Conv 计算流程
- 3. 2 案例
-
- 3.2.1 普通稀疏卷积
- 3.2.2 subm模式的稀疏卷积
3D点云数据非常稀疏,尤其体素化处理后(比如200k的点放在1440 144041个格子中),大部分空间都没有数据,此时卷积的话基本上都是在卷空气。此时直接用标准卷积去处理数据,浪费大量的计算资源,所以对3D的点云,一般采用稀疏卷积,只对有数据的部分进行计算,从而大大提高卷积的效率。
稀疏卷积的计算和标准卷积的计算结果是一样的(SubMConv3d是有差异的),只不过稀疏卷积的对输入和输出的数据表达和标准卷积是不一样的,它通过一个feats(值)和indices(索引)来表达数据,并且只表达有值的部分,这种表示方式是一种稀疏化储存的表示方式。
1. 标准卷积与Sparse Conv对比
(1)普通卷积
- 普通卷积:利用卷积核在输入数据中滑动,对输入4x4的数据,利用3x3大小的kernel_size计算,得到4x4的输出
(2) 稀疏卷积
稀疏卷积通过一个feats(值) 和indices(索引)来表达输入矩阵中的值(图1),并且只表达有值的部分。图1中输入tensor中有值的部分为:1,2,3 feats;对应的索引分别为(0,0),(1,1),(3,3)。可以看到,稀疏卷积(Sparse Conv)和标准卷积的计算结果是一样的,只不过表达形式不一样,稀疏卷积的结果只表达有值的部分,通过feats(值)和indices(索引)存储,这种表示方式就是一种稀疏化储存的方式。
为什么我们要用稀疏卷积呢?主要它可以实现在GPU运算时,在GPU block级别跳过一些值都是0的数据,这是因为点云是非常稀疏的,特别是将它体素化表达后,比如将20万个点放在(1440144041)个网格上,整体非常稀疏,很多空间都是0, 对于全是0的计算,是一种计算资源的浪费,而稀疏卷积就可以实现只在有值的位置进行计算(subm模式
),值为0的地方在卷积的时候就跳过不计算。
(3) 改进的稀疏卷积(subm)
- subm模式下的稀疏卷积是一个改进版的稀疏卷积,它和标准的稀疏卷积的区别是,
标准的稀疏卷积
和普通的卷积
计算结果是一样
的,只是对结果稀疏表示
。但subm模式
的稀疏卷积,只在有值的地方做卷积计算
。 - 比如上图中输入矩阵中有
1,2,3
3个非0的值,此时在计算卷积的时候,会将卷积核中心对准有值的位置,然后计算卷积,经过subm卷积计算,输入有值的位置会有对应的计算结果,值为0的位置输出全是0。然后将结果稀疏表示为feats和indices。
总结
-
标准的
SparseConv
卷积的次数和普通的卷积是一样的,只不过对输入和输出数据
进行了稀疏化表达和存储
。而subm模式下
的稀疏卷积,只对输入tensor中有值的位置
卷积,如果3个地方有值,则卷积3次,输出3个值。 -
普通的稀疏卷积和标准卷积一样,输出的大小是和输入和卷积核大小相关的。而
subm稀疏卷积
,输入有3个地方有值,输出永远是3个值,也就是它的输出个数和输入中非零个数
是一样的。
2 Sparse Conv 官方API
参考:https://github.de/traveller59/spconv/blob/master/docs/USAGE.md
import spconv.pytorch as spconv
from spconv.pytorch import functional as Fsp
from torch import nn
from spconv.pytorch.utils import PointToVoxel
from spconv.pytorch.hash import HashTable
3. Sparse Conv 计算
- https://github.com/traveller59/spconv/blob/master/docs/USAGE.md
在进行spconv(Sparse Conv)时,首先需要对lidar点云体素化,比如将lidar点映射到(1440 x 1440 x 41) 的网格上,接下来就可以对体素化后的lidar点云计算稀疏卷积。
3. 1 Sparse Conv 计算流程
(1) 点云体素化PointToVoxe
voxel generator in spconv generate indices in
ZYX
order, the params format are XYZ.
generated indicesdon't include batch axis
, you need to add it by yourself.
see examples/voxel_gen.py for examples.
- 利用
PointToVoxel
产生的indices
,坐标顺序为ZYX
,我们需要调整为XYZ
- 产生的indices,没有batch维,需要我们自己添加一个batch_id
- 体素化生成voxels(feats)和coords,用于后续稀疏卷积使用
- 其中 官方提供的点云体素化案例如下:来自于
USAGE.md
from spconv.pytorch.utils import PointToVoxel, gather_features_by_pc_voxel_id
# this generator generate ZYX indices.
gen = PointToVoxel(
vsize_xyz=[0.1, 0.1, 0.1],
coors_range_xyz=[-80, -80, -2, 80, 80, 6],
num_point_features=3,
max_num_voxels=5000,
max_num_points_per_voxel=5)
pc = np.random.uniform(-10, 10, size=[1000, 3])
pc_th = torch.from_numpy(pc)
voxels, coords, num_points_per_voxel = gen(pc_th, empty_