【Open3d】使用open3d可视化

网络中同一视角显示点云

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函数就可以了。

动态显示点云

参考:https://www.cnblogs.com/brt2/p/14283547.html

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

semantic-kitti


# 将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()
  • 25
    点赞
  • 176
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tech沉思录

点赞加投币,感谢您的资瓷~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值