(1)将RandLA-Net的运行结果可视化
(2)将Semantic3D和SemanticKITTI可视化做对比
本文的代码的画图代码来自RandLA-Net的开源代码。实现部分为一些数据处理。
展示demo:
https://www.bilibili.com/video/BV1MA411i7mo
# 师兄建议可以用pcl+放置相机和转角来实现,类似论文demo的那种效果。
目录
一、使用open3d画图
主要是调用helper_tool.py中的Plot类,摘录如下。其中:
(1)random_colors输入为N,N是要表达的类别数,如SemanticKITTI是20类,Semantic3D是9类。
(2)draw_pc,输入x-y-z-r-g-b格式的数据绘图
(3)draw_pc_sem_ins,输入pc_xyz是点云坐标信息,pc_sem_ins是对应的label,plot_colors是label对应的颜色,SemanticKITTI中,每个序列、每帧中的label是不一定的,如果要使每个label对应的颜色相同,需要提前调用random_colors或自己生成,然后输入进去。
class Plot:
@staticmethod
def random_colors(N, bright=True, seed=0): # 生成随机颜色,其中N为需要的类别数
brightness = 1.0 if bright else 0.7
hsv = [(0.15 + i / float(N), 1, brightness) for i in range(N)]
colors = list(map(lambda c: colorsys.hsv_to_rgb(*c), hsv))
random.seed(seed)
random.shuffle(colors)
return colors
@staticmethod
def draw_pc(pc_xyzrgb): # 输入数据格式为x-y-z-r-g-b六维
pc = open3d.PointCloud()
pc.points = open3d.Vector3dVector(pc_xyzrgb[:, 0:3])
if pc_xyzrgb.shape[1] == 3:
open3d.draw_geometries([pc])
return 0
if np.max(pc_xyzrgb[:, 3:6]) > 20: ## 0-255
pc.colors = open3d.Vector3dVector(pc_xyzrgb[:, 3:6] / 255.)
else:
pc.colors = open3d.Vector3dVector(pc_xyzrgb[:, 3:6])
open3d.draw_geometries([pc])
return 0
@staticmethod
def draw_pc_sem_ins(pc_xyz, pc_sem_ins, plot_colors=None): # pc_xyz是坐标信息 pc_sem_ins是label plot_colors是用每类的颜色[r, g, b]/255
"""
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)
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)
Plot.draw_pc(Y_semins)
return Y_semins
二、SemanticKITTI绘图
这里我是画序列11-21的第一帧,如果不想只画第一帧,将get_file_list和get_test_result_file_list中的break注释掉即可。绘制效果如下:
from helper_tool import Plot
from os.path import join, dirname, abspath
from helper_tool import DataProcessing as DP
import numpy as np
import os
import pickle
import yaml
def get_file_list(dataset_path):
seq_list = np.sort(os.listdir(dataset_path))
test_file_list = []
for seq_id in seq_list:
seq_path = join(dataset_path, seq_id)
pc_path = join(seq_path, 'velodyne')
if int(seq_id) >= 11:
for f in np.sort(os.listdir(pc_path)):
test_file_list.append([join(pc_path, f)])
break
test_file_list = np.concatenate(test_file_list, axis=0)
return test_file_list
def get_test_result_file_list(dataset_path):
seq_list = np.sort(os.listdir(dataset_path))
test_result_file_list = []
for seq_id in seq_list:
seq_path = join(dataset_path, seq_id)
pred_path = join(seq_path, 'predictions')
for f in np.sort(os.listdir(pred_path)):
test_result_file_list.append([join(pred_path, f)])
break
test_file_list = np.concatenate(test_result_file_list, axis=0)
return test_file_list
if __name__ == '__main__':
dataset_path = '/../../../../data/semantic_kitti/dataset/sequences'
predict_path = '/../../../../data/semantic_kitti/dataset/test/sequences'
test_list = get_file_list(dataset_path)
test_label_list = get_test_result_file_list(predict_path)
BASE_DIR = dirname(abspath(__file__))
# remap_lut #
data_config = join(BASE_DIR, 'utils', 'semantic-kitti.yaml')
DATA = yaml.safe_load(open(data_config, 'r'))
remap_dict = DATA["learning_map"]
max_key = max(remap_dict.keys())
remap_lut = np.zeros((max_key + 100), dtype=np.int32)
remap_lut[list(remap_dict.keys())] = list(remap_dict.values())
# remap_lut #
plot_colors = Plot.random_colors(21, seed=2)
for i in range(len(test_list)):
pc_path = test_list[i]
labels_path = test_label_list[i]
points = DP.load_pc_kitti(pc_path)
# 用深蓝色画初始点云 #
rpoints = np.zeros((points.shape[0],6),dtype=np.int)
rpoints[:,0:3] = points
rpoints[:,5] = 1
Plot.draw_pc(rpoints)
# 画对应的预测点云 #
labels = DP.load_label_kitti(labels_path, remap_lut)
Plot.draw_pc_sem_ins(points, labels,plot_colors)
三、Semantic3D绘图
绘制效果如下:
from helper_tool import Plot
from os.path import join, exists
from helper_ply import read_ply
import numpy as np
import os
if __name__ == '__main__':
path = '/../../data'
label_folder = './test/Log_2020-04-09_03-32-36/predictions/'
label_to_names = {0: 'unlabeled',
1: 'man-made terrain',
2: 'natural terrain',
3: 'high vegetation',
4: 'low vegetation',
5: 'buildings',
6: 'hard scape',
7: 'scanning artefacts',
8: 'cars'}
original_folder = join(path, 'semantic3d')
full_pc_folder = join(path, 'original_ply')
test_files_names = []
cloud_names = [file_name[:-4] for file_name in os.listdir(original_folder) if file_name[-4:] == '.txt']
for pc_name in cloud_names:
if not exists(join(original_folder, pc_name + '.labels')):
test_files_names.append(pc_name + '.ply')
test_files_names = np.sort(test_files_names)
# Ascii files dict for testing
ascii_files = {
'MarketplaceFeldkirch_Station4_rgb_intensity-reduced.ply': 'marketsquarefeldkirch4-reduced.labels',
'sg27_station10_rgb_intensity-reduced.ply': 'sg27_10-reduced.labels',
'sg28_Station2_rgb_intensity-reduced.ply': 'sg28_2-reduced.labels',
'StGallenCathedral_station6_rgb_intensity-reduced.ply': 'stgallencathedral6-reduced.labels',
'birdfountain_station1_xyz_intensity_rgb.ply': 'birdfountain1.labels',
'castleblatten_station1_intensity_rgb.ply': 'castleblatten1.labels',
'castleblatten_station5_xyz_intensity_rgb.ply': 'castleblatten5.labels',
'marketplacefeldkirch_station1_intensity_rgb.ply': 'marketsquarefeldkirch1.labels',
'marketplacefeldkirch_station4_intensity_rgb.ply': 'marketsquarefeldkirch4.labels',
'marketplacefeldkirch_station7_intensity_rgb.ply': 'marketsquarefeldkirch7.labels',
'sg27_station10_intensity_rgb.ply': 'sg27_10.labels',
'sg27_station3_intensity_rgb.ply': 'sg27_3.labels',
'sg27_station6_intensity_rgb.ply': 'sg27_6.labels',
'sg27_station8_intensity_rgb.ply': 'sg27_8.labels',
'sg28_station2_intensity_rgb.ply': 'sg28_2.labels',
'sg28_station5_xyz_intensity_rgb.ply': 'sg28_5.labels',
'stgallencathedral_station1_intensity_rgb.ply': 'stgallencathedral1.labels',
'stgallencathedral_station3_intensity_rgb.ply': 'stgallencathedral3.labels',
'stgallencathedral_station6_intensity_rgb.ply': 'stgallencathedral6.labels'}
plot_colors = Plot.random_colors(11, seed=2)
for file in test_files_names:
print(file)
test_files = join(full_pc_folder, file)
label_files = join(label_folder, ascii_files[file])
data = read_ply(test_files)
# 绘制原图
pc_xyzrgb = np.vstack((data['x'], data['y'], data['z'], data['red'], data['green'], data['blue'])).T
Plot.draw_pc(pc_xyzrgb)
# 绘制预测结果图
pc_xyz = np.vstack((data['x'], data['y'], data['z'])).T
pc_sem_ins = np.loadtxt(label_files)
pc_sem_ins = pc_sem_ins.astype(int)
Plot.draw_pc_sem_ins(pc_xyz, pc_sem_ins,plot_colors)
版权声明:本文为qq_40731332原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。