目录

一. 简介

二. 基础结构

三. 项目代码

四. 实验结果

总结

Reference


最近开始研究点云分析的相关项目,经过文献调研我发现,近几年比较热的方法,基本都是基于深度学习框架设计的。正好我计划在2022年切入点云深度学习这个研究方向,于是我决定创建一个博客专题,翻译和编辑一批具有代表性意义的点云深度学习研究报告,即方便为我自己的研究计划提供素材,又希望能够帮助到有需要的小伙伴参考与学习。如果你对这个专题感兴趣,希望能够关注我的博客,那将是对我创作的最大支持。

作为博客专题的开篇之作,我挑选了一篇极具代表性的工作,即PCPNET来讲解。一方面,该工作和我目前正在推进的一个项目密切相关,具有极大的参考价值;另一方面,该项工作被著名的点云去噪算法PointCleanNet引入并作为基础训练结构,其被证明在点云去噪任务中能够获得非常优秀的性能。因此,我们将该项工作作为开篇,来开启点云深度学习的研究之旅。


一. 简介

对于基于点云的形状分析任务来说,实现对局部形状特征(法向、曲率等)的有效表示是一个基础性问题。局部形状特征的表示受到很多干扰因素影响,包括噪声,动态采样密度,复杂的几何细节以及缺损部分等。这些干扰因素无疑对点云的局部形状特征表示产生影响,进而影响相关应用的性能。要解决这个问题,一般都是利用点云内各个点的局部邻域估计,建立一个隐式曲面表示,以实现对局部特征的模拟。但是,这里存在两个难点:1)点云本身并没有邻接关系,这提高了获得点云的准确1-邻域或局部连续结构的难度;2)实现对局部邻域的估计,一般需要复杂的参数控制,以解决密度与几何特征保持带来的问题,这使得算法的通用性变差,同样的模型,在某些数据上结果不错,但是换了不一样的数据,性能可能会大打折扣。受到文献[2]和[3]的启发,Guerrero在2018年提出一个基于数据驱动的点云神经网络模型,即PCPNet。PCPNet通过建立点云局部区域的深度分析,获得具有较高鲁棒性与精确性的局部形状特征估计结果。该模型最大的优点是不再受限于传统方法基于局部邻域估计与隐式曲面建模的方案,规避了待处理点云本身的质量缺陷,利用外部数据的经验来指导特征分析,以获得性能提升。


二. 基础结构

整体来说,PCPNet的特征训练部分类似于PointNet++,即通过提取一个点以及对应半径范围内的邻点以建立训练Patch。基于Patch,实现对局部几何特征的估计。

第一步,先将输入的点云变换为一个标准的姿态,基于一个空间变换网络[4]来实现。

第二步,对点应用对称函数,解决无序问题。PointNet中已经给出了解决方案:

Hl是patch的一个特征。hl被称为对称方程。方程是标量方程,定义在局部的patch上。Hl可以被直观的理解为顶贴故意在hl上的一个密度估计。相比于pointnet,对称方程为:

FNN2是一个三层的全连接层,函数g能够被理解为一个不太复杂的点集函数。这个计算过程类似于原始pointnet中的h。

第三步,STN2是一个第二个空间变换器,作用于g上。

最后,求和hl,获得:

网络结构如下图所示:

图 2.1 PCPNet算法流程图  


三. 项目代码

项目主页:PCPNet: Learning Local Shape Properties from Raw Point Clouds

代码链接:GitHub - paulguerrero/pcpnet: Pytorch implementation of PCPNet

简单的说一下配置,原项目基于python3.6编写的,python建议0.4.0+,我使用的是0.4.1,可以直接用conda命令完成下载:conda install pytorch=0.4.1 cuda90 -c pytorch

其他的一些包版本参考下图:

项目的核心代码为pcpnet.py,存储了PCPNet网络层的结构,主要的类包括:

class STN(nn.Module)
class QSTN(nn.Module)
class PointNetfeat(nn.Module)
class PCPNet(nn.Module)
class MSPCPNet(nn.Module)

这里的MSPCONet使用的是多尺度训练方法。默认的化还是使用单一尺度的PCPNet

因为我对Pytorch也是刚开始学,很多的细节也不太懂。我只是简单的梳理了一下结构,大致的网络模型大家的逻辑整理如下:

#feat部分应该是从STN1到FNN2的主体结构
self.feat = PointNetfeat(num_points=num_points,num_scales=1,use_point_stn=use_point_stn,use_feat_stn=use_feat_stn,sym_op=sym_op,get_pointfvals=get_pointfvals,point_tuple=point_tuple)#从这里考试应该是将特征对称化后,到经过FNN3输出的部分
self.fc1 = nn.Linear(1024, 512)
self.fc2 = nn.Linear(512, 256)
self.fc3 = nn.Linear(256, output_dim)
self.bn1 = nn.BatchNorm1d(512)
self.bn2 = nn.BatchNorm1d(256)
self.do1 = nn.Dropout(p=0.3)
self.do2 = nn.Dropout(p=0.3)

