ubuntu安装 veloview_Pointnet+Frustum-Pointnet复现(Pytorch1.3+Ubuntu18.04)

1.数据集和预处理

1.1 ModelNet40

ModelNet40是一个大规模3D CAD数据集,始于3D ShapeNets: A Deep Representation for Volumetric Shapes

Zhirong,创建初衷是为了学习到能良好捕捉类内差别的3D表示,比当时最新的数据集大22倍。包含151,128个3D CAD模型和660个不同类别,如下图。

作者在实验时仅选取了40个类别,每个类别各100个不同的CAD模型,得到4000个CAD模型。(但我下载出来的ModelNet40并不是4000个CAD模型,而是训练集有9843个,测试集有2468个,而且类内数量不同)

1.1.1 ModelNet10

ModelNet10选取了对应于NYU RGB-D数据集的其中10个类别。

1.1.2 原始数据分析和可视化

这里CAD模型是.off格式,可以在ubuntu上用meshlab进行可视化,可以旋转缩放。

比如airplane_0001.off

OFF

90714 104773 0

20.967 -26.1154 46.5444

21.0619 -26.091 46.5031

-1.08889 46.8341 38.0388

3 24 25 26

3 25 24 27

...

3 90711 90710 90713

第二行三个参数表示有90714个顶点,104773个面,0个边。

然后是90714行,每行是点的坐标。

最后是104773行,每行表示面,3指3个点,24 25 26指点的索引。

在meshlab中可以看到:

Pointet官方提供的数据是已经处理过的.h5格式,而非ModelNet40的.OFF,而且并没有给出读取OFF并写入.h5的代码,却有读取ply的代码。

以其中一个ply_data_train0.h5为例,查看其中的数据

import numpy as np

import h5py

import os

#example of a single ply_data_train0.h5

f = h5py.File('modelnet40_ply_hdf5_2048/ply_data_train0.h5', 'r')

dset = f.keys()#

data = f['data'][:]#(2048, 2048, 3),dtype=float32,min=-0.9999981,max=0.9999962,mean=2.1612625e-09

faceId = f['faceId'][:]#(2048, 2048),dtype=int32,min=0,max=1435033

label = f['label'][:]#(2048,1),dtype=uint8,min=0,max=39

normal = f['normal'][:]#(2048, 2048, 3),dtype=float32,min=-1.0,max=1.0,mean=-0.0041686897

对于此,PointNet论文中已经有所解释,

We uniformly sample 1024 points on mesh faces according to face area and normalize them into a unit sphere.During training we augment the point cloud on-the-fly by randomly rotating the object along the up-axis and jitter the position of each points by a Gaussian noise with zero mean and 0.02 standard deviation.(在网格面上均匀采样1024个点,标准化为单位圆。训练时增强数据:一是沿up-axis随机旋转,二是点云抖动,对每个点增加一个噪声位移,噪声的均值为0,标准差为0.02)

可以推理出,data是从均匀采样后且标准化为单位圆后的2048个点,faceId是2048个点对应的面的序号,label是类别标签,normal是法向量。为了验证data是否已标准化,我做了以下验证,求点云的直径,标准化后应该为1。可以看出已经很接近1了(但不清楚为什么有点误差)。

>>> np.max(np.sqrt(np.sum(abs(data[1])**2,axis=-1)))

0.94388014

>>> np.max(np.sqrt(np.sum(abs(data[2])**2,axis=-1)))

0.9544609

可以看出normal确实是对data标准化为单位圆后的结果。这里对标准化的方法进一步分析, pointnet/utils/pc_util.py 中有以下代码,可以直接使用。这里标准化是用点云/直径的方式,如果用min-max标准化会导致变形。

# Normalize the point cloud

# We normalize scale to fit points in a unit sphere

if normalize:

centroid = np.mean(points, axis=0)

points -= centroid

furthest_distance = np.max(np.sqrt(np.sum(abs(points)**2,axis=-1)))

points /= furthest_distance

接下来回来继续看Pointnet官方,整个文件夹一共有7个.h5文件,应该包括了整个训练集和测试集。

# all .h5

datapath = 'modelnet40_ply_hdf5_2048'

for root, dirs, files in os.walk(datapath):

for _f in files:

if(_f.endswith('.h5')):

f = h5py.File(os.path.join(datapath,_f), 'r')

dset = f.keys()

data = f['data'][:]

print(_f,data.shape)

