1.数据集加载

if FLAGS.normal:
assert(NUM_POINT<=10000)
DATA_PATH = os.path.join(ROOT_DIR, 'data/modelnet40_normal_resampled')
TRAIN_DATASET = modelnet_dataset.ModelNetDataset(root=DATA_PATH, npoints=NUM_POINT, split='train', normal_channel=FLAGS.normal, batch_size=BATCH_SIZE)
TEST_DATASET = modelnet_dataset.ModelNetDataset(root=DATA_PATH, npoints=NUM_POINT, split='test', normal_channel=FLAGS.normal, batch_size=BATCH_SIZE)
else:
assert(NUM_POINT<=2048)
TRAIN_DATASET = modelnet_h5_dataset.ModelNetH5Dataset(os.path.join(BASE_DIR, 'data/modelnet40_ply_hdf5_2048/train_files.txt'), batch_size=BATCH_SIZE, npoints=NUM_POINT, shuffle=True)
TEST_DATASET = modelnet_h5_dataset.ModelNetH5Dataset(os.path.join(BASE_DIR, 'data/modelnet40_ply_hdf5_2048/test_files.txt'), batch_size=BATCH_SIZE, npoints=NUM_POINT, shuffle=False)

训练数据(TRAIN_DATASET)是5个.h5格式的文件:

data/modelnet40_ply_hdf5_2048/ply_data_train0.h5
data/modelnet40_ply_hdf5_2048/ply_data_train1.h5
data/modelnet40_ply_hdf5_2048/ply_data_train2.h5
data/modelnet40_ply_hdf5_2048/ply_data_train3.h5
data/modelnet40_ply_hdf5_2048/ply_data_train4.h5

训练之前把5个训练文件的顺序打乱:

if self.shuffle: np.random.shuffle(self.file_idxs)

测试数据(TEST_DATASET)是2个.h5格式的文件:

data/modelnet40_ply_hdf5_2048/ply_data_test0.h5
data/modelnet40_ply_hdf5_2048/ply_data_test1.h5

数据集加载的关键是对数据集进行分批,2048*2048*3---->16*1024*3,16*1024*3,16*1024*3,...

注:2048个对象顺序打乱

modelnet_h5_dataset.py文件:

        data_batch = self.current_data[start_idx:end_idx, 0:self.npoints, :].copy() #这一句是关键语句,从一个.h5文件中的顺序已经打乱过的2048个对象中取出16个对象,每个对象中从2048个点云中取出1024个点云
label_batch = self.current_label[start_idx:end_idx].copy()
self.npoints=1024

按照顺序取1024个点。(按照顺序取的这1024个点,居然很均匀,不知道原因何在?)

注:一个对象的1024个点在训练之前会打乱。

A. 根据2048*2048*3---->16*1024*3,把16*1024*3的前16个对象存入.txt文件,2048*2048*3的前16个对象存入.txt文件,利用CloudCompare对比二者的情况,看下降采样后和降采样前的一个点云对象有什么不同。

B. 以下代码存入后16个对象。(16*1024*3)

for i in range(data_batch.shape[0]):
filename=''.join(["/media/dell/D/qcc/code/pointnet/code/pointnet2-master/data/contemporaryfile/train_",str(i),'.txt'])
np.savetxt(filename, data_batch[i],fmt="%.13f,%.13f,%.13f", delimiter=',')

带上标签:

for i in range(data_batch.shape[0]):
filename=''.join(["/media/dell/D/qcc/code/pointnet/code/pointnet2-master/data/contemporaryfile/train_",str(i),'.txt'])
traindata_and_label = np.column_stack((data_batch[i], np.ones((1024, 1), dtype=int) * label_batch[i])) # np.column_stack将两个矩阵进行组合连接
np.savetxt(filename, traindata_and_label,fmt="%.13f,%.13f,%.13f,%d", delimiter=',')

C. 以下代码存入前16个对象。(16*2048*3)

for i in range(16):
filename=''.join(["/media/dell/D/qcc/code/pointnet/code/pointnet2-master/data/contemporaryfile/initial_train_",str(i),'.txt'])
np.savetxt(filename, self.current_data[i],fmt="%.13f,%.13f,%.13f", delimiter=',')