PointNetfeat里边应该包含的就是使用PointNet的部分层,按照论文所说,应该是从STN1到FNN2的部分。FNN就是MLP。接下来展示PointNetfeat的核心代码:

class PointNetfeat(nn.Module):def __init__(self, num_scales=1, num_points=500, use_point_stn=True, use_feat_stn=True, sym_op='max', get_pointfvals=False, point_tuple=1):super(PointNetfeat, self).__init__()self.num_points = num_pointsself.num_scales = num_scalesself.use_point_stn = use_point_stnself.use_feat_stn = use_feat_stnself.sym_op = sym_opself.get_pointfvals = get_pointfvalsself.point_tuple = point_tuple#这里对应的就是原文的STN1和STN2if self.use_point_stn:# self.stn1 = STN(num_scales=self.num_scales, num_points=num_points, dim=3, sym_op=self.sym_op)self.stn1 = QSTN(num_scales=self.num_scales, num_points=num_points*self.point_tuple, dim=3, sym_op=self.sym_op)if self.use_feat_stn:self.stn2 = STN(num_scales=self.num_scales, num_points=num_points, dim=64, sym_op=self.sym_op)#这里对应的就是原文的FNN1self.conv0a = torch.nn.Conv1d(3*self.point_tuple, 64, 1)self.conv0b = torch.nn.Conv1d(64, 64, 1)self.bn0a = nn.BatchNorm1d(64)self.bn0b = nn.BatchNorm1d(64)#这里对应的就是原文的FNN2,k=1024self.conv1 = torch.nn.Conv1d(64, 64, 1)self.conv2 = torch.nn.Conv1d(64, 128, 1)self.conv3 = torch.nn.Conv1d(128, 1024, 1)self.bn1 = nn.BatchNorm1d(64)self.bn2 = nn.BatchNorm1d(128)self.bn3 = nn.BatchNorm1d(1024)if self.num_scales > 1:self.conv4 = torch.nn.Conv1d(1024, 1024*self.num_scales, 1)self.bn4 = nn.BatchNorm1d(1024*self.num_scales)#这里对应的是对特征的对称化方法,取最大或求和if self.sym_op == 'max':self.mp1 = torch.nn.MaxPool1d(num_points)elif self.sym_op == 'sum':self.mp1 = Noneelse:raise ValueError('Unsupported symmetric operation: %s' % (self.sym_op))

似乎这里的顺序和文章中网络的结构顺序有点不一致,但是实际没有影响,因为真正控制参数优化的代码在forward函数里:

import torch.nn.functional as F# mlp (64,64)
x = F.relu(self.bn0a(self.conv0a(x)))
x = F.relu(self.bn0b(self.conv0b(x)))# feature transform
if self.use_feat_stn:trans2 = self.stn2(x)x = x.transpose(2, 1)x = torch.bmm(x, trans2)x = x.transpose(2, 1)
else:trans2 = None# mlp (64,128,1024)
x = F.relu(self.bn1(self.conv1(x)))
x = F.relu(self.bn2(self.conv2(x)))
x = self.bn3(self.conv3(x))# mlp (1024,1024*num_scales)
if self.num_scales > 1:x = self.bn4(self.conv4(F.relu(x)))if self.get_pointfvals:pointfvals = x
else:pointfvals = None # so the intermediate result can be forgotten if it is not needed

四. 实验结果

这个给出原文的两幅实验图作为参考。根据量化的误差色温图可以看到,PCPNet对于局部特征估计任务能够提供不错的计算结果。


总结

总体来说,PCPNet还是基于PointNet建立点云分析框架,以实现对点云的局部几何特征的提取与训练。自然该框架继承了PointNet甚至PointNet++点云分析的优点。但是,我认为该框架对于噪声的处理没有引用额外的模块,这就让整个网络对于噪声数据处理的泛化性能力有所损失。当然,这间接推动了PointCleanNet的提出。即使如此,PCPNet想比传统的MLS或其他局部几何特征分析来说,依然能够获得显著的性能提升。


Reference

[1] P. Guerrero, Y. Kleiman, M. Ovsjanikov, et al. Pcpnet learning local shape properties from raw point clouds[C]//Computer Graphics Forum. 2018, 37(2): 75-85.

[2] A. BOULCH, R. MARLET. Deep learning for robust normal estimation in unstructured point clouds. Computer Graphics Forum 35, 5(2016), 281–290.

[3] QI C. R., YI L., SU H., GUIBAS L. J.: Pointnet++: Deep hierarchical feature learning on point sets in a metric space. arXiv preprint arXiv:1706.02413 (2017). 3

