【三维语义分割模型】DGCNN

 【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。   

参考书籍:《人工智能点云处理及深度学习算法》

 本文为专栏《Python三维点云实战宝典》系列文章,专栏介绍地址“https://blog.csdn.net/suiyingy/article/details/124017716”。配套书籍《人工智能点云处理及深度学习算法》提供更加全面和系统的解析。

1 模型结构

        DGCNN发表于TOG 2019《Dynamic Graph CNN for Learning on Point Clouds》,论文地址为“https://arxiv.org/abs/1801.07829”。从论文题目上来看,模型似乎采用了图神经网络(GCN)。DGCNN中的图实际上是指运用点与点之间相对特征来进行点云特征提取,提取方式仍然采用的是卷积网络。因而,模型并没有采用图神经网络。

        DGCNN的创新点在于点云特征提取时不仅考虑点自身的特征,而且融合了周围点云的相对特征。周围点云相对特征通过EdgeConv卷积来实现。相比于PointNet++模型而言,该模型进一步关注了点云的局部特征,使点云特征提取更加丰富有效,从而提高算法复杂度。DGCNN发布时在点云分割、分类任务中取得了最优水平。

        DGCNN模型的总体结构如下图所示,其主要思路与PointNet++基本一致,包括了最大池化和全局特征拼接等步骤。两者区别在于DGCNN在MLP提取点云特征时使用了周围点云的相对特征。

59b24bc45203405b8f83e6be4f511f1c.png

图DGCNN模型结构

2 EdgeConv卷积

        EdgeConv卷积结构如下图所示,重点用于提取边(edge)特征。PointNet中分组点云特征通过对输入特征分别进行MLP操作得到。EdgeConv输入增加了对点云相对于中心点的特征,从而使得输入特征的局部信息更加丰富。

f880902125bc43ca924fdb9c6ff85d6b.png

图 EdgeConv

EdgeConv卷积过程如下:

  1. 尽量点云分组:采用最近邻方法(KNN)搜索最近的K个点作为相邻点。如果输入点云特征中包含空间坐标信息,那么KNN是采用坐标距离作为相邻点选择依据,否则以全部特征距离作为选择依据。假设输入点云维度为Cin x npoint,那么分组后点云特征维度为Cin x npoint x K。
  2. 中心相对特征提取:将分组内点云特征减去分组中心点特征,得到点云相对中心特征,维度为Cin x npoint x K。
  3. 特征拼接:点云原始输入特征与中心相对特征进行拼接,得到(2 x Cin)x npoint x K维度特征。
  4. MLP特征提取:MLP层第一个卷积的输入通道数为2 x Cin,最后一层卷积输出通道数量为Cout,那么上述拼接特征经过MLP操作后得到Cout x npoint x K维度特征。
  5. 最大池化:Cout x npoint x K维度特征经最大池化后输出Cout x npoint维度特征。最大池化将分组内特征融入进中心点中,同时解决了分组内点云无序性问题。
  6. 深层特征提取:连续EdgeConv串联起来实现深层特征提取,可类比连续传统卷积操作。

3 主干网络

        DGCNN模型主干网络结构采用了3个连续的EdgeConv卷积模块提取不同深度特征,并采用特征拼接实现不同深度特征的融合。模型输入点云维度为4096x9,9个属性维度介绍请参考PointNet++章节。

3.1 EdgeConv1

        第一个EdgeConv卷积模块的输入维度为4096x9,后三维特征为空间坐标,因而采用距离KNN的方式来选择最近邻点。分组最近邻点数量为20。分组后点云特征维度为9x4096x20,与中心点作差得到维度同样为9x4096x20的中心相对特征。两者拼接后得到18x4096x20维度特征,经过MLP卷积Conv2d(18, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)、Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)及最大池化后输出64x4096维度特征。

        关键程序解析如下所示:

idx = self.groupers[i](new_points[..., -3:].contiguous(), new_points[..., -3:].contiguous())[-1]#根据距离KNN筛选K个最近邻点,N x K,4096x20
grouped_results = grouping_operation(new_points_trans, idx)  # (B, C, N) -> (B, C, N, K)#分组,9x4096x20
grouped_results -= new_points_trans.unsqueeze(-1)#与中心点特征的差值,C x N x K,9x4096x20
new_points = new_points_trans.unsqueeze(-1).repeat(1, 1, 1, grouped_results.shape[-1])#中心点特征,9x4096x20
new_points = torch.cat([grouped_results, new_points], dim=1)#特征拼接,(2 x C)x N x K,18x4096x20
# (B, mlp[-1], N, K)
new_points = self.mlps[i](new_points)#64x4096x20
# (B, mlp[-1], N)
new_points = self._pool_features(new_points)#最大池化,64x4096
#MLP
DGCNNGFModule(
  (groupers): ModuleList(
    (0): QueryAndGroup()
  )
  (mlps): ModuleList(
    (0): Sequential(
      (layer0): ConvModule(
        (conv): Conv2d(18, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (activate): LeakyReLU(negative_slope=0.2, inplace=True)
      )
      (layer1): ConvModule(
        (conv): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (activate): LeakyReLU(negative_slope=0.2, inplace=True)
      )
    )
  )
)

3.2 EdgeConv2

        第二个EdgeConv卷积模块的输入是第一个EdgeConv的输出,维度为4096x64,特征不含点云坐标,因而采用全部特征KNN的方式来选择最近邻点。分组最近邻点数量为20。分组后点云特征维度为64x4096x20,与中心点作差得到维度同样为64x4096x20的中心相对特征。两者拼接后得到128x4096x20维度特征,经过MLP卷积Conv2d(128, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)、Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)及最大池化后输出64x4096维度特征。