带上标签:

for i in range(16):
filename=''.join(["/media/dell/D/qcc/code/pointnet/code/pointnet2-master/data/contemporaryfile/initial_train_",str(i),'.txt'])
traindata_and_label=np.column_stack((self.current_data[i], np.ones((2048,1),dtype=int)*self.current_label[i]))#np.column_stack将两个矩阵进行组合连接
np.savetxt(filename, traindata_and_label,fmt="%.13f,%.13f,%.13f,%d", delimiter=',')

D. 对比。

可以看到,第一个好像是躺椅,第二个是钢琴,采样过程暂时还不知道,但是看上去采样很均匀。

--------------------------------------------------------------------------------

#              在此处考虑制作自己的训练数据集。          #

--------------------------------------------------------------------------------

每一个.h5训练或者测试文件中包含2048个对象,每个对象包含2048个点云,每个点云包含x、y、z三维坐标。

在训练之前,会把这2048个对象随机打乱,当然打乱之后,其对象和标签仍然是对应的。

制作h5训练和测试文件的步骤如下:

  1. 运行matlab文件:ready_for_make_hdf5.m ,独立的标线点云对象写入文件。
  2. 运行Python文件:putfilenamesintofile.py,把训练和测试的文件的名字存到一个文件中。
  3. 运行python文件:make_hdf5_c.py ,制作h5文件。
  4. 运行Python文件:putfilenamesintofile.py,把h5文件名字写到一个文件中。
  5. 运行训练文件:train.py

2.训练模型的加载

