#!/usr/bin/env python """ 简单BEV分割可视化 - 不依赖mmdet3d库 """ import os import pickle import numpy as np import matplotlib.pyplot as plt def load_results_safely(filepath): """安全加载结果,避免CUDA库问题""" # 临时禁用CUDA相关的导入 import sys original_modules = sys.modules.copy() try: # 阻止可能导致CUDA导入的模块 blocked_modules = [ 'mmdet3d', 'torch', 'torchvision', 'torchaudio', 'mmcv', 'mmdet', 'torchpack' ] for mod in blocked_modules: if mod in sys.modules: del sys.modules[mod] with open(filepath, 'rb') as f: results = pickle.load(f) return results, True except Exception as e: print(f"标准加载失败: {e}") return None, False finally: # 恢复原始模块状态 sys.modules.update(original_modules) def visualize_bev_masks(masks_bev, sample_idx=0, save_dir='bev_visualization'): """可视化BEV分割结果""" os.makedirs(save_dir, exist_ok=True) # 类别名称 class_names = ['drivable_area', 'ped_crossing', 'walkway', 'stop_line', 'carpark_area', 'divider'] colors = ['green', 'yellow', 'orange', 'red', 'purple', 'black'] # 如果是torch tensor,转换为numpy if hasattr(masks_bev, 'cpu'): masks_bev = masks_bev.cpu().numpy() fig, axes = plt.subplots(2, 3, figsize=(15, 10)) fig.suptitle(f'BEV分割结果 - 样本 {sample_idx}', fontsize=16) for i in range(6): row, col = i // 3, i % 3 ax = axes[row, col] mask = masks_bev[i] if hasattr(mask, 'cpu'): mask = mask.cpu().numpy() # 显示mask (0-1之间的概率) im = ax.imshow(mask, cmap='viridis', vmin=0, vmax=1) ax.set_title(f'{class_names[i]}\n激活像素: {(mask > 0.5).sum()}') ax.axis('off') # 计算统计信息 activated_pixels = (mask > 0.5).sum() total_pixels = mask.size percentage = activated_pixels / total_pixels * 100 print("15s") # 添加颜色条 plt.tight_layout() cbar_ax = fig.add_axes([0.92, 0.15, 0.02, 0.7]) fig.colorbar(im, cax=cbar_ax, label='预测概率') # 保存图像 save_path = os.path.join(save_dir, f'bev_segmentation_sample_{sample_idx}.png') plt.savefig(save_path, dpi=300, bbox_inches='tight') print(f"\nBEV分割可视化已保存: {save_path}") plt.show() # 创建叠加视图 fig, ax = plt.subplots(1, 1, figsize=(10, 10)) ax.set_title(f'BEV分割叠加视图 - 样本 {sample_idx}') # 创建彩色叠加图像 height, width = masks_bev[0].shape overlay = np.zeros((height, width, 3), dtype=np.uint8) for i in range(6): mask = masks_bev[i] if hasattr(mask, 'cpu'): mask = mask.cpu().numpy() # 只显示高置信度区域 binary_mask = mask > 0.5 # 为每个类别分配颜色 if class_names[i] == 'drivable_area': color = [0, 255, 0] # 绿色 elif class_names[i] == 'ped_crossing': color = [255, 255, 0] # 黄色 elif class_names[i] == 'walkway': color = [255, 165, 0] # 橙色 elif class_names[i] == 'stop_line': color = [255, 0, 0] # 红色 elif class_names[i] == 'carpark_area': color = [128, 0, 128] # 紫色 else: # divider color = [0, 0, 0] # 黑色 # 应用颜色 (只在mask区域) for c in range(3): overlay[binary_mask, c] = color[c] ax.imshow(overlay) ax.set_title(f'BEV分割叠加 (高置信度区域) - 样本 {sample_idx}') ax.axis('off') # 添加图例 legend_elements = [] for i, name in enumerate(class_names): if class_names[i] == 'drivable_area': color = [0, 255, 0] elif class_names[i] == 'ped_crossing': color = [255, 255, 0] elif class_names[i] == 'walkway': color = [255, 165, 0] elif class_names[i] == 'stop_line': color = [255, 0, 0] elif class_names[i] == 'carpark_area': color = [128, 0, 128] else: color = [0, 0, 0] import matplotlib.patches as mpatches patch = mpatches.Patch(color=np.array(color)/255, label=name) legend_elements.append(patch) ax.legend(handles=legend_elements, bbox_to_anchor=(1.05, 1), loc='upper left') overlay_path = os.path.join(save_dir, f'bev_overlay_sample_{sample_idx}.png') plt.savefig(overlay_path, dpi=300, bbox_inches='tight') print(f"BEV叠加可视化已保存: {overlay_path}") plt.show() def analyze_3d_detection(sample, sample_idx=0): """分析3D检测结果""" print(f"\n=== 3D检测结果分析 - 样本 {sample_idx} ===") if 'boxes_3d' in sample: boxes_3d = sample['boxes_3d'] print(f"3D检测框数量: {len(boxes_3d)}") if len(boxes_3d) > 0: if hasattr(boxes_3d, 'cpu'): boxes_3d = boxes_3d.cpu().numpy() print(f"检测框形状: {boxes_3d.shape}") # 分析检测框的范围 if boxes_3d.shape[1] >= 7: # x, y, z, w, l, h, rot x_coords = boxes_3d[:, 0] y_coords = boxes_3d[:, 1] z_coords = boxes_3d[:, 2] print(".2f") print(".2f") print(".2f") if 'scores_3d' in sample: scores_3d = sample['scores_3d'] if len(scores_3d) > 0: if hasattr(scores_3d, 'cpu'): scores_3d = scores_3d.cpu().numpy() print(".3f") if 'labels_3d' in sample: labels_3d = sample['labels_3d'] if len(labels_3d) > 0: if hasattr(labels_3d, 'cpu'): labels_3d = labels_3d.cpu().numpy() unique_labels, counts = np.unique(labels_3d, return_counts=True) print("检测类别分布:") for label, count in zip(unique_labels, counts): print(f" 类别 {int(label)}: {count} 个") def main(): # 推理结果文件 result_file = '/data/infer_test/20251120_124755/one_batch_results.pkl' print("开始分析推理结果...") print(f"结果文件: {result_file}") # 加载结果 results, success = load_results_safely(result_file) if not success or results is None: print("无法加载结果文件") return print(f"成功加载! 包含 {len(results)} 个样本") # 分析第一个样本 sample_idx = 0 if sample_idx < len(results): sample = results[sample_idx] print(f"\n样本 {sample_idx} 包含字段: {list(sample.keys())}") # 可视化BEV分割 if 'masks_bev' in sample: print("\n开始BEV分割可视化...") visualize_bev_masks(sample['masks_bev'], sample_idx) # 分析3D检测 analyze_3d_detection(sample, sample_idx) # 分析Ground Truth (如果有) if 'gt_masks_bev' in sample: gt_masks = sample['gt_masks_bev'] print(f"\nGround Truth BEV分割形状: {gt_masks.shape}") else: print(f"样本索引 {sample_idx} 超出范围") if __name__ == '__main__': main()