3.3 EdgeConv3

        第三个EdgeConv卷积模块的输入是第二个EdgeConv的输出,维度为4096x64,特征不含点云坐标,因而采用全部特征KNN的方式来选择最近邻点。分组最近邻点数量为20。分组后点云特征维度为64x4096x20,与中心点作差得到维度同样为64x4096x20的中心相对特征。两者拼接后得到128x4096x20维度特征,经过MLP卷积Conv2d(128, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)及最大池化后输出64x4096维度特征。

        三个EdgeConv卷积模块均输出64x4096三个维度特征。DGCNN主干网络最终输出特征gf_points,包括原始点云特征和EdgeConv特征,特征维度分别为4096x9、4096x64、4096x64、4096x64。

3.4 特征融合与结果预测

        三个EdgeConv特征进行拼接得到192x4096维度特征,经过卷积Conv1d(192, 1024, kernel_size=(1,), stride=(1,), bias=False)和最大池化后得到1024维全局特征。由于示例程序仅包含语义分割任务,因而全局特征不包含来自分类网络的全局特征,即少了模型结构中的Categorical vector部分。

        全局特征与三个EdgeConv特征再次拼接得到1216x496维度特征。该特征作为点云语义特征,相当于为每个输入点提取到1216维特征,并用该特征来预测语义类别。

        点云语义特征(1216x4096)经过卷积: Conv1d(1216, 512, kernel_size=(1,), stride=(1,), bias=False)、Conv1d(512, 256, kernel_size=(1,), stride=(1,), bias=False)和Conv1d(256, 13, kernel_size=(1,), stride=(1,))得到13x4096维预测结果。每个点分别对13个类别进行预测。

        关键示例程序及参数配置如下所示。

#特征融,Point feature aggregation module
fa_points = self.FA_module(gf_points)
new_points = torch.cat(points[1:], dim=-1)#4096x64x3,4096x192,不同网络深度特征进行拼接融合
new_points = new_points.transpose(1, 2).contiguous()  # (B, C, N),192x4096
new_points = self.mlps(new_points)#1024x4096
new_fa_points = new_points.max(dim=-1, keepdim=True)[0]#最大池化,1024x1
new_fa_points = new_fa_points.repeat(1, 1, new_points.shape[-1])#1024x4096,全局特征
new_points = torch.cat([new_fa_points, new_points_copy], dim=1)#全局特征与局部特征拼接,1216x4096
fp_points = self.FP_module(fa_points)#4096x512
fp_points = fp_points.transpose(1, 2).contiguous()#512x4096
output = self.pre_seg_conv(fp_points)#256x4096
output = self.cls_seg(output)#13x4096
DGCNNHead(
  (loss_decode): CrossEntropyLoss(avg_non_ignore=False)
  (conv_seg): Conv1d(256, 13, kernel_size=(1,), stride=(1,))
  (dropout): Dropout(p=0.5, inplace=False)
  (FP_module): DGCNNFPModule(
    (mlps): Sequential(
      (layer0): ConvModule(
        (conv): Conv1d(1216, 512, kernel_size=(1,), stride=(1,), bias=False)
        (bn): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (activate): LeakyReLU(negative_slope=0.2, inplace=True)
      )

3.5 损失函数

        DGCNN模型损失函数仅包含语义分割损失,损失函数类型为CrossEntropyLoss,语义预测损失函数为CrossEntropyLoss,其输入为13x4096维预测结果和4096个语义标签pts_semantic_mask。

3.6 顶层结构

        DGCNv模型顶层结构主要包括以下两部分:

  1. 主干网络特征提取,采用三个EdgeConv卷积模块提取三组不同尺度特征,见第(3)部分。
  2. 语义分割结果预测,包括特征融合、语义预测和语义分割损失函数计算,见第(4)部分。
def forward_train(self, points, img_metas, pts_semantic_mask):
    points_cat = torch.stack(points)#输入点云坐标及属性 4096x9
    pts_semantic_mask_cat = torch.stack(pts_semantic_mask) #输入点云语义类别标签,即每个点所属类别
    # extract features using backbone
    x = self.extract_feat(points_cat)
    losses = dict()
    loss_decode = self._decode_head_forward_train(x, img_metas, pts_semantic_mask_cat)
    losses.update(loss_decode)
    return losses

4 模型训练

        DGCNN模型官方程序地址为“https://github.com/zhangjian94cn/dgcnn”,而本节基于mmdetection3d框架中的实现程序进行介绍,其输入数据集为S3DIS。模型训练命令为“python tools/train.py configs/dgcnn/dgcnn_32x4_cosine_100e_s3dis_seg-3d-13class-area1.py”。运行训练命令可得到如图所示训练结果。

c933585a043846daa17ac1858814a0bc.png

5【python三维深度学习】python三维点云从基础到深度学习_python3d点云从基础到深度学习-CSDN博客

【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。  

更多python与C++技巧、三维算法、深度学习算法总结、大模型请关注我的博客,欢迎讨论与交流:https://blog.csdn.net/suiyingy,或”乐乐感知学堂“公众号。Python三维领域专业书籍推荐:《人工智能点云处理及深度学习算法》。

 本文为专栏《Python三维点云实战宝典》系列文章,专栏介绍地址“https://blog.csdn.net/suiyingy/article/details/124017716”。配套书籍《人工智能点云处理及深度学习算法》提供更加全面和系统的解析。

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coding的叶子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值