点云_open3d_可视化点云以及标注的box

可视化点云

点云的可视化--标注的3D box的可视化

基础运算理解

 magnitude 向量大小
两个向量的欧式距离
  np.sqrt(np.sum(np.power(vecA-vecB,2)))
  numpy库中的sum函数则求得的是整个matrix的所有数据之和,返回的是一个float型数值,  
  两个列向量的差的平方求和后再开方,输出的应该是一个float型数值,
  
  python的平方运算符是**,那么python中x的平方,就是这么写:x**2
  numpy.square()

  numpy.linalg.matrix_power
  numpy.sqrt
  numpy.power
  	
  np.sqrt(np.square(vector_1 - vector_2).sum())
  np.sqrt(np.sum(np.power(vecA-vecB,2)))
  magnitude = np.sqrt(np.sum((vecA-vecB)**2))

代码示例

 # -*- coding: utf-8 -*-

import open3d as o3d
import numpy as np
from pathlib import Path

def rotz(t):
    c = np.cos(t)
    s = np.sin(t)
    return np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])

def box2corner(box):
    x = box[0]
    y = box[1]
    z = box[2]
    l = box[3]  # dx
    w = box[4]  # dy
    h = box[5]  # dz
    yaw = box[6]
    Box = np.array(
        [
            [-l / 2, -l / 2, l / 2, l / 2, -l / 2, -l / 2, l / 2, l / 2],
            [w / 2, -w / 2, -w / 2, w / 2, w / 2, -w / 2, -w / 2, w / 2],
            [-h / 2, -h / 2, -h / 2, -h / 2, h / 2, h / 2, h / 2, h / 2],
        ]
    )
    # 先旋转再平移
    R = rotz(yaw)
    corners_3d = np.dot(R, Box)  # corners_3d: (3, 8)
    corners_3d[0, :] = corners_3d[0, :] + x
    corners_3d[1, :] = corners_3d[1, :] + y
    corners_3d[2, :] = corners_3d[2, :] + z
    return np.transpose(corners_3d)


def get_line_set(corners):
    lines = [
        [0, 1], [1, 2], [2, 3], [3, 0],
        [4, 5], [5, 6], [6, 7], [7, 4],
        [0, 4], [1, 5], [2, 6], [3, 7],]
    colors = [[1,0,0] for i in range(len(lines))]
    line_set = o3d.geometry.LineSet()
    line_set.points = o3d.utility.Vector3dVector(corners)
    line_set.lines = o3d.utility.Vector2iVector(lines)
    line_set.colors = o3d.utility.Vector3dVector(colors)
    return line_set


def load_pre_label(gt_json_path):
    if Path(gt_json_path).exists():
        pred_box = []
        with open(gt_json_path, 'r') as fobj:
            print("load pre label: ", gt_json_path)
            for line in fobj:
                l = line.strip().split(" ")
                cx, cy, cz, sx, sy, sz, yaw = l[0], l[1],l[2], l[3],l[4], l[5],l[6]
                box_data = list(map(float,[ cx, cy, cz, sx, sy, sz, yaw]))
                pred_box.append(box_data)
        return pred_box

############## 
def get_draw_box(pre_box_set):
    draw_boxes = []
    for box_p in pre_box_set:
        cx, cy, cz, sx, sy, sz, yaw = box_p[0],box_p[1],box_p[2], box_p[3],box_p[4], box_p[5],box_p[6]
        corner_box = box2corner([cx, cy, cz, sx, sy, sz, yaw])
        draw_box = get_line_set(corner_box)
        draw_boxes.append(draw_box)
    return draw_boxes


def draw_points_and_boxes(gt_pcd,pred_json):
    mesh_frame = o3d.io.read_point_cloud(gt_pcd, remove_infinite_points=True, remove_nan_points=True)
    box_sigle_pcd_all = load_pre_label(pred_json) 
    draw_boxes = get_draw_box(box_sigle_pcd_all)
    vis = o3d.visualization.Visualizer()
    vis.create_window(window_name="show_pred_pcd")
    render_option = vis.get_render_option()
    render_option.point_size = 2
    coordinate_frame = o3d.geometry.TriangleMesh.create_coordinate_frame(size=2.0, origin=[0, 0, 0])
    vis.add_geometry(coordinate_frame)
    vis.add_geometry(mesh_frame)  
    for box in draw_boxes:
        vis.add_geometry(box)
    vis.run()
    vis.destroy_window()

############ 

