176 lines
5.3 KiB
Python
Executable File
176 lines
5.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""
|
||
可视化nuScenes推理结果的简化脚本
|
||
直接使用pickle文件生成可视化
|
||
"""
|
||
|
||
import pickle
|
||
import numpy as np
|
||
import matplotlib.pyplot as plt
|
||
from pathlib import Path
|
||
import argparse
|
||
|
||
|
||
def visualize_detection_bev(results, idx=0, output_path='detection_bev.png'):
|
||
"""可视化3D检测结果(BEV视图)"""
|
||
fig, ax = plt.subplots(figsize=(12, 12))
|
||
|
||
result = results[idx]
|
||
|
||
if 'boxes_3d' in result:
|
||
boxes = result['boxes_3d']
|
||
scores = result['scores_3d']
|
||
labels = result['labels_3d']
|
||
|
||
# 类别名称
|
||
class_names = [
|
||
'car', 'truck', 'construction_vehicle', 'bus', 'trailer',
|
||
'barrier', 'motorcycle', 'bicycle', 'pedestrian', 'traffic_cone'
|
||
]
|
||
|
||
colors = plt.cm.tab10(np.linspace(0, 1, 10))
|
||
|
||
for box, score, label in zip(boxes, scores, labels):
|
||
if score < 0.3:
|
||
continue
|
||
|
||
# 提取中心和尺寸
|
||
center = box[:2]
|
||
size = box[3:5]
|
||
yaw = box[6]
|
||
|
||
# 绘制框
|
||
l, w = size[0], size[1]
|
||
corners = np.array([
|
||
[-l/2, -w/2], [l/2, -w/2],
|
||
[l/2, w/2], [-l/2, w/2], [-l/2, -w/2]
|
||
])
|
||
|
||
rot = np.array([
|
||
[np.cos(yaw), -np.sin(yaw)],
|
||
[np.sin(yaw), np.cos(yaw)]
|
||
])
|
||
corners = corners @ rot.T + center
|
||
|
||
color = colors[label % 10]
|
||
ax.plot(corners[:, 0], corners[:, 1], color=color, linewidth=2)
|
||
ax.scatter(center[0], center[1], color=color, s=50)
|
||
|
||
# 标签
|
||
class_name = class_names[label] if label < len(class_names) else f'cls_{label}'
|
||
ax.text(center[0], center[1], f'{class_name}\n{score:.2f}',
|
||
fontsize=8, color='white',
|
||
bbox=dict(boxstyle='round', facecolor=color, alpha=0.7))
|
||
|
||
ax.set_xlim(-50, 50)
|
||
ax.set_ylim(-50, 50)
|
||
ax.set_aspect('equal')
|
||
ax.grid(True, alpha=0.3)
|
||
ax.set_xlabel('X (meters)', fontsize=14)
|
||
ax.set_ylabel('Y (meters)', fontsize=14)
|
||
ax.set_title('3D Detection Results (BEV View)', fontsize=16)
|
||
|
||
plt.tight_layout()
|
||
plt.savefig(output_path, dpi=150)
|
||
plt.close()
|
||
|
||
print(f"✅ 已保存: {output_path}")
|
||
|
||
|
||
def visualize_segmentation(results, idx=0, output_path='segmentation.png'):
|
||
"""可视化BEV分割结果"""
|
||
fig, ax = plt.subplots(figsize=(10, 10))
|
||
|
||
result = results[idx]
|
||
|
||
if 'seg_pred' in result:
|
||
seg_pred = result['seg_pred'] # (C, H, W)
|
||
|
||
# 创建彩色图
|
||
h, w = seg_pred.shape[1:]
|
||
color_map = np.zeros((h, w, 3), dtype=np.uint8)
|
||
|
||
colors = {
|
||
0: [128, 64, 128], # drivable_area
|
||
1: [244, 35, 232], # ped_crossing
|
||
2: [70, 70, 70], # walkway
|
||
3: [220, 20, 60], # stop_line
|
||
4: [157, 234, 50], # carpark_area
|
||
5: [255, 255, 0], # divider
|
||
}
|
||
|
||
class_names = [
|
||
'drivable_area', 'ped_crossing', 'walkway',
|
||
'stop_line', 'carpark_area', 'divider'
|
||
]
|
||
|
||
for idx, name in enumerate(class_names):
|
||
if idx < seg_pred.shape[0]:
|
||
mask = seg_pred[idx] > 0.5
|
||
color_map[mask] = colors[idx]
|
||
|
||
ax.imshow(color_map)
|
||
ax.set_title('BEV Segmentation', fontsize=16)
|
||
ax.axis('off')
|
||
|
||
# 图例
|
||
from matplotlib.patches import Patch
|
||
legend_elements = [
|
||
Patch(facecolor=np.array(colors[i])/255, label=class_names[i])
|
||
for i in range(len(class_names))
|
||
]
|
||
ax.legend(handles=legend_elements, loc='upper right')
|
||
|
||
plt.tight_layout()
|
||
plt.savefig(output_path, dpi=150)
|
||
plt.close()
|
||
|
||
print(f"✅ 已保存: {output_path}")
|
||
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser()
|
||
parser.add_argument('--results', default='results.pkl', help='结果pickle文件')
|
||
parser.add_argument('--output-dir', default='visualizations', help='输出目录')
|
||
parser.add_argument('--samples', type=int, default=5, help='可视化样本数')
|
||
args = parser.parse_args()
|
||
|
||
print(f"\n{'='*80}")
|
||
print("可视化nuScenes推理结果")
|
||
print(f"{'='*80}\n")
|
||
|
||
# 创建输出目录
|
||
Path(args.output_dir).mkdir(exist_ok=True)
|
||
|
||
# 加载结果
|
||
print(f"加载结果: {args.results}")
|
||
with open(args.results, 'rb') as f:
|
||
results = pickle.load(f)
|
||
|
||
print(f"结果数量: {len(results)}")
|
||
print(f"可视化前 {min(args.samples, len(results))} 个样本\n")
|
||
|
||
# 可视化
|
||
for i in range(min(args.samples, len(results))):
|
||
print(f"处理样本 {i+1}/{min(args.samples, len(results))}...")
|
||
|
||
det_path = Path(args.output_dir) / f"sample_{i:04d}_detection.png"
|
||
seg_path = Path(args.output_dir) / f"sample_{i:04d}_segmentation.png"
|
||
|
||
visualize_detection_bev(results, i, str(det_path))
|
||
visualize_segmentation(results, i, str(seg_path))
|
||
|
||
print(f"\n{'='*80}")
|
||
print(f"✅ 完成!结果保存在: {args.output_dir}/")
|
||
print(f"{'='*80}\n")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|
||
|
||
|
||
|
||
|
||
|
||
|