mmdet3d+waymo test/evaluation流程

编程入门 行业动态 更新时间:2024-10-27 16:37:35

mmdet3d+waymo test/evaluation<a href=https://www.elefans.com/category/jswz/34/1770115.html style=流程"/>

mmdet3d+waymo test/evaluation流程

evaluation是最直观反映模型性能和问题的步骤,也是检验运行环境是否有错的重要一换,下面依托detr3d与custom waymo dataset类,介绍一下mmdet3d+waymo在eval的流程。
调用eval有两种流程,一种是training过程中eval,另一种是调用test.py,test.py支持validation set和test set的处理。无论哪种,其核心都是调用dataset类下的evaluate方法。下面主要讲调用test.py的流程。

evaluation

调用bash

bash tools/dist_test.sh \
projects/configs/detr3d/detr3d_res101_gridmask_waymo.py \
work_dirs/detr3d_res101_gridmask_waymo/epoch_10.pth \
8 --eval=waymo

其中 --eval代表evaluate的时候用哪种style的metric,比如waymo,在mmdet3d里支持kitti和waymo两种style。

tools/dist_test.sh

CONFIG=$1
CHECKPOINT=$2
GPUS=$3
PORT=${PORT:-29500}PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \
python -m torch.distributed.launch --nproc_per_node=$GPUS --master_port=$PORT \$(dirname "$0")/test.py $CONFIG $CHECKPOINT --launcher pytorch ${@:4}

就是用torch的distributed.launch方法来启动我们的test.py。这里有个巨坑是之后可能会调用tensorflow,环境配置不好的话就会出现cuda error,解决方法后面说。

tools/test.py

和tools/train.py类似。首先处理命令行参数,读config文件,初始化dataset,dataloader,载入model。
值得注意的是dataset = build_dataset(cfg.data.test),也就是config文件的‘data’里,‘test’的部分;data里还有’train’和’eval’,这个都是在training流程里使用的。
初始化后,就是把image放进model里,然后进行evaluate了,核心代码如下:

outputs = single_gpu_test(model, data_loader, args.show, args.show_dir)
#list of dict where dict['pts_bbox']=dict(bboxes scores labels)
if args.format_only:dataset.format_results(outputs, **kwargs)
if args.eval:print(dataset.evaluate(outputs, **eval_kwargs))

如果跑的是test set,没有gt box,就只会format result,否则调用dataset的evaluate函数。下面先讲讲single gpu test,再讲evaluate

single_gpu_test

这个函数位于mmdet3d/apis/test.py中,核心就是

model.eval()
results = []
for i, data in enumerate(data_loader):with torch.no_grad():result = model(return_loss=False, rescale=True, **data)if args.show: ...results.extend(result)

result的格式为[dict(),dict()...],其中result[0]['pts_bbox']存了每个frame的所有bbox相关信息,也是一个dict,格式如下:

 predictions_dict = {'bboxes': boxes3d,'scores': scores,'labels': labels}

不太重要的细节:

detr3d的detector在调用forward处理batched input tensor之后,会调用bbox coder把output feature整理成bboxes,并把一个batch的bboxes按frame分开,形成一个list。在分开的同时,gpu上的data也放到了cpu上。

dataset.evaluate(output, …)

waymo_dataset类里,不仅定义了如何读取数据,也定义了如何根据数据进行evaluation;后者在代码里占了很大部分。
evaluate有kitti和waymo标准,下面只讲waymo的,核心代码如下:

result_files, tmp_dir = self.format_results(results,pklfile_prefix,submission_prefix,data_format='waymo')ret_bytes = subprocess.check_output(        'mmdetection3d/mmdet3d/core/evaluation/waymo_utils/' +f'compute_detection_metrics_main {pklfile_prefix}.bin ' +f'{waymo_root}/gt.bin',shell=True)
ret_texts = ret_bytes.decode('utf-8')
print(ret_texts)

由于我们之前处理出的waymo数据都是kitti格式的,需要调用format_results把格式转回waymo。比如最关键的bbox坐标,都是以front_cam为坐标系的,我们要把他转回以lidar坐标。结果会存到一个.bin文件里。

转回去之后,调用github: waymo-open-dataset提供的compute_detection_metrics_main,比较我们的.bin文件,和validation set里面本来就有的laser_gt.bin,从而得到metric。值得一提的是.bin文件是protobuf文件,其类型为waymo_open_dataset.protos.metrics_pb2.Objects(),定义可以在相关的.proto文件里查看。也可以用python很方便地查看他的内容。

dataset.format_results(results)

