文章目录
DGCNN和RSNet与KCNet和PointwiseCNN一样,都着眼于对局部特征提取方面的工作。
CVPR2018 DGCNN
Dynamic Graph CNN for Learning on Point Clouds
(论文链接)(源码链接)
受到PointNet和graph CNN的启发,作者提出了EdgeConv和Dynamic Graph。
PointNet在提取点云局部特征时是逐点进行处理的,并没有考虑到点与点之间的关系,因此在局部特征的提取上有所欠缺,DGCNN是构建局部邻近图,然后在边上进行像卷积一样的操作。与graph CNN的不同之处在于,DGCNN每层的大小是在动态更新的,而不是固定的。
Edge Convolution
对于一个含有
n
n
n个点的点云
X
=
{
x
1
,
.
.
.
x
n
}
∈
R
F
,
x
i
=
(
x
i
,
y
i
,
z
i
)
X=\{\mathbf{x}_1,...\mathbf{x}_n\}\in\mathbb{R}^F,\mathbf{x}_i=(x_i,y_i,z_i)
X={x1,...xn}∈RF,xi=(xi,yi,zi),构建一个有向图
G
=
(
V
,
E
)
\mathcal{G}=(\mathcal{V}, \mathcal{E})
G=(V,E)来表示点云的局部结构,其中,
V
=
{
1
,
…
,
n
}
\mathcal{V}=\{1, \ldots, n\}
V={1,…,n},
E
⊆
V
×
V
\mathcal{E} \subseteq \mathcal{V} \times \mathcal{V}
E⊆V×V分别是顶点和边。最简单的方法是构建一个点云的k最近邻图,图上包含自环,每条边的特征定义为
e
i
j
=
h
Θ
(
x
i
,
x
j
)
,
e_{i j}=h_{\Theta}\left(\mathrm{x}_{i}, \mathrm{x}_{j}\right),
eij=hΘ(xi,xj), 其中
h
Θ
:
R
F
×
R
F
→
R
F
′
h_{\Theta}: \mathbb{R}^{F} \times \mathbb{R}^{F} \rightarrow \mathbb{R}^{F^{\prime}}
hΘ:RF×RF→RF′是包含一组待学习参数
Θ
的
{\Theta}的
Θ的非线性函数。最后用一个channelwise symmetric aggregation operation
□
\square
□对每条边的特征进行操作,EdgeConv的输出可以表示为:
x
i
′
=
∏
j
:
(
i
,
j
)
∈
E
h
Θ
(
x
i
,
x
j
)
\mathbf{x}_{i}^{\prime}=\prod_{j:(i, j) \in \mathcal{E}} h_{\Theta}\left(\mathbf{x}_{i}, \mathbf{x}_{j}\right)
xi′=j:(i,j)∈E∏hΘ(xi,xj)
其中,
x
i
\mathbf{x}_{i}
xi是中心点,
{
x
j
:
(
i
,
j
)
∈
E
}
\{\mathbf{x}_j:(i, j) \in \mathcal{E}\}
{xj:(i,j)∈E}是相邻的一些点。如下图。
非线性函数
h
h
h和channelwise symmetric aggregation operation
□
\square
□的选择可以有下列几种:
- x i m ′ = ∑ j : ( i , j ) ∈ E θ m ⋅ x j x_{i m}^{\prime}=\sum_{j:(i, j) \in \mathcal{E}} \theta_{m} \cdot \mathbf{x}_{j} xim′=j:(i,j)∈E∑θm⋅xj当 x 1 , . . . x n \mathbf{x}_1,...\mathbf{x}_n x1,...xn表示规则网格上的图像像素时, G \mathcal{G} G可以表示像素点之间的连接情况,可以将 θ m ⋅ x j \theta_{m} \cdot \mathbf{x}_{j} θm⋅xj作为 h h h,求和运算作为channelwise symmetric aggregation。上式中 Θ = ( θ 1 , … , θ M ) \mathbf{\Theta}=\left(\boldsymbol{\theta}_{1}, \ldots, \boldsymbol{\theta}_{M}\right) Θ=(θ1,…,θM)为 M M M个不同filter的权值,每个 θ M \theta_{M} θM的维度与 x \mathbf{x} x都是相同的, ⋅ \cdot ⋅指欧几里得内积。
-
h
Θ
(
x
i
,
x
j
)
=
h
Θ
(
x
i
)
h_{\Theta}\left(\mathbf{x}_{i}, \mathbf{x}_{j}\right)=h_{\Theta}\left(\mathbf{x}_{i}\right)
hΘ(xi,xj)=hΘ(xi)
这一种只对全局形体特征进行了提取,而没有考虑到点与点之间相邻的关系结构,在PointNet中用的就是这一种。 -
h
Θ
(
x
i
,
x
j
)
=
h
Θ
(
x
j
)
,
x
i
m
′
=
∑
j
∈
V
(
h
θ
(
x
j
)
)
g
(
u
(
x
i
,
x
j
)
)
h_{\Theta}\left(\mathbf{x}_{i}, \mathbf{x}_{j}\right)=h_{\Theta}\left(\mathbf{x}_{j}\right),\\ x_{i m}^{\prime}=\sum_{j \in \mathcal{V}}\left(h_{\boldsymbol{\theta}\left(\mathrm{x}_{j}\right)}\right) g\left(u\left(\mathrm{x}_{i}, \mathrm{x}_{j}\right)\right)
hΘ(xi,xj)=hΘ(xj),xim′=j∈V∑(hθ(xj))g(u(xi,xj))
上式中, g \mathcal{g} g是高斯核, u u u计算的是点与点之间的欧氏距离。Atzmon et al.在[1]中使用过。 -
h
Θ
(
x
i
,
x
j
)
=
h
Θ
(
x
j
−
x
i
)
h_{\Theta}\left(\mathbf{x}_{i}, \mathbf{x}_{j}\right)=h_{\Theta}\left(\mathbf{x}_{j}-\mathbf{x}_{i}\right)
hΘ(xi,xj)=hΘ(xj−xi)
这一种只考虑了局部信息,而没有考虑全局信息。 -
h
Θ
(
x
i
,
x
j
)
=
h
ˉ
Θ
(
x
i
,
x
j
−
x
i
)
h_{\Theta}\left(\mathbf{x}_{i}, \mathbf{x}_{j}\right)=\bar{h}_{\Theta}\left(\mathbf{x}_{i}, \mathbf{x}_{j}-\mathbf{x}_{i}\right)
hΘ(xi,xj)=hˉΘ(xi,xj−xi)
本文中使用的为上式,通过从 x i \mathbf{x}_i xi坐标中提取的全局信息和计算 x j − x i \mathbf{x}_j-\mathbf{x}_i xj−xi得到的局部信息相结合。具体的,本文用到的操作如下:
e i j m ′ = ReLU ( θ m ⋅ ( x j − x i ) + ϕ m ⋅ x i ) , x i m ′ = max j : ( i , j ) ∈ E e i j m ′ e_{i j m}^{\prime}=\operatorname{ReLU}\left(\theta_{m} \cdot\left(\mathrm{x}_{j}-\mathrm{x}_{i}\right)+\phi_{m} \cdot \mathrm{x}_{i}\right),\\ x_{i m}^{\prime}=\max _{j:(i, j) \in \mathcal{E}} e_{i j m}^{\prime} eijm′=ReLU(θm⋅(xj−xi)+ϕm⋅xi),xim′=j:(i,j)∈Emaxeijm′
其中, Θ = ( θ 1 , … , θ M , ϕ 1 , … , ϕ M ) \Theta=\left(\theta_{1}, \ldots, \theta_{M}, \phi_{1}, \ldots, \phi_{M}\right) Θ=(θ1,…,θM,ϕ1,…,ϕM)。
论文里写的比较复杂,根据代码EdgeConv具体的操作大概: - 对于每个点 x i x_i xi,找到 k k k个最近邻点。 k k k个点按距离升序排列,得到 x j i 1 , x j i 2 , … , x j i k x_{j_{i 1}}, x_{j_{i 2}}, \dots, x_{j_{i k}} xji1,xji2,…,xjik
- 依次计算出 x j i 1 − x i , x j i 2 − x i , … , x j i k − x i x_{j_{i 1}}-x_{i}, x_{j_{i 2}}-x_{i}, \ldots, x_{j_{i k}}-x_{i} xji1−xi,xji2−xi,…,xjik−xi
- 每个边里面加入上一步计算得到的,得到 ( x i , x j i 1 − x i ) , ( x i , x j i 2 − x i ) , … , ( x i , x j i k − x i ) \left(x_{i}, x_{j_{i 1}}-x_{i}\right),\left(x_{i}, x_{j_{i 2}}-x_{i}\right), \ldots,\left(x_{i}, x_{j_{i k}}-x_{i}\right) (xi,xji1−xi),(xi,xji2−xi),…,(xi,xjik−xi)
- 对于上面得到的每个特征用 h θ h_\theta hθ来更新。代码中使用的是卷积核为1x1的Conv2d
- 用max pooling,将以上k的特征整合为一个特征,作为 x i x_i xi的新特征。
Dynamic graph update
在每一层都有不同的图
G
(
l
)
=
(
V
(
l
)
,
E
(
l
)
)
\mathcal{G}^{(l)}=\left(\mathcal{V}^{(l)}, \mathcal{E}^{(l)}\right)
G(l)=(V(l),E(l)),其中第
l
l
l层的边是由
(
i
,
j
i
1
)
,
…
,
(
i
,
j
i
k
l
)
\left(i, j_{i 1}\right), \ldots,\left(i, j_{i k_{l}}\right)
(i,ji1),…,(i,jikl)组成的,
x
j
i
1
(
l
)
,
…
,
x
j
i
k
(
l
)
\mathbf{x}_{j_{i 1}}^{(l)}, \ldots, x_{j_{i k}}^{(l)}
xji1(l),…,xjik(l)是与
x
i
(
i
)
x_i^{(i)}
xi(i)相离最近的
k
l
k_l
kl个点。也就是说,每一层图也都是不同的,DGCNN学习了如何构建每一层的图。
(大概就是由于
x
j
i
k
(
l
)
\mathbf{x}_{j_{i k}}^{(l)}
xjik(l)在不断的变化,EdgeConv计算得到的特征也都在不断地变化,每一次计算都会得到新的特征,也就是整个图是在动态变化的)
Properties
Permutation Invariance 每一层使用的是对称函数max,因此对点的顺序不敏感。
Translation Invariance 对于变换
T
T
T:
e
i
j
m
′
=
θ
m
⋅
(
x
j
+
T
−
(
x
i
+
T
)
)
+
ϕ
m
⋅
(
x
i
+
T
)
=
θ
m
⋅
(
x
j
−
x
i
)
+
ϕ
m
⋅
(
x
i
+
T
)
\begin{aligned} e_{i j m}^{\prime} &=\boldsymbol{\theta}_{m} \cdot\left(\mathbf{x}_{j}+T-\left(\mathbf{x}_{i}+T\right)\right)+\phi_{m} \cdot\left(\mathbf{x}_{i}+T\right) \\ &=\boldsymbol{\theta}_{m} \cdot\left(\mathbf{x}_{j}-\mathbf{x}_{i}\right)+\boldsymbol{\phi}_{m} \cdot\left(\mathbf{x}_{i}+T\right) \end{aligned}
eijm′=θm⋅(xj+T−(xi+T))+ϕm⋅(xi+T)=θm⋅(xj−xi)+ϕm⋅(xi+T)
令
ϕ
m
=
0
\phi_m=0
ϕm=0则操作是完全置换不变的。
Architecture
Classification
- 4个EdgeConv Layer每层后面各接了一层全连接层,各层神经元个数分别为 ( 64 , 64 , 128 , 256 ) (64,64,128,256) (64,64,128,256)【论文里写的是The four EdgeConv layers use three shared fully-connected layers(64,64,128,256).代码里也是这么写的,然而跟图上好像不太一样hhhhh。emmmmm】,根据每个EdgeConv层的特征重新计算图并用于下一个EdgeConv层,计算k近邻图时 k = 20 k=20 k=20。
- 将各个全连接层的输出concat到一起得到一个 512 512 512维的数据,使用一个全连接层(1024)来综合多尺度的特征(前4层Conv层的输出)
- 用max pooling和sum pooling来对上一层的输出进行处理,并concat到一起
- 然后通过两层全连接层(512,256)来处理全局特征(dropout=0.5)
- 每层都使用了LeakyReLU和batch normalization
Part Segmentation
- 在spatial transformer network后使用了3层EdgeConv Layer
- 使用一层全连接层来对此前的得到的特征进行处理,并参照pointnet的做法进行concat
- 然后将此前得到的特征concat到一起,然后使用3层全连接层(256,256,128)进行处理
- ReLU、batch normalization、dropout的用法与classification一致
Indoor Scene Segmentation
与part segmentation的网络结构差不多,但是没有 categorical vector
[1] Matan Atzmon,Haggai Maron,and Yaron Lipman.2018. Point Convolutional Neural Networks by Extension Operators. ACM Trans. Graph.37,4,Article71(July2018), 12pages. https://doi.org/10.1145/3197517.3201301
CVPR2018 RSNet
(论文链接)(pytorch源码链接)
不同于此前的一些网络在处理无序点云时,主要是采用对称函数进行处理,而得到一个具有排列不变性的网络,RSNet则是采用slice pooling layer将无序的点云进行处理得到有序的特征,然后用RNN处理(RNN的输入是有序序列),再用slice unpooling layer将特征传递到每一个点。作者在论文中对复杂度进行了分析,确识还蛮高效的。
Architecture
对于点云输入数据
X
X
X,通过RSNet得到
Y
=
{
y
1
,
y
2
,
.
.
.
y
i
,
.
.
.
y
n
}
,
y
i
∈
L
Y=\{y_1,y_2,...y_i,...y_n\},y_i\in L
Y={y1,y2,...yi,...yn},yi∈L,即每一个点
x
i
x_i
xi得到一个相应的标签
y
i
y_i
yi。
根据源码net.py的内容:
- 输入点云数据首先经过了1个卷积核大小为 1 × 9 1\times9 1×9的Conv2d和2个卷积核大小为 1 × 1 1\times1 1×1的Conv2d,每一层后面都有用relu和batch normalization,输出通道大小均为64
- 紧接着是根据 x , y , z x,y,z x,y,z三个方向进行切片的Slice pooling layer
- 得到的不同排序的切片集合通过6层双向RNN,输出通道大小分别为(64,512,256,128,128,256)
- 通过RNN得到的特征分别使用slice unpooling layer处理,并对三个分支的得到的特征进行加和
- 加和得到的数据通过三层卷积核大小为
1
×
1
1\times1
1×1的卷积层,输出通道大小为(512,256,13),其中前两层的输出使用了relu,但没有使用batch normalization,最后一层之前使用了dropout。
Independent Feature Extraction
在RSNet中有两个特征提取模块,分别是输入特征模块和输出特征模块。输入特征模块对于输入 X ∈ R n × d i n X\in \mathbb{R}^{n\times d^{in}} X∈Rn×din得到特征 F i n ∈ R n × d i n F^{in}\in \mathbb{R}^{n\times d^{in}} Fin∈Rn×din,输出特征模块对于输入特征 F s u ∈ R n × d s u F^{su}\in \mathbb{R}^{n\times d^{su}} Fsu∈Rn×dsu得到每个点的预测标签。
Local Dependency Module
Slice Pooling Layer
Slice pooling layer的输入为无序的点云数据
F
i
n
=
{
f
1
i
n
,
f
2
i
n
.
.
.
f
n
i
n
}
F^{in}=\{f_1^{in},f_2^{in}...f_n^{in}\}
Fin={f1in,f2in...fnin},首先将点云数据分组到切片中,然后通过在切片中聚合点的特征来为每个切片生成全局表示。切片的方向有
x
,
y
,
z
x,y,z
x,y,z三个,以
z
z
z为例,具体的操做如下图(a):
根据点云在
z
z
z维度分布的范围
[
z
m
i
n
,
z
m
a
x
]
[z_{min},z_{max}]
[zmin,zmax]和超参数
r
r
r进行切片划分,点
x
i
x_i
xi将被划分到第
k
k
k块,其中
k
=
⌊
z
i
−
z
m
i
n
r
⌋
k=\lfloor \frac{z_i-z_{min}}{r}\rfloor
k=⌊rzi−zmin⌋,总共将被划分为
N
=
⌈
z
m
a
x
−
z
m
i
n
r
⌉
N=\lceil \frac{z_{max}-z_{min}}{r}\rceil
N=⌈rzmax−zmin⌉块,可以表示为
S
=
{
S
1
,
S
2
,
.
.
.
S
N
}
S=\{S_1,S_2,...S_N\}
S={S1,S2,...SN},
S
i
S_i
Si表示第
i
i
i个切片的点云集合,然后对每个切片中的数据进行如下操作,最终得到特征向量
F
s
=
{
f
s
1
,
f
s
2
,
.
.
.
f
s
N
}
F^s=\{f^{s1},f^{s2},...f^{sN}\}
Fs={fs1,fs2,...fsN}
f
s
i
=
max
x
j
∈
S
i
{
f
j
i
n
}
f^{s i}=\max _{x_{j} \in S_{i}}\left\{f_{j}^{i n}\right\}
fsi=xj∈Simax{fjin}
Slice Pooling Layer有如下特点:
Oeder and Structure
F
s
F^s
Fs是一个有序且具有一定结构特征的序列,
f
s
1
f^{s1}
fs1到
f
s
N
f^{sN}
fsN分别是点云从下到上的切片,
f
s
i
f^{si}
fsi和
s
s
(
i
−
1
)
s^{s(i-1)}
ss(i−1)是相邻的特征。
Efficiency slice pooling layer的复杂度是
O
(
n
)
O(n)
O(n)
Local context trade-off
RNN
RSNet中使用的是双向RNN units,RNNs得到的输出是 F r = { f r 1 , f r 2 , . . . f r N } F^r=\{f^{r1},f^{r2},...f^{rN}\} Fr={fr1,fr2,...frN}
Slice Unpooling Layer
将一个slice中多个点的特征映射成了一个全局的特征向量,因此这里需要完成映射的逆过程,如上图(b)所示,每个点的特征由其所在slice的全局特征向量表示
一些实验结果: