pointnet.pytorch代码解析

代码运行

Training

cd utils
python train_classification.py --dataset <dataset path> --nepoch=<number epochs> --dataset_type <modelnet40 | shapenet>
python train_segmentation.py --dataset <dataset path> --nepoch=<number epochs>

运行结果

  1. Classification on ShapeNet

    epoch = 10 Overall Acc
    Original implementation N/A
    this implementation(无 feature transform) 95.6
    this implementation(有 feature transform) 92.97
  2. Segmentation on ShapeNet

dataset代码

  1. 读取的数据格式

    ShapeNetDataset():默认读取分割数据,返回值d:点云个数*(点云数据ps,标签seg)

    数据ps:torch.Size([2500, 3]) torch.FloatTensor ,一个点云有2500个点,每个点3个特征

    标签seg:torch.Size([2500]) torch.LongTensor,每个点都有一个标签

    代码及注释如下:

    if __name__ == '__main__':
    dataset = sys.argv[1] # 运行命令中传入的第一个参数
    datapath = sys.argv[2] # 运行命令中传入的第二个参数 if dataset == 'shapenet':
    # 读取标签为Chair的分割数据
    d = ShapeNetDataset(root = datapath, class_choice = ['Chair'])
    print(len(d)) #2658,共有2658个Chair点云
    ps, seg = d[0]
    print(ps.size(), ps.type(), seg.size(),seg.type())
    # torch.Size([2500, 3]) torch.FloatTensor ,第一个点云有2500个点,每个点3个特征
    # torch.Size([2500]) torch.LongTensor,每个点都有一个标签 d = ShapeNetDataset(root = datapath, classification = True)
    print(len(d))
    ps, cls = d[0]
    print(ps.size(), ps.type(), cls.size(),cls.type())
    # torch.Size([2500, 3]) torch.FloatTensor torch.Size([1]) torch.LongTensor,每个点云一个标签
    # get_segmentation_classes(datapath)
  2. 数据读取

model代码

  1. 网络整体结构

    if __name__ == '__main__':
    # input transform
    sim_data = Variable(torch.rand(32,3,2500)) # 32个点云,3个特征,2500个点
    trans = STN3d()
    out = trans(sim_data) # stn torch.Size([32, 3, 3]),返回3x3的输入变换矩阵
    print('stn', out.size())
    print('loss', feature_transform_regularizer(out)) # feature transform
    sim_data_64d = Variable(torch.rand(32, 64, 2500))
    trans = STNkd(k=64)
    out = trans(sim_data_64d) # stn64d torch.Size([32, 64, 64]),返回64x64的特征变换矩阵
    print('stn64d', out.size())
    print('loss', feature_transform_regularizer(out)) # global feat
    pointfeat = PointNetfeat(global_feat=True)
    out, _, _ = pointfeat(sim_data) # global feat torch.Size([32, 1024]),32个点云,每个有1024维全局特征
    print('global feat', out.size()) # point feat
    pointfeat = PointNetfeat(global_feat=False)
    out, _, _ = pointfeat(sim_data) # point feat torch.Size([32, 1088, 2500]),2500个点,每个点有1024+64维特征
    print('point feat', out.size()) # Classification
    cls = PointNetCls(k = 5)
    out, _, _ = cls(sim_data) # class torch.Size([32, 5]),global feat经过全连接层,得到在5个类别上的概率信息
    print('class', out.size()) # Segmentation
    seg = PointNetDenseCls(k = 3)
    out, _, _ = seg(sim_data) # seg torch.Size([32, 2500, 3]),point feat经过一维卷积,得到在3个类别上概率信息
    print('seg', out.size())
  2. PointNetfeat特征提取网络

    class PointNetfeat(nn.Module):
    '''
    点云的特征提取网络:global feature 和 point features
    '''
    def __init__(self, global_feat = True, feature_transform = False):
    super(PointNetfeat, self).__init__()
    self.stn = STN3d()
    self.conv1 = torch.nn.Conv1d(3, 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)
    self.global_feat = global_feat
    self.feature_transform = feature_transform
    if self.feature_transform:
    self.fstn = STNkd(k=64) def forward(self, x):
    n_pts = x.size()[2]
    trans = self.stn(x)
    x = x.transpose(2, 1)
    x = torch.bmm(x, trans) # 乘以3x3变换矩阵
    x = x.transpose(2, 1)
    x = F.relu(self.bn1(self.conv1(x))) if self.feature_transform: # 特征变换,64x64矩阵
    trans_feat = self.fstn(x)
    x = x.transpose(2,1)
    x = torch.bmm(x, trans_feat)
    x = x.transpose(2,1)
    else:
    trans_feat = None pointfeat = x # nx64的点特征
    x = F.relu(self.bn2(self.conv2(x)))
    x = self.bn3(self.conv3(x))
    x = torch.max(x, 2, keepdim=True)[0] # Maxpool
    x = x.view(-1, 1024)
    if self.global_feat:
    return x, trans, trans_feat # x:mx1x1024的global feature,两个变换矩阵
    else:
    x = x.view(-1, 1024, 1).repeat(1, 1, n_pts)
    return torch.cat([x, pointfeat], 1), trans, trans_feat # global feature+point features = nx1088的点特征矩阵

pointnet.pytorch代码解析的更多相关文章

  1. 【论文笔记】AutoML for MCA on Mobile Devices——论文解读与代码解析

    理论部分 方法介绍 本节将详细介绍AMC的算法流程.AMC旨在自动地找出每层的冗余参数. AMC训练一个强化学习的策略,对每个卷积层会给出其action(即压缩率),然后根据压缩率进行裁枝.裁枝后,A ...

  2. VBA常用代码解析

    031 删除工作表中的空行 如果需要删除工作表中所有的空行,可以使用下面的代码. Sub DelBlankRow() DimrRow As Long DimLRow As Long Dimi As L ...

  3. [nRF51822] 12、基础实验代码解析大全 · 实验19 - PWM

    一.PWM概述: PWM(Pulse Width Modulation):脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形. PWM 的几个基本概念: 1) 占空比:占空比是指 ...

  4. [nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写

     一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识 ...

  5. [nRF51822] 10、基础实验代码解析大全 · 实验15 - RTC

    一.实验内容: 配置NRF51822 的RTC0 的TICK 频率为8Hz,COMPARE0 匹配事件触发周期为3 秒,并使能了TICK 和COMPARE0 中断. TICK 中断中驱动指示灯D1 翻 ...

  6. [nRF51822] 9、基础实验代码解析大全 · 实验12 - ADC

    一.本实验ADC 配置 分辨率:10 位. 输入通道:5,即使用输入通道AIN5 检测电位器的电压. ADC 基准电压:1.2V. 二.NRF51822 ADC 管脚分布 NRF51822 的ADC ...

  7. java集合框架之java HashMap代码解析

     java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...

  8. Kakfa揭秘 Day8 DirectKafkaStream代码解析

    Kakfa揭秘 Day8 DirectKafkaStream代码解析 今天让我们进入SparkStreaming,看一下其中重要的Kafka模块DirectStream的具体实现. 构造Stream ...

  9. linux内存管理--slab及其代码解析

    Linux内核使用了源自于 Solaris 的一种方法,但是这种方法在嵌入式系统中已经使用了很长时间了,它是将内存作为对象按照大小进行分配,被称为slab高速缓存. 内存管理的目标是提供一种方法,为实 ...

随机推荐

  1. 【题解】coin HDU2884 多重背包

    题目 Coins Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  2. Keyboarding(信息学奥赛一本通-T1452)

    [题目描述] 出自 World Final 2015 F. Keyboarding 给定一个 r 行 c 列的在电视上的"虚拟键盘",通过「上,下,左,右,选择」共 5 个控制键, ...

  3. Windows10 准备/安装Flutter研发环境

    Flutter简介 Flutter 是 Google 开源的 UI 工具包,帮助开发者通过一套代码库高效构建多平台精美应用,支持移动.Web.桌面和嵌入式平台. Flutter 中国 安装Flutte ...

  4. 垃圾处理器-CMS

    一.简介 CMS垃圾收集器是一款用于老年代的,使用复制-清除-整理算法的垃圾收集器. 二.GC阶段 1.初始化标记(STW) 暂停应用程序线程,遍历 GC ROOTS 直接可达的对象并将其压入标记栈( ...

  5. ps 快速去掉不需要的部分

    1.打开图片---使用套索工具将不需要的圈起来----右键填充--直接点击确定就可以了

  6. Mweb发布blog到各博客平台

    Mweb发布blog到各博客平台 主流博客平台 博客平台 博客园 CSDN 51CTO 博客类型 MetaWeblog API MetaWeblog API MetaWeblog API 博客网址 h ...

  7. AcWing 201. 可见的点

    在一个平面直角坐标系的第一象限内,如果一个点(x,y)与原点(0,0)的连线中没有通过其他任何点,则称该点在原点处是可见的. 编写一个程序,计算给0<x,y<=n定整数N的情况下,满足的可 ...

  8. consul 多节点/单节点集群搭建

    三节点配置 下载安装包 mkdir /data/consul mkdir /data/consul/data curl -SLO https://github.com/consul/1.9.5/con ...

  9. Python 脚本退出

    return:在定义函数时从函数中返回一个函数的返回值,终止函数的执行. os._exit(),sys.exit(),exit(),quit()都能够退出当前执行脚本,差别在于os._exit()直接 ...

  10. 你觉得我的这段Java代码还有优化的空间吗?

    上周,因为要测试一个方法的在并发场景下的结果是不是符合预期,我写了一段单元测试的代码.写完之后截了个图发了一个朋友圈,很多人表示短短的几行代码,涉及到好几个知识点. 还有人给出了一些优化的建议.那么, ...