输入是model得到的bbox,函数首先将list of dict的格式转换成kitti format的result,然后再调用KITTI2Waymo converter,把kitii format转换成waymo format。核心代码如下:

result_files = self.bbox2result_kitti(outputs,self.CLASSES,pklfile_prefix,submission_prefix)
converter = KITTI2Waymo(result_files['pts_bbox'],waymo_tfrecords_dir,waymo_results_save_dir,waymo_results_final_path, prefix)
converter.convert()

bbox2result_kitti返回的result_files 为:List[dict]: A list of dict have the kitti 3d format ,主要负责一些简单的格式转换。

KITTI2Waymo主要负责把dict格式转换成metric_pb2.object格式,其中内容也有变:坐标系的变换,添加timestamp,context_name使得能够匹配到gt.bin对应的object

mmdet3d/core/evaluation/waymo_utils/KITTI2Waymo

这一块是比较坑爹的,因为他多线程读tfrecord文件来获得timestamp和cam_to_velodyne变换矩阵,读取的过程tensorflow又莫名其妙用了gpu,导致我每次运行都报错,下面讲讲具体流程。

self. __ init __
    def __init__(self,kitti_result_files,waymo_tfrecords_dir,waymo_results_save_dir,waymo_results_final_path,prefix,workers=64):

其他重要内容:
self.waymo_tfrecord_pathnames获取validation set底下所有.tfrecord的pathname
self.name2idx是一个dict,存储ABBBCCC -> result index的映射。ABBBCCC就是kitti format的一帧的命名方式,其中A=1,代表valildation set,BBB对应tfrecord的index,CCC是tfrecord里第几帧;result index就是我们的result_files的index。

self.convert
mmcv.track_parallel_progress(self.convert_one, range(len(self.waymo_tfrecord_pathnames)), self.workers)
# combine all seperate .bin files into one .bin
pathnames = sorted(glob(join(self.waymo_results_save_dir, '*.bin')))
combined = selfbine(pathnames)
with open(self.waymo_results_final_path, 'wb') as f:f.write(combined.SerializeToString())

这里用了mmcv的方法,并行调用convert_one,遍历每个tfrecord提取每个frame的参数。每个frame会形成一个.bin文件,最后把分散的.bin文件合成一个.bin,就可以和gt.bin比较了。

self.conver_one

如下可见,对于每个线程,我们都调用tensorflow来读取.tfrecord文件,这一读就坏了,具体的原因未知,之后开一篇总结一下碰到的坑,解决办法就是把这些信息用dict存到其他格式的文件里,不读取.tfrecord就不会错了。
如下图可见,如果tfrecord里的某个frame和kitti result能对上,那么就用这个frame的转换矩阵、timestamp等信息来把对应的kitti_result转换成waymo format result,并存在一个bin里。调用的是parse_object函数,相关转换方法可以参考下面的链接二。

def convert_one(self, file_idx):"""Convert action for single file.Args:file_idx (int): Index of the file to be converted."""file_pathname = self.waymo_tfrecord_pathnames[file_idx]file_data = tf.data.TFRecordDataset(file_pathname, compression_type='')## return still got error herefor frame_num, frame_data in enumerate(file_data):frame = open_dataset.Frame()frame.ParseFromString(bytearray(frame_data.numpy()))filename = f'{self.prefix}{file_idx:03d}{frame_num:03d}'for camera in frame.context.camera_calibrations:# FRONT = 1, see dataset.proto for detailsif camera.name == 1:T_front_cam_to_vehicle = np.array(camera.extrinsic.transform).reshape(4, 4)T_k2w = T_front_cam_to_vehicle @ self.T_ref_to_front_cam    # inverse(Tr_velo_to_cam)context_name = frame.context.name               # file name stripframe_timestamp_micros = frame.timestamp_micros     # timestampif filename in self.name2idx:kitti_result = \self.kitti_result_files[self.name2idx[filename]]objects = self.parse_objects(kitti_result, T_k2w, context_name,frame_timestamp_micros)else:print(filename, 'not found.')objects = metrics_pb2.Objects()with open(join(self.waymo_results_save_dir, f'{filename}.bin'),'wb') as f:f.write(objects.SerializeToString())

参考链接

  1. waymo 数据集-MMDetection3D
  2. 带你玩转 3D 检测和分割 (二):核心组件分析之坐标系和 Box

更多推荐

mmdet3d+waymo test/evaluation流程

本文发布于:2024-03-08 06:32:06,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1720070.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:流程   waymo   mmdet3d   evaluation   test

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!