Reputation: 95
I am currently learning open3d for visualizing point cloud data. I managed to visualize a sequence of point clouds read from a series of .pcd files (one file for one point cloud) at real-time using the non-blocking visualization introduced here: Non-blocking visualization
By following the documentation I was able to update geometry of type "point cloud". Here is how I did the visualization:
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()
However, apart from the point clouds I also have a set of bounding boxes for each point cloud given by the center coordinates [cx, cy, cz], rotation around z axis "rot_z" and [length, width, height] of the bounding boxes. I want to find a way to render the bounding box along with the point clouds and update them every frame (for each frame, there are one point cloud + a different number of bounding boxes to be rendered and the old rendering of last frame needs to be cleared and updated).
Is there a way to do this? If open3d cannot do this, what is the common way/library to do this in python?
Any advice will be grateful, thanks in advance!
Upvotes: 1
Views: 13549
Reputation: 73
For visualizing the bounding boxes, you'll have to convert the boxes from
[cx, cy, cz, rot_z, length, width, height]
to an array of points that represent the 8 corners of the box.
You can use a function like this, that takes an array containing [x,y,z,h,w,l,r]
, and returns an [8, 3]
matrix that represents the [x, y, z]
for each 8 corners of the box:
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()
Once you've converted your bounding boxes to [8, 3]
matrices representing the corners, you can display them in Open3D by using the LineSet
object:
# 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)
In terms of updating the bounding boxes each time step, refer to the documentation for the Open3D Visualizer object, where there are methods for clearing all geometry (clear_geometries()
), clearing a specific geometry (remove_geometry(geometry)
), etc.
Hope this answer wasn't too late. Good luck!
Upvotes: 7