RandLA-Net结果可视化(将结果保存到本地再通过cloudcompare可视化)
问题:
RandLA-Net官网提供代码的可视化部分是通过open3d的方式呈现的,但如果使用远端服务器去跑,可能就无法实现可视化;或者当我们的需要可视化的点云文件过大时(几个G),在本地电脑运行这个代码就会直接导致电脑卡死。
本文提供一种将最终的测试结果保存为ply/txt文件,再通过一些常用的点云处理工具,如meshlab、cloudcompare等进行可视化的方式。
官方可视化代码解释
RandLA-Net官方提供的代码中,可视化的部分在utils/6_fold_cv.py中,将
中的visualization = False设置为Ture即可;代码将执行以下部分,主要是绘制原始点云、按照真实标签赋颜色的点云以及按照预测标签赋颜色的点云:
其中draw_pc_sem_ins方法来自于RandLA-Net的helper_tool.py,主要是将标签和颜色进行一个映射,然后通过open3d进行绘图展示;
def draw_pc_sem_ins(pc_xyz, pc_sem_ins, plot_colors=None):
"""
pc_xyz: 3D coordinates of point clouds
pc_sem_ins: semantic or instance labels
plot_colors: custom color list
"""
if plot_colors is not None:
ins_colors = plot_colors
else:
ins_colors = Plot.random_colors(len(np.unique(pc_sem_ins)) + 1, seed=2)
sem_ins_labels = np.unique(pc_sem_ins)
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)
Plot.draw_pc(Y_semins)
return Y_semins
如果需要使用open3d进行可视化,只需要将utils/6_fold_cv.py中可视化的这部分代码和读取文件部分的提取出来即可,此处不多做介绍,下面主要介绍一下通过将最终预测结果保存为ply/txt到本地的方式,通过点云处理工具进行可视化的方法。
实现过程:
首先需要将helper_tool.py当中的draw_pc_ins方法进行一些修改,由于我们不需要使用open3d进行绘图,所以注释掉PC.draw_pc相关的代码即可,具体可以参考下面的代码:
def draw_pc_sem_ins(pc_xyz, pc_sem_ins, plot_colors=None):
"""
pc_xyz: 3D coordinates of point clouds
pc_sem_ins: semantic or instance labels
plot_colors: custom color list
"""
if plot_colors is not None:
ins_colors = plot_colors
else:
ins_colors = Plot.random_colors(len(np.unique(pc_sem_ins)) + 1, seed=2)
##############################
sem_ins_labels = np.unique(pc_sem_ins)
#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)
#Plot.draw_pc(Y_semins)
return Y_semins
以下将预测结果保存为ply/txt的代码,其中base_dir是使用randla-net模型预测后的ply文件所在路径,注意:使用RandLa-Net官方代码运行测试代码后生成的ply文件只保存了预测标签和真实标签,没有其他信息,不能直接将此ply丢到cloudcompare中进行可视化!
original_data_dir是真实点云对应的ply文件,data_path中 ’Area_1.ply‘是我实际想要可视化的那一个点云文件,当然也可以直接写成’*.ply‘,不过后面的保存生成文件的代码也需要在一个循环中进行。需要根据实际点云类别标签数量修改rang(5)中的值。保存为ply的话需要用到trimesh,可以直接用pip install trimesh安装这个库。保存为txt的话可以直接用我注释掉的那一行代码,最后将保存的文件拿到cloudcompare中即可完成可视化。
import numpy as np
import glob, os, sys
import trimesh
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = os.path.dirname(BASE_DIR)
sys.path.append(ROOT_DIR)
from helper_ply import read_ply
from helper_tool import Plot
if __name__ == '__main__':
base_dir = 'D:\\mageechan\\randlanet-vis\\randla-net-tf2-main\\results'
original_data_dir = 'D:\\mageechan\\randlanet-vis\\original_ply'
data_path = glob.glob(os.path.join(base_dir, 'Area_1.ply'))
data_path = np.sort(data_path)
test_total_correct = 0
test_total_seen = 0
gt_classes = [0 for _ in range(5)]
positive_classes = [0 for _ in range(5)]
true_positive_classes = [0 for _ in range(5)]
visualization = True
for file_name in data_path:
pred_data = read_ply(file_name)
pred = pred_data['pred']
original_data = read_ply(os.path.join(original_data_dir, file_name.split('\\')[-1][:-4] + '.ply'))
labels = original_data['class']
#print(labels)
points = np.vstack((original_data['x'], original_data['y'], original_data['z'])).T
##################
# Visualize data #
##################
if visualization:
#colors = np.vstack((original_data['red'], original_data['green'], original_data['blue'])).T
#xyzrgb = np.concatenate([points, colors], axis=-1)
print("绘制颜色信息")
pred_point=Plot.draw_pc_sem_ins(points, pred)
true_point=Plot.draw_pc_sem_ins(points, labels)
vertices1 = pred_point[:, :3]
colors1 = pred_point[:, 3:]
vertices2 = true_point[:, :3]
colors2 = true_point[:, 3:]
mesh1 = trimesh.Trimesh(vertices=vertices1, vertex_colors=colors1)
mesh2= trimesh.Trimesh(vertices=vertices2, vertex_colors=colors2)
print("开始保存")
mesh1.export('D:\\mageechan\\randlanet-vis\\randla-net-tf2-main\\results\\Area_1_pred_point.ply')
mesh2.export('D:\\mageechan\\randlanet-vis\\randla-net-tf2-main\\results\\Area_1_true_point.ply')
#np.savetxt('D:\\mageechan\\randlanet-vis\\randla-net-tf2-main\\results\\true_point.txt', pred_point,fmt='%.4f')
print("保存成功")