如何在Python中绘制边界框并实时更新它们

Kev*_* Hu 1 python data-visualization bounding-box point-clouds open3d

我目前正在学习 open3d 来可视化点云数据。我设法使用此处介绍的非阻塞可视化实时可视化从一系列 .pcd 文件(一个文件对应一个点云)读取的一系列点云:非阻塞可视化

通过遵循文档,我能够更新“点云”类型的几何图形。这是我进行可视化的方法:

    import open3d as o3d
    import numpy as np
    import time

    geometry = o3d.geometry.PointCloud()
    geometry.points = o3d.utility.Vector3dVector(pt_clouds[0])
    o3d.utility.set_verbosity_level(o3d.utility.VerbosityLevel.Debug)

    vis = o3d.visualization.Visualizer()
    vis.create_window()
    vis.add_geometry(geometry)

    for pt_cloud in pt_clouds: #pt_clouds are the point cloud data from several .pcf files

        geometry.points = o3d.utility.Vector3dVector(pt_cloud)
        vis.update_geometry(geometry)
        vis.poll_events()
        vis.update_renderer()
        time.sleep(1 / 20)

    vis.destroy_window()
Run Code Online (Sandbox Code Playgroud)

然而,除了点云之外,我还有一组由中心坐标 [cx,cy,cz] 给出的每个点云的边界框,绕 z 轴“rot_z”的旋转和边界的 [长度,宽度,高度]盒子。我想找到一种方法来渲染边界框和点云,并在每一帧更新它们(对于每一帧,有一个点云+要渲染的不同数量的边界框,并且最后一帧的旧渲染需要被清除和更新)。

有没有办法做到这一点?如果 open3d 不能做到这一点,那么在 python 中执行此操作的常用方法/库是什么?

任何建议将不胜感激,提前致谢!

小智 7

为了可视化边界框,您必须将框从

[cx, cy, cz, rot_z, length, width, height]代表盒子 8 个角的点数组。

您可以使用这样的函数,它接受一个包含 的数组[x,y,z,h,w,l,r],并返回一个[8, 3]代表[x, y, z]盒子每个 8 个角的矩阵:

def box_center_to_corner(box_center):
    # To return
    corner_boxes = np.zeros((8, 3))

    translation = box[0:3]
    h, w, l = size[3], size[4], size[5]
    rotation = box[6]

    # Create a bounding box outline
    bounding_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]])

    # Standard 3x3 rotation matrix around the Z axis
    rotation_matrix = np.array([
        [np.cos(rotation), -np.sin(rotation), 0.0],
        [np.sin(rotation), np.cos(rotation), 0.0],
        [0.0, 0.0, 1.0]])

    # Repeat the [x, y, z] eight times
    eight_points = np.tile(translation, (8, 1))

    # Translate the rotated bounding box by the
    # original center position to obtain the final box
    corner_box = np.dot(
        rotation_matrix, bounding_box) + eight_points.transpose()

    return corner_box.transpose()
Run Code Online (Sandbox Code Playgroud)

将边界框转换为[8, 3]表示角的矩阵后,您可以使用以下LineSet对象在 Open3D 中显示它们:

# Our lines span from points 0 to 1, 1 to 2, 2 to 3, etc...
lines = [[0, 1], [1, 2], [2, 3], [0, 3],
         [4, 5], [5, 6], [6, 7], [4, 7],
         [0, 4], [1, 5], [2, 6], [3, 7]]

# Use the same color for all lines
colors = [[1, 0, 0] for _ in range(len(lines))]

line_set = o3d.geometry.LineSet()
line_set.points = o3d.utility.Vector3dVector(corner_box)
line_set.lines = o3d.utility.Vector2iVector(lines)
line_set.colors = o3d.utility.Vector3dVector(colors)

# Create a visualization object and window
vis = o3d.visualization.Visualizer()
vis.create_window()

# Display the bounding boxes:
vis.add_geometry(corner_box)
Run Code Online (Sandbox Code Playgroud)

关于每个时间步更新边界框,请参阅 Open3D Visualizer对象的文档,其中有清除所有几何体 ( clear_geometries())、清除特定几何体 ( remove_geometry(geometry)) 等的方法。

希望这个答案还不算太晚。祝你好运!