visualizer_3d.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. # Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import argparse
  15. import importlib.util
  16. import os
  17. import numpy as np
  18. class LazyLoader:
  19. def __init__(self, module_name):
  20. self.module_name = module_name
  21. self._module = None
  22. def __getattr__(self, item):
  23. if self._module is None:
  24. self._module = importlib.import_module(self.module_name)
  25. return getattr(self._module, item)
  26. open3d = LazyLoader("open3d")
  27. class Visualizer3D:
  28. def __init__(self):
  29. self.vis = open3d.visualization.Visualizer() # initialize visualizer
  30. def boxes_to_lines(self, box: np.ndarray):
  31. """
  32. 4-------- 6
  33. /| /|
  34. 5 -------- 3 .
  35. | | | |
  36. . 7 -------- 1
  37. |/ |/
  38. 2 -------- 0
  39. """
  40. center = box[0:3]
  41. lwh = box[3:6]
  42. angles = np.array([0, 0, box[6] + 1e-10])
  43. rot = open3d.geometry.get_rotation_matrix_from_axis_angle(angles)
  44. box3d = open3d.geometry.OrientedBoundingBox(center, rot, lwh)
  45. return open3d.geometry.LineSet.create_from_oriented_bounding_box(box3d)
  46. def draw_results(
  47. self, points: np.ndarray, result: dict, score_threshold: float
  48. ) -> None:
  49. scores = result["scores"]
  50. bbox3d = result["bbox3d"]
  51. label_preds = result["labels"]
  52. num_bbox3d, bbox3d_dims = bbox3d.shape
  53. result_boxes = []
  54. for box_idx in range(num_bbox3d):
  55. if scores[box_idx] < score_threshold:
  56. continue
  57. if bbox3d_dims == 9:
  58. print(
  59. "Score: {} Label: {} Box(x_c, y_c, z_c, w, l, h, vec_x, vec_y, -rot): {} {} {} {} {} {} {} {} {}".format(
  60. scores[box_idx],
  61. label_preds[box_idx],
  62. bbox3d[box_idx, 0],
  63. bbox3d[box_idx, 1],
  64. bbox3d[box_idx, 2],
  65. bbox3d[box_idx, 3],
  66. bbox3d[box_idx, 4],
  67. bbox3d[box_idx, 5],
  68. bbox3d[box_idx, 6],
  69. bbox3d[box_idx, 7],
  70. bbox3d[box_idx, 8],
  71. )
  72. )
  73. elif bbox3d_dims == 7:
  74. print(
  75. "Score: {} Label: {} Box(x_c, y_c, z_c, w, l, h, -rot): {} {} {} {} {} {} {}".format(
  76. scores[box_idx],
  77. label_preds[box_idx],
  78. bbox3d[box_idx, 0],
  79. bbox3d[box_idx, 1],
  80. bbox3d[box_idx, 2],
  81. bbox3d[box_idx, 3],
  82. bbox3d[box_idx, 4],
  83. bbox3d[box_idx, 5],
  84. bbox3d[box_idx, 6],
  85. )
  86. )
  87. # draw result
  88. result_boxes.append(
  89. [
  90. bbox3d[box_idx, 0],
  91. bbox3d[box_idx, 1],
  92. bbox3d[box_idx, 2],
  93. bbox3d[box_idx, 3],
  94. bbox3d[box_idx, 4],
  95. bbox3d[box_idx, 5],
  96. bbox3d[box_idx, -1],
  97. ]
  98. )
  99. # config
  100. self.vis.create_window()
  101. self.vis.get_render_option().point_size = 1.0
  102. self.vis.get_render_option().background_color = [0, 0, 0]
  103. pc_color = [1, 1, 1]
  104. num_points = len(points)
  105. pc_colors = np.tile(pc_color, (num_points, 1))
  106. # raw point cloud
  107. pts = open3d.geometry.PointCloud()
  108. pts.points = open3d.utility.Vector3dVector(points[:, :3])
  109. pts.colors = open3d.utility.Vector3dVector(pc_colors)
  110. self.vis.add_geometry(pts)
  111. # result_boxes
  112. obs_color = [1, 0, 0]
  113. result_boxes = np.array(result_boxes)
  114. for i in range(result_boxes.shape[0]):
  115. lines = self.boxes_to_lines(result_boxes[i])
  116. # show different colors for different classes
  117. if label_preds[i] <= 4:
  118. obs_color = [
  119. 0,
  120. 1,
  121. 0,
  122. ] # 'car', 'truck', 'trailer', 'bus', 'construction_vehicle',
  123. elif label_preds[i] <= 6:
  124. obs_color = [0, 0, 1] # 'bicycle', 'motorcycle'
  125. elif label_preds[i] <= 7:
  126. obs_color = [1, 0, 0] # 'pedestrian'
  127. else:
  128. obs_color = [1, 0, 1] # 'traffic_cone','barrier'
  129. lines.paint_uniform_color(obs_color)
  130. self.vis.add_geometry(lines)
  131. self.vis.run()
  132. self.vis.poll_events()
  133. self.vis.update_renderer()
  134. # self.vis.capture_screen_image("result.png")
  135. self.vis.destroy_window()
  136. if __name__ == "__main__":
  137. parser = argparse.ArgumentParser(description="Visualizer 3d")
  138. parser.add_argument("--save_path", type=str, default=None)
  139. args = parser.parse_args()
  140. save_path = args.save_path
  141. if save_path is None:
  142. raise ValueError("Please specify the path to the saved results.")
  143. points = np.load(os.path.join(save_path, "points.npy"), allow_pickle=True)
  144. result = np.load(os.path.join(save_path, "results.npy"), allow_pickle=True).item()
  145. score_threshold = 0.25
  146. vis = Visualizer3D()
  147. vis.draw_results(points, result, score_threshold)