pointnet2_cls_ssg.py

    l1_xyz, l1_points, l1_indices = pointnet_sa_module(l0_xyz, l0_points, npoint=512, radius=0.2, nsample=32, mlp=[64,64,128], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer1', use_nchw=True) #a
l2_xyz, l2_points, l2_indices = pointnet_sa_module(l1_xyz, l1_points, npoint=128, radius=0.4, nsample=64, mlp=[128,128,256], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer2') #b
l3_xyz, l3_points, l3_indices = pointnet_sa_module(l2_xyz, l2_points, npoint=None, radius=None, nsample=None, mlp=[256,512,1024], mlp2=None, group_all=True, is_training=is_training, bn_decay=bn_decay, scope='layer3') #c

a.

l0_xyz: (16, 1024, 3) 初始的输入点云,16个对象,每个对象有1024个点,每个点有x,y,z三维坐标。

npoint=512: 从1024个点中用最远点采样方法选出512个质心点。

radius=0.2: 采样的球形邻域的半径是0.2m.

nsample=32: 每个质心点周围采样32个点。

返回值:

  • l1_xyz:第二层输入的点云,(16, 512, 3)。第一层设置512个中心点,3是每个中心点的三维坐标
  • l1_points: (16, 512, 128)第一层提取到的local point region的特征, 512个分组(group),每个group有128维的局部小区域特征
  • l1_indices:(16, 512, 32) 512个group,每个group 有32个成员,32表示这32 个points 的下标
# Sample and Grouping layer
if group_all:
nsample = xyz.get_shape()[1].value
new_xyz, new_points, idx, grouped_xyz = sample_and_group_all(xyz, points, use_xyz)
else:
new_xyz, new_points, idx, grouped_xyz = sample_and_group(npoint, radius, nsample, xyz, points, knn, use_xyz)
#找到中心点 (new xyz),每个group的局部特征(new points),每个group对应的下标(idx)
        #new_xyz是最远点采样的返回结果: 16*512*3.

     #idx是球形邻域(r=0.2m)查询到的点的索引.
        #grouped_xyz: 16*512*32*3

        # Point Feature Embedding layer
if use_nchw: new_points = tf.transpose(new_points, [0,3,1,2])
for i, num_out_channel in enumerate(mlp):
new_points = tf_util.conv2d(new_points, num_out_channel, [1,1],
padding='VALID', stride=[1,1],
bn=bn, is_training=is_training,
scope='conv%d'%(i), bn_decay=bn_decay,
data_format=data_format)
if use_nchw: new_points = tf.transpose(new_points, [0,2,3,1])
#pointnet层:对 new points 提取特征的卷积层 # Pooling in Local Regions
# 对每个group的feature进行pooling,得到每个中心点的local points feature
if pooling=='max':
new_points = tf.reduce_max(new_points, axis=[2], keep_dims=True, name='maxpool') elif pooling=='avg':
new_points = tf.reduce_mean(new_points, axis=[2], keep_dims=True, name='avgpool')
elif pooling=='weighted_avg':
with tf.variable_scope('weighted_avg'):
dists = tf.norm(grouped_xyz,axis=-1,ord=2,keep_dims=True)
exp_dists = tf.exp(-dists * 5)
weights = exp_dists/tf.reduce_sum(exp_dists,axis=2,keep_dims=True) # (batch_size, npoint, nsample, 1)
new_points *= weights # (batch_size, npoint, nsample, mlp[-1])
new_points = tf.reduce_sum(new_points, axis=2, keep_dims=True)
elif pooling=='max_and_avg':
max_points = tf.reduce_max(new_points, axis=[2], keep_dims=True, name='maxpool')
avg_points = tf.reduce_mean(new_points, axis=[2], keep_dims=True, name='avgpool')
new_points = tf.concat([avg_points, max_points], axis=-1) # [Optional] Further Processing
if mlp2 is not None:
if use_nchw: new_points = tf.transpose(new_points, [0,3,1,2])
for i, num_out_channel in enumerate(mlp2):
new_points = tf_util.conv2d(new_points, num_out_channel, [1,1],
padding='VALID', stride=[1,1],
bn=bn, is_training=is_training,
scope='conv_post_%d'%(i), bn_decay=bn_decay,
data_format=data_format)
if use_nchw: new_points = tf.transpose(new_points, [0,2,3,1]) new_points = tf.squeeze(new_points, [2]) # (batch_size, npoints, mlp2[-1])
return new_xyz, new_points, idx

这一段带注释的代码参考来源是:https://zhuanlan.zhihu.com/p/57761392


0============================================================0

两条横线之间的内容来自:https://zhuanlan.zhihu.com/p/57761392

0============================================================0

SA(set abstraction)层的解释

1. 改进特征提取方法:pointnet++使用了分层抽取特征的思想,把每一次叫做set abstraction。分为三部分:采样层、分组层、特征提取层。首先来看采样层,为了从稠密的点云中抽取出一些相对较为重要的中心点,采用FPS(farthest point sampling)最远点采样法,这些点并不一定具有语义信息。当然也可以随机采样;然后是分组层,在上一层提取出的中心点的某个范围内寻找最近个k近邻点组成一个group;特征提取层是将这k个点通过小型pointnet网络进行卷积和pooling得到的特征作为此中心点的特征,再送入下一个分层继续。这样每一层得到的中心点都是上一层中心点的子集,并且随着层数加深,中心点的个数越来越少,但是每一个中心点包含的信息越来越多。

2. 解决点云密度不同问题:由于采集时会出现采样密度不均的问题,所以通过固定范围选取的固定个数的近邻点是不合适的。pointnet++提出了两个解决方案。

2.1. 多尺度分组

如上图左所示,在每一个分组层都通过多个尺度(设置多个半径值) 来确定每一个组,并经过 pointnet提取特征之后将多个特征 concat 起来,得到新特征。

2.2. 多分辨率分组

如上图右所示。左边特征向量是通过2个set abstraction后得到的,每次set abstraction的半径不一样。右边特征向量是直接对当前层中所有点进行pointnet卷积得到。并且,当点云密度不均时,可以通过判断当前patch的密度对左右两个特征向量给予不同权重。例如,当patch中密度很小,左边向量得到的信息就没有对所有patch中点提取的特征可信度更高,于是将右特征向量的权重提高。以此达到减少计算量的同时解决密度问题。

一、分类任务

见网络下面的那个分支。

分层抽取特征层 set abstraction layer

主要有以下三个部分组成

  • 1. sample layer: 采样层。得到重要的中心点(使用最远点采样)
  • 2. group layer: 分组层。找到距离中心点附近的k个最近点(使用knn),组成local points region
  • 3. pointnet layer:  特征提取层。对每个local points region提取特征

这样每一层得到的中心点都是上一层中心点的子集,并且随着层数加深,中心点的个数越来越少,但是每一个中心点包含的信息越来越多。

来看代码具体实现。这样的参数设置是SSG(same scale grouping),作者在论文主要提出的是MSG(multi-scale grouping),其实只是参数设置的不同。解释见注释。


点云卷积:

输入:(16,3,512,32)

输出:(16,64,512,32)

(a): 多尺度分组,不同尺度所提取的局部特征concatenate到一起。

(b): 多分辨率分组,左边从输入点云中(最远点采样法)采样一定个数的质心,右边在每个质心周围一定邻域内采样一组点(比如32个)。

    # Set abstraction layers  每个模块中先采样,找邻域,然后用三层1*1卷积构成的全连接层进行特征提取,最后做池化,输出
# Note: When using NCHW for layer 2, we see increased GPU memory usage (in TF1.4).
# So we only use NCHW for layer 1 until this issue can be resolved. 总共用了9个mlp层用于特征提取。
l1_xyz, l1_points, l1_indices = pointnet_sa_module(l0_xyz, l0_points, npoint=512, radius=0.2, nsample=32, mlp=[64,64,128], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer1', use_nchw=True)
l2_xyz, l2_points, l2_indices = pointnet_sa_module(l1_xyz, l1_points, npoint=128, radius=0.4, nsample=64, mlp=[128,128,256], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer2') #b
l3_xyz, l3_points, l3_indices = pointnet_sa_module(l2_xyz, l2_points, npoint=None, radius=None, nsample=None, mlp=[256,512,1024], mlp2=None, group_all=True, is_training=is_training, bn_decay=bn_decay, scope='layer3') #c

b.

l2_xyz:(<tf.Tensor 'layer2/GatherPoint:0' shape=(16, 128, 3) dtype=float32>,  16个对象,每个对象选择128个质心点,每个质心点有x,y,z坐标
 l2_points:<tf.Tensor 'layer2/Squeeze:0' shape=(16, 128, 256) dtype=float32>,  16个对象,每个对象选择128个质心点,256代表局部小区域的特征向量
 l2_indices:<tf.Tensor 'layer2/QueryBallPoint:0' shape=(16, 128, 64) dtype=int32>) ,  16个对象,每个对象选择128个质心点,每个质心点周围选取64个点云,64是点云的索引。

c.
(<tf.Tensor 'layer3/Const:0' shape=(16, 1, 3) dtype=float32>,
 <tf.Tensor 'layer3/Squeeze:0' shape=(16, 1, 1024) dtype=float32>,
 <tf.Tensor 'layer3/Const_1:0' shape=(16, 1, 128) dtype=int64>)

l3_xyz:16个对象,每个对象选择1个质心点,每个质心点有x,y,z坐标

l3_points:16个对象,每个对象选择1个质心点,每个质心点具有1024维特征向量

l3_indices:16个对象,每个对象选择1个质心点,每个质心点周围选取128个点云,128是点云的索引。

3. 分类的整个过程如下:

点云卷积的方法(如何由3维变成64维的):

pointnet++之classification/train.py的更多相关文章

  1. pointnet++之scannet/train.py

    1.作者可能把scannet数据集分成了训练集和测试集并处理成了.pickle文件. 2.在代码运行过程中,作者从.pickle文件中读出训练集1201个场景的x.y.z坐标和测试集312个场景的x. ...

  2. py-faster-rcnn代码阅读1-train_net.py & train.py

    # train_net.py#!/usr/bin/env python # -------------------------------------------------------- # Fas ...

  3. 2011:Audio Classification (Train/Test) Tasks - MIREX Wiki

    Contents [hide] 1 Audio Classification (Test/Train) tasks 1.1 Description 1.1.1 Task specific mailin ...

  4. 论文笔记之:Semi-supervised Classification with Graph Convolutional Networks

    Semi-supervised Classification with Graph Convolutional Networks 2018-01-16  22:33:36 1. 文章主要思想: 2. ...

  5. r-cnn学习(四):train_faster_rcnn_alt_opt.py源码学习

    论文看的云里雾里,希望通过阅读其代码来进一步了解. 参考:http://blog.csdn.net/sloanqin/article/details/51525692 首先是./tools/train ...

  6. 深度学习原理与框架-图像补全(原理与代码) 1.tf.nn.moments(求平均值和标准差) 2.tf.control_dependencies(先执行内部操作) 3.tf.cond(判别执行前或后函数) 4.tf.nn.atrous_conv2d 5.tf.nn.conv2d_transpose(反卷积) 7.tf.train.get_checkpoint_state(判断sess是否存在

    1. tf.nn.moments(x, axes=[0, 1, 2])  # 对前三个维度求平均值和标准差,结果为最后一个维度,即对每个feature_map求平均值和标准差 参数说明:x为输入的fe ...

  7. 深度学习原理与框架-猫狗图像识别-卷积神经网络(代码) 1.cv2.resize(图片压缩) 2..get_shape()[1:4].num_elements(获得最后三维度之和) 3.saver.save(训练参数的保存) 4.tf.train.import_meta_graph(加载模型结构) 5.saver.restore(训练参数载入)

    1.cv2.resize(image, (image_size, image_size), 0, 0, cv2.INTER_LINEAR) 参数说明:image表示输入图片,image_size表示变 ...

  8. 解读tensorflow之rnn 的示例 ptb_word_lm.py

    这两天想搞清楚用tensorflow来实现rnn/lstm如何做,但是google了半天,发现tf在rnn方面的实现代码或者教程都太少了,仅有的几个教程讲的又过于简单.没办法,只能亲自动手一步步研究官 ...

  9. PH_Pooled Featrues Classification MIREX 2011 Submission

    Abstract Principal Mel-Spectrum Components (Feature) Temporal Pooling Functions (Model) Single Hidde ...

随机推荐

  1. java使用jxls导出Excel

    jxls是基于POI的Excel模板导出导入框架.通过使用类似于jstl的标签,有效较少导出Excel的代码量. 1.pom <!-- https://mvnrepository.com/art ...

  2. CentOS7安装Oracle 11g数据库

    转载:https://blog.csdn.net/lia17/article/details/82256565 rpm -ivh --force --nodeps *.rpm 强制装 rpm依赖包下载 ...

  3. SEO-------- 了解

    SEO(Search Engine Optimization) 译为:搜索引擎优化,是一种透过了解搜索引擎的运作规则来调整网站,以及提高目的的网站在有关搜索引擎内的排名方式. 目的:为了让用户更快的搜 ...

  4. WPF 隐藏式控件

    没用Popup用的面板控件,全部代码使用xaml的触发器. 代码: <Grid> <DockPanel> <StackPanel Background=" Do ...

  5. LaTex语法

    排版数学公式是TeX系统设计的初衷,它在LaTeX中占有特殊地位,也是LaTeX最为人所称道的功能之一.基于对MathType排版效果的不满意,以及对公式进行检索的需求,我们使用LaTeX输入数学公式 ...

  6. C# WebAPI 文件在线预览

    最近在写一个移动端API接口,其中有一个需求:接口返回附件url地址让手机端调用实现文件在线预览.大体实现思路:把doc.xls等文本格式文件转换为pdf,转换后的pdf文件存放在服务器上面,方便第二 ...

  7. 基于log4net的日志组件扩展封装,实现自动记录交互日志 XYH.Log4Net.Extend(微服务监控)

    背景: 随着公司的项目不断的完善,功能越来越复杂,服务也越来越多(微服务),公司迫切需要对整个系统的每一个程序的运行情况进行监控,并且能够实现对自动记录不同服务间的程序调用的交互日志,以及通一个服务或 ...

  8. 编译 datax

    datax 是阿里巴巴官方开源的一个数据同步工具,可以用于诸多数据源之间的同步,并且使用简单.效率高. datax 官方有提供编译好的版本,可以直接下载,但是其中包含有 BUG. 我最近遇到的一个问题 ...

  9. Error: Opening Robot Framework log failed on mac jenkins

    For resolve your problem you must : Connect on your jenkins url (http://[IP]:8080/) Click on Manage ...

  10. React中的三大属性

    一.前言: 属性1:state 属性2:props 属性3:ref 与事件处理 二.主要内容: 属性1:state 1,认识: 1) state 是组件对象中最重要的属性,值是一个对象(可以包含多个数 ...