文章目录
- 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,33个非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
ZYXorder, 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_