为了从稀疏的深度采样(Lidar)中重建出稠密的深度信息, 研究人员提出了一种高效的稀疏卷积层,用于在训练过程中精确定位数据缺失的位置,实现了具有稀疏不变性的特征抽取和重建手段。Sparsity Invariant CNNs
1.基于稀疏采样的稠密深度重建
激光雷达是十分重要的传感器,能给出非常准确的距离信息。但其缺陷在于采集的数据较为稀疏、同时数据也不规则,现有的神经网络在处理非规则稀疏数据时会产生一系列问题(无法明确定义卷积操作)。为了处理这个问题,研究人员将三维点云投影到虚拟的二维平面实现2.5D的表示,并利用图像修复/深度补全的方法进行处理,得到稠密的2.5D表示。最重要的是,这种特征还不随稀疏性变化,具有不变性。
这篇文章的主要目的是>>>通过稀疏的输入,获得稠密的输出结果,并得到稀疏不变性的表示<<<<。
2.Sparse Conv稀疏卷积
可以将稠密重建视为从稀疏空间向稠密空间中的映射过程,这个过程由多层神经网络来实现。
与先前方法不同的是,研究人员根据采样点的位置同时定义了一个观测二进制掩膜O,来为网络提供输入点的位置信息:
针对稀疏的输入数据,只有精确地在观测像素位置上点才被考虑(也就是o为1的位置),并利用观测点的数量进行归一化处理。这一操作背后的想法是由于输入数据的稀疏性不同,这种方法直接针对输入的有效点进行处理,使得输出具有不变性。
随后利用下面的最大池化方法来为后续的层提供新的观测mask,如果滤波器中的领域都没有值那么这个点就属于没有观测到的点,在mask中置零,如果有值则证明这是有值的观测点置为一:
3.模型架构
研究人员提出了了下面的网络架构,其中输入包含了稀疏的深度图(黄色)和二进制的观测掩膜(红色),输出预测后的稠密深度图(这个图可以对应第二个代码实现中最后一部分网络结构来理解
)。
这里面最重要的是将mask加入到了模型的训练过程中,可以看到在每一层都有稀疏卷积在作用,对真正观测到的值进行处理。特征和mask同时输入稀疏卷积操作。首先上部分支中,a.特征和mask先进行点乘,保留下观测到的值,b.而后与权重进行第一次卷积;c.mask与全1矩阵进行归一化卷积,d.而后与权重作用后的特征j进行点乘,e.最后加上偏置得到最终的特征结果;f.而mask分支则利用第二节里面提到的改进最大池化方法来得到新的mask(这里的a~f可以对应代码注释中对应步骤来理解
):
通过mask与特征的共同作用,使模型专注于对于观测数据的特征提取和学习,使得最后恢复的稠密深度图更为精确,得到的表示特征具有稀疏不变性。下面的表格中可以看到不同采样率下的稀疏卷积结果都比较稳定
4.代码实现
找到了一个关于这篇论文的代码实现,主要对文章中的稀疏卷积部分进行了定义:
import tensorflow as tf
# copy from https://github.com/PeterTor/sparse_convolution/blob/master/sparse.py
"""输入为一个特征张量和一个观测值的mask
输出为稀疏卷积后的张量和对应新的mask
函数内部和一般卷积类似,包含了滤波器个数、核的大小、步长以及L2的幅值
对应上面稀疏卷积来看会更清晰,对应a~f步骤
"""
def sparse_conv(tensor,binary_mask = None,filters=32,kernel_size=3,strides=2,l2_scale=0.0):
if binary_mask == None: #first layer has no binary mask
b,h,w,c = tensor.get_shape()
channels=tf.split(tensor,c,axis=3)
#assume that if one channel has no information, all channels have no information
binary_mask = tf.where(tf.equal(channels[0], 0), tf.zeros_like(channels[0]), tf.ones_like(channels[0])) #mask should only have the size of (B,H,W,1) #生成掩膜
#稀疏卷积的上半部分支
features = tf.multiply(tensor,binary_mask) #对应第一步逐点乘法>>a
features = tf.layers.conv2d(features, filters=filters, kernel_size=kernel_size, strides=(strides, strides), trainable=