目录
- 网络中同一视角显示点云
- 可视化点云
- 使用knn搜索点云,并指定颜色
- 可视化点云+label
- 可视化两个点云
- 保存与读取view point
- 动态显示点云
- 动态显示点云
- SemanticKITTI bin+label点云转PCD
网络中同一视角显示点云
import numpy as np
from numpy.core.fromnumeric import reshape
import open3d as o3d
from torch import tensor, Tensor
COLOR_MAP = {
0: (0., 0., 0.),
1: (174., 199., 232.),
2: (152., 223., 138.),
3: (31., 119., 180.),
4: (255., 187., 120.),
5: (188., 189., 34.),
6: (140., 86., 75.),
7: (255., 152., 150.),
8: (214., 39., 40.),
9: (197., 176., 213.),
10: (148., 103., 189.),
11: (196., 156., 148.),
12: (23., 190., 207.),
13: (100., 85., 144.),
14: (247., 182., 210.),
15: (66., 188., 102.),
16: (219., 219., 141.),
17: (140., 57., 197.),
18: (202., 185., 52.),
19: (51., 176., 203.),
20: (200., 54., 131.),
21: (92., 193., 61.),
22: (78., 71., 183.),
23: (172., 114., 82.),
24: (255., 127., 14.),
25: (91., 163., 138.),
26: (153., 98., 156.),
27: (140., 153., 101.),
28: (158., 218., 229.),
29: (100., 125., 154.),
30: (178., 127., 135.),
32: (146., 111., 194.),
33: (44., 160., 44.),
34: (112., 128., 144.),
35: (96., 207., 209.),
36: (227., 119., 194.),
37: (213., 92., 176.),
38: (94., 106., 211.),
39: (82., 84., 163.),
40: (100., 85., 144.),
}
def visualize_with_label(cloud, label, window_name="open3d"):
assert cloud.shape[0] == label.shape[0]
pt = o3d.geometry.PointCloud()
pt.points = o3d.utility.Vector3dVector(cloud)
colors = [COLOR_MAP[i] for i in list(label)]
pt.colors = o3d.utility.Vector3dVector(colors)
# o3d.visualization.draw_geometries([pt], window_name ,width=500, height=500)
def visualize_without_label(cloud, window_name="open3d"):
# assert cloud.shape[0] == label.shape[0]
if isinstance(cloud, Tensor):
cloud = cloud.cpu().numpy().reshape((-1,3))
pt = o3d.geometry.PointCloud()
pt.points = o3d.utility.Vector3dVector(cloud)
# colors = [COLOR_MAP[i] for i in list(label)]
# pt.colors = o3d.utility.Vector3dVector(colors)
o3d.visualization.draw_geometries([pt], window_name ,width=500, height=500)
def ptGenerator(cloud):
if isinstance(cloud, Tensor):
cloud = cloud.cpu().numpy().reshape((-1,3))
pt = o3d.geometry.PointCloud()
pt.points = o3d.utility.Vector3dVector(cloud)
return pt
def save_view_point(pcd, filename):
vis = o3d.visualization.Visualizer()
vis.create_window()
vis.add_geometry(pcd)
vis.run() # user changes the view and press "q" to terminate
param = vis.get_view_control().convert_to_pinhole_camera_parameters()
o3d.io.write_pinhole_camera_parameters(filename, param)
vis.destroy_window()
def load_view_point(pcd, filename):
vis = o3d.visualization.Visualizer()
vis.create_window()
ctr = vis.get_view_control()
param = o3d.io.read_pinhole_camera_parameters(filename)
vis.add_geometry(pcd)
ctr.convert_from_pinhole_camera_parameters(param)
vis.run()
vis.destroy_window()
def vis_by_one_viewpoint(load_view_point_flag:bool, window_name:str, pcd):
# if load_view_point is False:
# save_view_point = True
if load_view_point_flag is False:
save_view_point(pcd = pcd, filename = './view.json')
print("===> save viewpoint to {}".format("./view.json"))
elif load_view_point_flag :
print("===> load viewpoint from {}".format("./view.json"))
load_view_point(pcd = pcd, filename = './view.json')
else:
raise NotImplementedError
可视化点云
# 使用open3d可视化点云
# 使用open3d可视化点云,返回pointcloud类型示例
def visualize(pointcloud):
from open3d.open3d.geometry import PointCloud
from open3d.open3d.utility import Vector3dVector
from open3d.open3d.visualization import draw_geometries
# from open3d_study import *
# points = np.random.rand(10000, 3)
point_cloud = PointCloud()
point_cloud.points = Vector3dVector(pointcloud[:,0:3].reshape(-1,3))
draw_geometries([point_cloud],width=800,height=600)
return point_cloud
使用knn搜索点云,并指定颜色
#创建点云对象
pcd=o3d.geometry.PointCloud()
pcd.points=o3d.utility.Vector3dVector(pt[:,0:3])
pcd.paint_uniform_color([0.5, 0.5, 0.5]) # 给全部点云上色,灰色
pcd_tree=o3d.geometry.KDTreeFlann(pcd) # 创建一个实例 pcd_tree以使用KDTree
[k, index, _] = pcd_tree.search_knn_vector_3d(pcd.points[K], 50)
np.asarray(pcd.colors)[index[1:], :] = [0, 1, 0] # 给50以内的点设置颜色为green
ps:colors和points是PointCloud中的两个矩阵
可视化点云+label
可视化点云,并根据标签赋值颜色
def vis(data,label):
'''
:param data: n*3的矩阵
:param label: n*1的矩阵
:return: 可视化
'''
data=data[:,:3]
labels=np.asarray(label)
max_label=labels.max()
# 颜色
colors = plt.get_cmap("tab20")(labels / (max_label if max_label > 0 else 1))
pt1 = o3d.geometry.PointCloud()
pt1.points = o3d.utility.Vector3dVector(data.reshape(-1, 3))
pt1.colors=o3d.utility.Vector3dVector(colors[:, :3])
o3d.visualization.draw_geometries([pt1],'part of cloud',width=500,height=500)
可视化两个点云
可视化两个点云并赋予不同的颜色
def vis_cloud(a,b):
# a:n*3的矩阵
# b:n*3的矩阵
pt1=o3d.geometry.PointCloud()
pt1.points=o3d.utility.Vector3dVector(a.reshape(-1,3))
pt1.paint_uniform_color([1,0,0])
pt2=o3d.geometry.PointCloud()
pt2.points=o3d.utility.Vector3dVector(b.reshape(-1,3))
pt2.paint_uniform_color([0,1,0])
o3d.visualization.draw_geometries([pt1,pt2],window_name='cloud[0] and corr',width=800,height=600)
保存与读取view point
参考
# Open3D: www.open3d.org
# The MIT License (MIT)
# See license file or visit www.open3d.org for details
# examples/python/visualization/load_save_viewpoint.py
import numpy as np
import open3d as o3d
def save_view_point(pcd, filename):
vis = o3d.visualization.Visualizer()
vis.create_window()
vis.add_geometry(pcd)
vis.run() # user changes the view and press "q" to terminate
param = vis.get_view_control().convert_to_pinhole_camera_parameters()
o3d.io.write_pinhole_camera_parameters(filename, param)
vis.destroy_window()
def load_view_point(pcd, filename):
vis = o3d.visualization.Visualizer()
vis.create_window()
ctr = vis.get_view_control()
param = o3d.io.read_pinhole_camera_parameters(filename)
vis.add_geometry(pcd)
ctr.convert_from_pinhole_camera_parameters(param)
vis.run()
vis.destroy_window()
if __name__ == "__main__":
pcd = o3d.io.read_point_cloud("../../test_data/fragment.pcd")
save_view_point(pcd, "viewpoint.json")
load_view_point(pcd, "viewpoint.json")
动态显示点云
# 方法2 类
# 参考:https://github.com/Jiang-Muyun/Open3D-Semantic-KITTI-Vis/blob/ddb188e1375a1d464dec077826725afd72a85e63/src/kitti_base.py#L43
class pt_Vis():
def __init__(self,name='20m test',width=800,height=600,json='./config/view_point.json'):
self.vis=o3d.visualization.Visualizer()
self.vis.create_window(window_name=name,width=width,height=height)
self.axis_pcd = o3d.geometry.TriangleMesh.create_coordinate_frame(size=5, origin=[0, 0, 0])
# 可视化参数
opt = self.vis.get_render_option()
opt.background_color = np.asarray([0, 0, 0])
opt.point_size = 1
opt.show_coordinate_frame = True
self.pcd = o3d.geometry.PointCloud()
self.vis.add_geometry(self.pcd)
# 读取viewpoint参数
self.param=o3d.io.read_pinhole_camera_parameters(json)
self.ctr=self.vis.get_view_control()
self.ctr.convert_from_pinhole_camera_parameters(self.param)
print('viewpoint json loaded!')
# param = self.ctr.convert_to_pinhole_camera_parameters()
#
# o3d.io.write_pinhole_camera_parameters('./config/new.json',param)
# print('viewpoint json saved!')
def __del__(self):
self.vis.destroy_window()
def update(self,pcd):
'''
:param pcd: PointCLoud()
:return:
'''
self.pcd.points=pcd.points
self.pcd=pcd
# self.pcd.colors=pcd.colors
# self.vis.clear_geometries()
self.vis.update_geometry(self.pcd) # 更新点云
# self.vis.remove_geometry(self.pcd) # 删除vis中的点云
self.vis.add_geometry(self.pcd) # 增加vis中的点云
# 设置viewpoint
self.ctr.convert_from_pinhole_camera_parameters(self.param)
self.vis.poll_events()
self.vis.update_renderer()
# self.vis.run()
def capture_screen(self,fn, depth = False):
if depth:
self.vis.capture_depth_image(fn, False)
else:
self.vis.capture_screen_image(fn, False)
使用:创建一个对象,然后再循环中不断调用
update
函数就可以了。
动态显示点云
import os
import numpy as np
import open3d as o3d
files = os.listdir("0806_reconstruction/")
vis = o3d.visualization.Visualizer()
vis.create_window()
pointcloud = o3d.geometry.PointCloud()
to_reset = True
vis.add_geometry(pointcloud)
for f in files:
pcd = o3d.io.read_point_cloud("0806_reconstruction/" + f)
pcd = np.asarray(pcd.points).reshape((-1, 3))
pointcloud.points = o3d.utility.Vector3dVector(pcd)
vis.update_geometry()
# 注意,如果使用的是open3d 0.8.0以后的版本,这句话应该改为下面格式
# vis.update_geometry(pointcloud)
if to_reset:
vis.reset_view_point(True)
to_reset = False
vis.poll_events()
vis.update_renderer()
SemanticKITTI bin+label点云转PCD
参考:
https://github.com/PRBonn/semantic-kitti-api/blob/master/auxiliary/laserscan.py https://github.com/mit-han-lab/spvnas/blob/master/visualize.py
# 将bin+label转为xyzrgb格式的PCD文件
import numpy as np
import logging
import open3d as o3d
logging.basicConfig(format='%(asctime)s.%(msecs)03d [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s',
datefmt='## %Y-%m-%d %H:%M:%S')
logging.getLogger().setLevel(logging.DEBUG)
logger = logging.getLogger()
label_name_mapping = {
0: 'unlabeled',
1: 'outlier',
10: 'car',
11: 'bicycle',
13: 'bus',
15: 'motorcycle',
16: 'on-rails',
18: 'truck',
20: 'other-vehicle',
30: 'person',
31: 'bicyclist',
32: 'motorcyclist',
40: 'road',
44: 'parking',
48: 'sidewalk',
49: 'other-ground',
50: 'building',
51: 'fence',
52: 'other-structure',
60: 'lane-marking',
70: 'vegetation',
71: 'trunk',
72: 'terrain',
80: 'pole',
81: 'traffic-sign',
99: 'other-object',
252: 'moving-car',
253: 'moving-bicyclist',
254: 'moving-person',
255: 'moving-motorcyclist',
256: 'moving-on-rails',
257: 'moving-bus',
258: 'moving-truck',
259: 'moving-other-vehicle'
}
kept_labels = [
'road', 'sidewalk', 'parking', 'other-ground', 'building', 'car', 'truck',
'bicycle', 'motorcycle', 'other-vehicle', 'vegetation', 'trunk', 'terrain',
'person', 'bicyclist', 'motorcyclist', 'fence', 'pole', 'traffic-sign'
]
cmap = np.array([
[245, 150, 100, 255],
[245, 230, 100, 255],
[150, 60, 30, 255],
[180, 30, 80, 255],
[255, 0, 0, 255],
[30, 30, 255, 255],
[200, 40, 255, 255],
[90, 30, 150, 255],
[255, 0, 255, 255],
[255, 150, 255, 255],
[75, 0, 75, 255],
[75, 0, 175, 255],
[0, 200, 255, 255],
[50, 120, 255, 255],
[0, 175, 0, 255],
[0, 60, 135, 255],
[80, 240, 150, 255],
[150, 240, 255, 255],
[0, 0, 255, 255],
])
cmap = cmap[:, [2, 1, 0, 3]] # convert bgra to rgba
class BinConvertor:
def __init__(self, bin_name, label_name):
self.bin_name = bin_name
self.label_name = label_name
self.points = np.zeros((0, 3), dtype=np.float32)
self.sem_label = np.zeros((0, 1), dtype=np.uint32) # [m, 1]: label
self.sem_label_color = np.zeros((0, 3), dtype=np.float32) # [m ,3]: color
# label map
reverse_label_name_mapping = {}
self.label_map = np.zeros(260)
cnt = 0
for label_id in label_name_mapping:
if label_id > 250:
if label_name_mapping[label_id].replace('moving-',
'') in kept_labels:
self.label_map[label_id] = reverse_label_name_mapping[
label_name_mapping[label_id].replace('moving-', '')]
else:
self.label_map[label_id] = 255
elif label_id == 0:
self.label_map[label_id] = 255
else:
if label_name_mapping[label_id] in kept_labels:
self.label_map[label_id] = cnt
reverse_label_name_mapping[
label_name_mapping[label_id]] = cnt
cnt += 1
else:
self.label_map[label_id] = 255
self.reverse_label_name_mapping = reverse_label_name_mapping
def read_bin(self):
scan = np.fromfile(self.bin_name, dtype=np.float32)
scan = scan.reshape((-1, 4))
self.points = scan[:,:3]
def read_label(self):
label = np.fromfile(self.label_name, dtype=np.uint32)
label = label.reshape((-1))
self.sem_label = label & 0xFFFF
assert self.points.shape[0] == self.sem_label.shape[0]
self.sem_label = self.label_map[self.sem_label].astype(np.int64)
def set_cloud(self):
# make color table
color_dict = {}
for i in range(19):
color_dict[i] = cmap[i, :]
color_dict[255] = [0,0,0,255]
pc = o3d.geometry.PointCloud()
pc.points = o3d.utility.Vector3dVector(self.points)
cloud_color = [color_dict[i] for i in list(self.sem_label)]
self.sem_label_color = np.array(cloud_color).reshape((-1,4))[:,:3] / 255
pc.colors = o3d.utility.Vector3dVector(self.sem_label_color)
o3d.visualization.draw_geometries([pc])
output_path = "F:\git\qt_visualizer_pcl\qt_visualizer\data\\000005.pcd"
o3d.io.write_point_cloud(output_path, pc)
logger.info("===> point cloud save to {}".format(output_path))
if __name__ == '__main__':
bin_name = "F:\git\qt_visualizer_pcl\qt_visualizer\data\\velodyne\\000005.bin"
label_name = "F:\git\qt_visualizer_pcl\qt_visualizer\data\labels\\000005.label"
bc = BinConvertor(bin_name, label_name)
bc.read_bin()
bc.read_label()
bc.set_cloud()