'''Results

ply_data_train1.h5 (2048, 2048, 3)

ply_data_test0.h5 (2048, 2048, 3)

ply_data_train2.h5 (2048, 2048, 3)

ply_data_test1.h5 (420, 2048, 3)

ply_data_train3.h5 (2048, 2048, 3)

ply_data_train4.h5 (1648, 2048, 3)

ply_data_train0.h5 (2048, 2048, 3)

可以看到,train有5个.h5,一共是9840个(2048,3)维的点,而test有2个.h5,一共有2468个点,与论文里说的一致。

1.1.3 随机采样

“在网格面上均匀采样1024个点,标准化为单位圆。”我的代码如下(由于pointnet没给采样代码,这里先用最简单的随机采样进行实现):

npoints = 1024

points = points_unit_sphere

choice = np.random.choice(len(faces), npoints, replace=True)

idxs = faces[choice,1:]

points_subset = np.mean(points[idxs],axis=1)

pyplot_draw_point_cloud(points_subset,'points_subset')

运行结果:

也可以直接从N个顶点中选1024个,有的人是这么实现的,不知道会不会影响结果:

points = points_unit_sphere

choice = np.random.choice(len(points), npoints, replace=True)

points_subset = points[choice, :]

pyplot_draw_point_cloud(points_subset,'points_subset')

运行结果:

1.1.4 最远点采样

后来发现随机采样效果很差,于是做了以下最远点采样的可视化。(最远点采样也是均匀采样的一种)

最远点采样的思想很简单,即一个一个选点,要求当前点的选取与上一个点的距离最大;但速度也比较慢,从151185个点采样到1024要花Time 3.887915030005388s,相比随机采样的Time 0.001566361985169351 s增大了1000倍。代码如下,参考了博客https://blog.csdn.net/weixin_39373480/article/details/88878629#37__330

def farthest_point_sample(xyz, npoint):

N, C = xyz.shape

centroids = np.zeros(npoint)

distance = np.ones(N) * 1e10

farthest = np.random.randint(0, N)# random select one as centroid

for i in range(npoint):

centroids[i] = farthest

centroid = xyz[farthest, :].reshape(1, 3)

dist = np.sum((xyz - centroid) ** 2, -1)

mask = dist < distance

distance[mask] = dist[mask]

farthest = np.argmax(distance)# select the farthest one as centroid

#print('index:%d, dis:%.3f'%(farthest,np.max(distance)))

return centroids

xyz = points.copy()

start = time.perf_counter()

points_farthest_index = farthest_point_sample(xyz,1024).astype(np.int64)

points_farthest = xyz[points_farthest_index,:]

print("%d to %d"%(xyz.shape[0],points_farthest.shape[0]))

print("Time {} s".format(float(time.perf_counter()-start)))

1.1.5 数据增强

Pointnet论文中训练时增强数据:一是沿垂直方向随机旋转,二是点云抖动,对每个点增加一个噪声位移,噪声的均值为0,标准差为0.02,我的代码如下:

def data_aug(self, points):

if self.rotation:

theta = np.random.uniform(0, np.pi * 2)

rotation_matrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])

points[:, [0, 2]] = points[:, [0, 2]].dot(rotation_matrix) # random rotation

if self.jiggle:

points += np.clip(np.random.normal(0, 0.01, size=points.shape),-0.05,0.05) # random jitter

return points

运行结果

1.2 ShapeNet

ShapeNet也是一个大型3D CAD数据集,包含3Million+ models and 4K+ categories。旨在采用一种数据驱动的方法来从各个对象类别和姿势的原始3D数据中学习复杂的形状分布(比如看到杯子侧面就能预测到里面是空心的),并自动发现分层的组合式零件表示。包含的任务有:object category recognition, shape completion, part segmentation,Next-Best-View Prediction, 3D Mesh Retrieval.但是,ShapeNet(这篇文章中)使用的模型采用卷积深度置信网络将几何3D形状表示为3D体素网格上二进制变量的概率分布,而不是像后来出现的PointNet那样直接以点云的原始形式作为输入。

1.2.1 ShapeNet

1.2.2 原始数据分析和可视化

为了方便起见,这里直接用pointnet作者提供的shapenet_part_seg_hdf5_data(346MB)。

test_file = '/home/aming/文档/reproduced/PointNet1_2_pytorch_reproduced/data/ShapeNet/hdf5_data/ply_data_test0.h5'

f = h5py.File(test_file, 'r')

dset = f.keys()#

data = f['data']#(2048, 2048, 3)

label = f['label']#(2048, 1)

pid = f['pid']#(2048, 2048)

points = data[0]

pyplot_draw_p

你可能感兴趣的:(ubuntu安装,veloview)