RandLA-net复现(数据集:S3DIS)
1.网络介绍:
这是一种简单高效的神经架构,用于点云分割的深度学习网络模型。它通过对点云数据进行局部聚合和随机采样来处理不同密度和规模的点云,并使用具有全局感知力的特征来进行点云分割任务。RandLA-Net 的核心思想是通过局部区域特征聚合和多尺度特征提取来处理点云数据。它首先将点云划分为不同的局部区域,然后对每个局部区域内的点进行特征聚合。之后,它通过多层的神经网络对聚合后的局部特征进行多尺度特征提取,以获得具有全局感知力的特征表示。最后,通过一个全连接层对每个点进行分类或分割。RandLA-Net 在点云分割任务中具有较好的性能,能够处理大规模的点云数据,并且在保留局部细节的同时具备全局感知力。它在场景分割、目标检测和语义分割等领域都有广泛的应用。
2.环境配置以及数据准备工作:
为了复现这个网络,本次实验采用的是RTX 2080 Ti(11GB),配置的虚拟环境为python3.6,linux系统下的Ubuntu18.04,cuda版本为10.0,cudnn为7.6.5,tensorflow的gpu版本为1.15.0,可以在此环境下跑通。
具体环境配置就按照github上的步骤来就行:
1.克隆存储库:
git clone --depth=1 https://github.com/QingyongHu/RandLA-Net && cd RandLA-Net
2.设置python环境:
conda create -n randlanet python=3.5
source activate randlanet
pip install -r helper_requirements.txt
sh compile_op.sh
注意:
(1)在配置环境本人也花了好几天时间走了很多弯路,主要就是针对RTX30.x系列的显卡,无法和tf1.x版本适配导致gpu显存占有但是使用率为0,所以更换了RYX20系列的显卡解决了gpu无法使用的问题。
(2)针对github上的安装依赖,无法和tf2.0以上的版本兼容,所以只能是安装tf1.x版本的 。
pip install -r helper_requirements.txt
3.数据集准备:
将S3DIS数据集拷贝或者迁移到一个名为“data“的文件夹下面(自己创建一个文件夹),路径在RandLA-Net-master文件夹下 ,因为我是在服务器上,所以自带S3DIS数据集的安装包,如图:
在终端进入虚拟环境(我是py36),再进入指定目录文件夹下,解压S3DIS数据包(过程大概五分钟左右)
conda activate py36
cd autodl-tmp
cd RandLA-Net-master
cd data
unzip Stanford3dDataset_v1.2_Aligned_Version.zip
得到下面的结果:
4.数据集格式转换:
要在RandLa-Net-master这个文件夹下,在转换之前需要修改data_prepare_s3dis.py为自己的路径
python utils/data_prepare_s3dis.py
上一步完成后会得到下面两个文件夹,一定要记住放在S3DIS文件夹下面,要不然会报错!
5.修改代码:
首先修改main_S3DIS.py,更改自己的路径:
要是调整参数,可以在helper_tool.py下更改参数设置,具体情况根据电脑配置选择。
3.开始训练和测试:
开始六折交叉验证:
sh jobs_6_fold_cv_s3dis.sh
这个过程很漫长,对六个区域分别进行训练和测试,预计大概三十多个小时左右。
过程会产生一些训练日志和文件:
训练完成后,将/test文件夹下面的所以ply文件复制移到S3DIS文件夹下,创建一个文件夹命名为:results,将ply文件放里面,计算最终的平均 IoU 结果:
python utils/6_fold_cv.py
4.结果可视化:
对于这一步也是请教了师兄,如果你想要直接显示的话,可以修改代码,在autodl-tmp/RandLA-Net-master/utils/6_fold_cv.py下:
将visualization改为True
我是在pycharm下,将test的ply文件进行格式转换后利用open3d库进行可视化,以下仅供参考:
import numpy as np
from helper_ply import read_ply,write_ply
original_data = read_ply('C:\\RandLA-Net-master\\data\\S3DIS\\original_ply\\Area_1_conferenceRoom_1.ply')
points = np.vstack((original_data['x'], original_data['y'], original_data['z'])).T
file_name='C:\\RandLA-Net-master\\data\\S3DIS\\results\\Area_1_conferenceRoom_1.ply'
pred_data = read_ply(file_name)
pred = pred_data['pred']
# label = pred_data['label']
labels = original_data['class']
pred -= 1
yuce,yucecount=np.unique(pred, return_counts=True)
write_ply('C:\RandLA-Net-master\预测area_1', (points, pred), ['x', 'y', 'z', 'class'])
上面这个过程是将原始ply文件的xyz坐标和网络预测后的标签值进行合并,得到xyzc格式的文件,如果你想显示原始ply文件就将下面代码改为:
write_ply('C:\RandLA-Net-master\预测area_1', (points, labels), ['x', 'y', 'z', 'class'])
如果要得到预测的ply文件:
write_ply('C:\RandLA-Net-master\预测area_1', (points, pred), ['x', 'y', 'z', 'class'])
接下来进行可视化:
import open3d as o3d
import numpy as np
from helper_ply import read_ply
def draw_pc(pc_xyzrgb):
# only visualize a number of points to save memory
num_pts = np.shape(pc_xyzrgb)[0]
pc = o3d.geometry.PointCloud()
pc.points = o3d.utility.Vector3dVector(pc_xyzrgb[:, 0:3])
if pc_xyzrgb.shape[1] == 3:
o3d.visualization.draw_geometries([pc])
return 0
if np.max(pc_xyzrgb[:, 3:6]) > 20: ## 0-255
pc.colors = o3d.utility.Vector3dVector(pc_xyzrgb[:, 3:6] / 255.)
else:
pc.colors = o3d.utility.Vector3dVector(pc_xyzrgb[:, 3:6])
o3d.geometry.PointCloud.estimate_normals(pc)
o3d.visualization.draw_geometries([pc], width=1000, height=1000)
return 0
def draw_pc_sem_ins(pc_xyz, pc_sem_ins, dataset='S3DIS'):
if dataset == 'S3DIS':
plot_colors = [[0, 0, 0],
[233, 229, 107],
[95, 156, 196],
[81, 163, 148],
[241, 149, 131],
[77, 174, 84],
[108, 135, 75],
[79, 79, 76],
[41, 49, 101],
[223, 52, 52],
[41, 49, 101],
[223, 52, 52],
[89, 47, 95],
[81, 109, 114],
[233, 233, 229]
]
ins_colors = plot_colors
sem_ins_labels = np.unique(pc_sem_ins)
print(sem_ins_labels)
sem_ins_bbox = []
Y_colors = np.zeros((pc_sem_ins.shape[0], 3))
for id, semins in enumerate(sem_ins_labels):
valid_ind = np.argwhere(pc_sem_ins == semins)[:, 0]
if semins <= -1:
tp = [0, 0, 0]
else:
if plot_colors is not None:
tp = ins_colors[semins]
else:
tp = ins_colors[id]
Y_colors[valid_ind] = tp
### bbox
valid_xyz = pc_xyz[valid_ind]
xmin = np.min(valid_xyz[:, 0]);
xmax = np.max(valid_xyz[:, 0])
ymin = np.min(valid_xyz[:, 1]);
ymax = np.max(valid_xyz[:, 1])
zmin = np.min(valid_xyz[:, 2]);
zmax = np.max(valid_xyz[:, 2])
sem_ins_bbox.append(
[[xmin, ymin, zmin], [xmax, ymax, zmax], [min(tp[0], 1.), min(tp[1], 1.), min(tp[2], 1.)]])
Y_semins = np.concatenate([pc_xyz[:, 0:3], Y_colors], axis=-1)
draw_pc(Y_semins)
return Y_semins
if __name__=='__main__':
#xyzrgb_file='原始文件'
#original_data= read_ply(xyzrgb_file)
#original_dataxyz = np.vstack((original_data['x'], original_data['y'], original_data['z'])).T
#original_datacolors = np.vstack((original_data['red'], original_data['green'], original_data['blue'])).T
#xyzrgb = np.concatenate([original_dataxyz, original_datacolors], axis=-1)
#draw_pc(xyzrgb) # visualize raw point clouds
file='C:\RandLA-Net-master\预测area_1.ply'
data = read_ply(file)
xyz=np.vstack((data['x'], data['y'], data['z'])).T
labels = data['class'] + 1
draw_pc_sem_ins(xyz,labels)
其中如果要可视化预测结果如上代码所示,修改路径即可。如果要显示原始结果就使用注释的代码即可。
if __name__=='__main__':
xyzrgb_file='原始文件的路径'
original_data= read_ply(xyzrgb_file)
original_dataxyz = np.vstack((original_data['x'], original_data['y'], original_data['z'])).T
original_datacolors = np.vstack((original_data['red'], original_data['green'], original_data['blue'])).T
xyzrgb = np.concatenate([original_dataxyz, original_datacolors], axis=-1)
draw_pc(xyzrgb) # visualize raw point clouds
5.结语:
以上就是全部的RandLA-Net训练测试S3DIS数据集的步骤,中间也遇到了很多问题,但是相比第一次复现网络还是提高了很多,收获了很多技能和解决问题的方法。本人为研一小白所以有很多地方不懂,希望可以有小伙伴一起学习,提出批评指正,我将感激之至。