mmdet3d+waymo test/evaluation流程
Posted ZLTJohn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 = self.combine(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 here
for frame_num, frame_data in enumerate(file_data):
frame = open_dataset.Frame()
frame.ParseFromString(bytearray(frame_data.numpy()))
filename = f'self.prefixfile_idx:03dframe_num:03d'
for camera in frame.context.camera_calibrations:
# FRONT = 1, see dataset.proto for details
if 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 strip
frame_timestamp_micros = frame.timestamp_micros # timestamp
if 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())
参考链接
以上是关于mmdet3d+waymo test/evaluation流程的主要内容,如果未能解决你的问题,请参考以下文章
mmdet3d+waymo test/evaluation流程