145 lines
4.4 KiB
Python
145 lines
4.4 KiB
Python
|
|
#!/usr/bin/env python
|
|||
|
|
"""
|
|||
|
|
只评估BEV分割的脚本,避免3D检测为空的问题
|
|||
|
|
"""
|
|||
|
|
import os
|
|||
|
|
import sys
|
|||
|
|
import torch
|
|||
|
|
|
|||
|
|
# 设置环境
|
|||
|
|
os.environ['PATH'] = '/opt/conda/bin:' + os.environ.get('PATH', '')
|
|||
|
|
os.environ['LD_LIBRARY_PATH'] = '/opt/conda/lib/python3.8/site-packages/torch/lib:/opt/conda/lib:/usr/local/cuda/lib64:' + os.environ.get('LD_LIBRARY_PATH', '')
|
|||
|
|
os.environ['PYTHONPATH'] = '/workspace/bevfusion:' + os.environ.get('PYTHONPATH', '')
|
|||
|
|
|
|||
|
|
def main():
|
|||
|
|
import mmcv
|
|||
|
|
from mmcv import Config
|
|||
|
|
from mmdet3d.datasets import build_dataloader, build_dataset
|
|||
|
|
from mmdet3d.models import build_model
|
|||
|
|
from mmcv.runner import load_checkpoint
|
|||
|
|
from mmdet3d.apis import single_gpu_test
|
|||
|
|
|
|||
|
|
# 加载配置
|
|||
|
|
config_file = 'configs/nuscenes/det/transfusion/secfpn/camera+lidar/swint_v0p075/multitask_BEV2X_phase4b_rmtppad_segmentation.yaml'
|
|||
|
|
cfg = Config.fromfile(config_file)
|
|||
|
|
|
|||
|
|
# 设置测试模式
|
|||
|
|
cfg.data.val.test_mode = True
|
|||
|
|
|
|||
|
|
# 构建数据集
|
|||
|
|
print("构建数据集...")
|
|||
|
|
from mmdet3d.datasets import NuScenesDataset
|
|||
|
|
|
|||
|
|
val_config = {
|
|||
|
|
'type': 'NuScenesDataset',
|
|||
|
|
'dataset_root': cfg.dataset_root,
|
|||
|
|
'ann_file': cfg.dataset_root + 'nuscenes_infos_val.pkl',
|
|||
|
|
'pipeline': cfg.evaluation.pipeline,
|
|||
|
|
'object_classes': cfg.object_classes,
|
|||
|
|
'map_classes': cfg.map_classes,
|
|||
|
|
'modality': {
|
|||
|
|
'use_lidar': True,
|
|||
|
|
'use_camera': True,
|
|||
|
|
'use_radar': False,
|
|||
|
|
'use_map': False,
|
|||
|
|
'use_external': False
|
|||
|
|
},
|
|||
|
|
'test_mode': True,
|
|||
|
|
'use_valid_flag': False,
|
|||
|
|
'box_type_3d': 'LiDAR',
|
|||
|
|
'load_interval': cfg.data.val.load_interval if hasattr(cfg.data.val, 'load_interval') else 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
dataset = build_dataset(val_config)
|
|||
|
|
print(f"数据集大小: {len(dataset)}")
|
|||
|
|
|
|||
|
|
# 构建数据加载器
|
|||
|
|
data_loader = build_dataloader(
|
|||
|
|
dataset,
|
|||
|
|
samples_per_gpu=1,
|
|||
|
|
workers_per_gpu=0,
|
|||
|
|
dist=False,
|
|||
|
|
shuffle=False,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 构建模型
|
|||
|
|
print("构建模型...")
|
|||
|
|
cfg.model.train_cfg = None
|
|||
|
|
model = build_model(cfg.model, test_cfg=cfg.get("test_cfg"))
|
|||
|
|
print(f"模型heads: {list(model.heads.keys())}")
|
|||
|
|
|
|||
|
|
# 加载checkpoint
|
|||
|
|
checkpoint_path = 'runs/run-4c8ec7e5-fabdc997/epoch_1.pth'
|
|||
|
|
print(f"加载checkpoint: {checkpoint_path}")
|
|||
|
|
checkpoint = load_checkpoint(model, checkpoint_path, map_location="cpu")
|
|||
|
|
|
|||
|
|
if "CLASSES" in checkpoint.get("meta", {}):
|
|||
|
|
model.CLASSES = checkpoint["meta"]["CLASSES"]
|
|||
|
|
else:
|
|||
|
|
model.CLASSES = dataset.CLASSES
|
|||
|
|
|
|||
|
|
# 单GPU测试
|
|||
|
|
print("开始BEV分割评估...")
|
|||
|
|
model = model.cuda()
|
|||
|
|
outputs = single_gpu_test(model, data_loader)
|
|||
|
|
|
|||
|
|
print(f"推理完成,结果数量: {len(outputs)}")
|
|||
|
|
|
|||
|
|
# 保存结果
|
|||
|
|
output_file = '/data/eval_fast/bev_only_results.pkl'
|
|||
|
|
mmcv.dump(outputs, output_file)
|
|||
|
|
print(f"结果已保存至: {output_file}")
|
|||
|
|
|
|||
|
|
# 手动评估BEV分割
|
|||
|
|
print("开始BEV分割评估...")
|
|||
|
|
|
|||
|
|
# 过滤只包含分割结果的输出
|
|||
|
|
seg_results = []
|
|||
|
|
for sample in outputs:
|
|||
|
|
if 'masks_bev' in sample and 'gt_masks_bev' in sample:
|
|||
|
|
seg_results.append({
|
|||
|
|
'masks_bev': sample['masks_bev'],
|
|||
|
|
'gt_masks_bev': sample['gt_masks_bev']
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
print(f"找到 {len(seg_results)} 个有效的分割样本")
|
|||
|
|
|
|||
|
|
if seg_results:
|
|||
|
|
# 计算分割指标
|
|||
|
|
total_iou = 0
|
|||
|
|
valid_samples = 0
|
|||
|
|
|
|||
|
|
for sample in seg_results:
|
|||
|
|
pred_mask = sample['masks_bev']
|
|||
|
|
gt_mask = sample['gt_masks_bev']
|
|||
|
|
|
|||
|
|
if hasattr(pred_mask, 'cpu'):
|
|||
|
|
pred_mask = pred_mask.cpu().numpy()
|
|||
|
|
if hasattr(gt_mask, 'cpu'):
|
|||
|
|
gt_mask = gt_mask.cpu().numpy()
|
|||
|
|
|
|||
|
|
# 计算mIoU (简化版,只计算第一个类别)
|
|||
|
|
pred_flat = pred_mask[0].flatten() # 假设第一个类别是主要类别
|
|||
|
|
gt_flat = gt_mask[0].flatten()
|
|||
|
|
|
|||
|
|
# 简单IoU计算
|
|||
|
|
intersection = ((pred_flat > 0.5) & (gt_flat > 0.5)).sum()
|
|||
|
|
union = ((pred_flat > 0.5) | (gt_flat > 0.5)).sum()
|
|||
|
|
|
|||
|
|
if union > 0:
|
|||
|
|
iou = intersection / union
|
|||
|
|
total_iou += iou
|
|||
|
|
valid_samples += 1
|
|||
|
|
|
|||
|
|
if valid_samples > 0:
|
|||
|
|
avg_iou = total_iou / valid_samples
|
|||
|
|
print(".4f")
|
|||
|
|
else:
|
|||
|
|
print("没有有效的分割样本进行评估")
|
|||
|
|
|
|||
|
|
print("BEV分割评估完成!")
|
|||
|
|
|
|||
|
|
if __name__ == '__main__':
|
|||
|
|
main()
|
|||
|
|
|