[4] M. JADERBERG, K. SIMONYAN K, A. ZISSERMAN, K. KAVUKCUOGLU. Spatial transformer networks. In Proc. NIPS. 2015, pp. 2017–2025. 4.

点云深度学习系列博客(一): 点云特征学习网络PCPNet相关推荐

  1. 点云深度学习系列博客(二): 点云配准网络PCRNet

    目录 一. 简介 二. 基础结构 三. 项目代码 四. 实验结果 总结 Reference 今天的点云深度学习系列博客为大家介绍一个用于点云配准的深度网络:PCRNet [1].凡是对点云相关应用有些 ...

  2. PX4代码学习系列博客(6)——offboard模式位置控制代码分析(之前转载过,这是第二次转载了)

    我刚刚发现这篇文章去年八月份的时候转载过一次了 https://blog.csdn.net/sinat_16643223/article/details/107874349 转载自:https://b ...

  3. 点云深度学习系列博客(四): PointNet代码精讲

    目录 1. 代码解析 1.1 初始化 1.2 数据载入 1.3 模型载入 1.4 训练代码 2. 实验结果 Reference 最近开始上手点云深度学习项目,相比之前纸上谈兵的阶段,此时我将把更多的精 ...

  4. 【技术博客】2020.04.28-简单塔防游戏和棋牌游戏构架学习 ——学习系列博客(一)构架初探

    序言,保卫萝卜项目作为自己学习整体游戏项目的开始,还是很有收获的. 项目初步实现了分管关卡地图编辑.场景结构.关卡选择.游戏地图等主要功能,同时内部构架采用了MVC加单例的构架,对我这种初学者还是很有 ...

  5. android中页面自动跳转,【学习笔记-安卓开发】8. Android Studio如何实现页面自动跳转(安卓学习系列博客)...

    先将上上一篇博客中写在页面里的button以及相关代码删除 8.如何让页面自动跳转 在安卓开发中有一个非常重要的Handler 当我们输入Handler会出现两个提示,一个是os中的,一个是loggi ...

  6. PX4代码学习系列博客(5)——在px4中添加自己的模块

    怎么在px4中添加自己的模块 在"px4固件目录结构和代码风格"这一节,曾经说过NuttX是一个实时的嵌入式系统,上面可以像windows那样运行程序.那既然是应用程序,那我们应该 ...

  7. Nginx + Tomcat + Session学习 - ﹎敏ō - 博客园

    Nginx + Tomcat + Session学习 - ﹎敏ō - 博客园 Nginx + Tomcat + Session学习 - ﹎敏ō - 博客园 Nginx + Tomcat + Ses ...

  8. 系统学习深度学习(博客转载地址)

    转载深度学习学习系列的一些文章 1. 系统学习深度学习(一) --深度学习与神经网络关系 https://blog.csdn.net/app_12062011/article/details/5431 ...

  9. 堪比培训机构的MySQL系列博客

    这个blog,我整理了我之前写的MySQL开发系列和MySQL运维系列,知识丰富程度堪比培训机构 个人能力有限,如有错误的地方,欢迎指正. 文章目录 一.MySQL开发系列 1.1 MySQL 行转列 ...

最新文章

  1. 车模换几代了,电池什么时候换?
  2. 图解手动全面检查管理本机端口
  3. c语音 udp最大长度_c语言udp自定义头文件 网络通信程序
  4. Segments POJ 3304 直线与线段是否相交
  5. leetcode 之Single Number(13)
  6. codis集群部署实战
  7. python内置函数用来返回_Python内置函数用法
  8. JavaScript 经典实例日常收集整理(常用经典)
  9. 配置FTP服务2(vsftpd 配置虚拟账号)
  10. C++ 通讯录设计(四)
  11. POI导出Word插入复选框
  12. 华为交换机关闭网口_关闭端口的命令 怎么开启华为交换机关闭端口,命令谁知道啊。...
  13. Bjui框架--日期选择器
  14. 每日学习笔记(13)
  15. 关于git reset --hard这个命令的惨痛教训
  16. 阿里云的esc服务器介绍
  17. 数据库SQL 某字段按首字母排序
  18. 深度学习之五:稀疏编码
  19. 查看电脑支持最大内存和内存条型号
  20. 免费的PDF在线合并工具,拿走不谢!

热门文章

  1. 橙游资讯正式发布V1.0
  2. 免费恢复删除文件的办法(效果与diskGenius类似)
  3. AEJoy —— 值得收藏的常用 29 个 AE 表达式实例
  4. Lazarus - Free Pascal IDE 窗口合并
  5. 密码学(Crypto)在线解密网站大全
  6. 用移动激光扫描来估计树干直径的分割和树干校准法
  7. 裸辞创业,挣了一千万!有钱人,都不想告诉你的5个秘密
  8. 高等学校数字校园建设目标和原则
  9. C++成员是指针的处理(二)-引用技术
  10. UCB CS61A | SICP C1