def calculate_zy_rotation_for_arrow(vec):
    """rotation over axis z and y required to
    get the vector vec into the same orientation as axis z
    of the original FOR

    Args:
        - vec (): 
    """
    # Rotation over z axis of the FOR
    gamma = np.arctan(vec[1] / vec[0])
    Rz = np.array(
        [
            [np.cos(gamma), -np.sin(gamma), 0],
            [np.sin(gamma), np.cos(gamma), 0],
            [0, 0, 1],
        ]
    )
    # Rotate vec to calculate next rotation
    vec = Rz.T @ vec.reshape(-1, 1)
    vec = vec.reshape(-1)
    # Rotation over y axis of the FOR
    beta = np.arctan(vec[0] / (vec[2] + 1e-8))
    Ry = np.array(
        [[np.cos(beta), 0, np.sin(beta)], [0, 1, 0], [-np.sin(beta), 0, np.cos(beta)]]
    )
    return (Rz, Ry)


def get_arrow(scale=10):
    """
    Create an arrow in for Open3D
    """
    cone_height = scale * 0.2
    cylinder_height = scale * 0.8
    cone_radius = scale / 10
    cylinder_radius = scale / 20
    mesh_frame = o3d.geometry.TriangleMesh.create_arrow(
        cone_radius=cone_radius,
        cone_height=cone_height,
        cylinder_radius=cylinder_radius,
        cylinder_height=cylinder_height,
    )
    return mesh_frame


def create_arrow(origin=[0, 0, 0], end=None, vec=None):
    """
    Creates an arrow from an origin point to an end point,
    or create an arrow from a vector vec starting from origin.
    Args:
        - end (): End point. [x,y,z]
        - vec (): Vector. [i,j,k]
    """
    scale = 10
    Ry = Rz = np.eye(3)
    T = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
    T[:3, -1] = origin
    if end is not None:
        vec = np.array(end) - np.array(origin)
    elif vec is not None:
        vec = np.array(vec)
    if end is not None or vec is not None:
        scale =  np.sqrt(np.sum(vec ** 2))
        Rz, Ry = calculate_zy_rotation_for_arrow(vec)
    mesh = get_arrow(scale)
    # Create the arrow
    mesh.rotate(Ry, center=np.array([0, 0, 0]))
    mesh.rotate(Rz, center=np.array([0, 0, 0]))
    mesh.translate(origin)
    ## set Arrow clors 
    mesh.paint_uniform_color([1.0, 0.0, 0.0])
    return mesh


def create_box_with_arrow(box):
    """
    box: list(8) [ x, y, z, dx, dy, dz, yaw]
    """
    cx, cy, cz, sx, sy, sz, yaw = box[0],box[1],box[2], box[3],box[4], box[5],box[6]
    corner_box = box2corner([cx, cy, cz, sx, sy, sz, yaw])
    box_o3d = get_line_set(corner_box)
    x = box[0]
    y = box[1]
    z = box[2]
    l = box[3]
    yaw = box[6]
    # get direction arrow
    dir_x = l / 2.0 * np.cos(yaw)
    dir_y = l / 2.0 * np.sin(yaw)

    arrow_origin = [x - dir_x, y - dir_y, z]
    arrow_end = [x + dir_x, y + dir_y, z]
    if l > 2:
        arrow = create_arrow(arrow_origin, arrow_end)
    else:
        arrow = None
    return box_o3d, arrow


def draw_points_and_arrow_boxes(gt_pcd,pred_json):
    mesh_frame = o3d.io.read_point_cloud(gt_pcd, remove_infinite_points=True, remove_nan_points=True)
    box_sigle_pcd_all = load_pre_label(pred_json) 
    boxes_o3d=[]
    for box_sig in box_sigle_pcd_all:
        box_o3d, arrow  = create_box_with_arrow(box_sig)
        boxes_o3d.append(box_o3d)
        boxes_o3d.append(arrow)   
    vis = o3d.visualization.Visualizer()
    vis.create_window(window_name="show_pred_with arrow pcd")
    render_option = vis.get_render_option()
    render_option.point_size = 2
    coordinate_frame = o3d.geometry.TriangleMesh.create_coordinate_frame(size=2.0, origin=[0, 0, 0])
    vis.add_geometry(coordinate_frame)
    vis.add_geometry(mesh_frame)      
    for element in boxes_o3d:
         if element is not None:
              vis.add_geometry(element)
    vis.run()
    vis.destroy_window()
####################

if __name__ == '__main__':
    exp_gt_pcd = r"~/test/833.9.pcd"
    exp_pred_json = r"~/test/833predected.txt"
    #draw_points_and_boxes(exp_gt_pcd,exp_pred_json)
    draw_points_and_arrow_boxes(exp_gt_pcd,exp_pred_json)

参考

https://stackoverflow.com/questions/59026581/create-arrows-in-open3d
posted @ 2022-11-11 16:50  辰令  阅读(723)  评论(0编辑  收藏  举报