注意
点击 点击这里 下载完整的示例代码
04. 使用预训练的 Monodepth2 Pose 模型对图像序列测试 PoseNet¶
这是一个使用 GluonCV Monodepth2 模型(用于 KITTI)在真实世界图像上进行快速演示。如果您尚未安装 MXNet 和 GluonCV,请遵循安装指南进行安装。本教程分为三个部分:准备 KITTI Odometry 数据集,通过 GluonCV 获取预训练的 PoseNet,以及在数据集上测试 PoseNet。
立即开始测试¶
提示
您可以随时跳过本教程,因为测试脚本是完整的并且可以直接运行。
下载 完整的 Python 脚本: test_pose.py
PoseNet 测试命令示例
python test_pose.py --model_zoo_pose monodepth2_resnet18_posenet_kitti_mono_stereo_640x192 --data_path ~/.mxnet/datasets/kitti/kitti_odom --eval_split odom_9 --pretrained_type gluoncv --png
更多训练命令选项,请运行 python test_pose.py -h
请查看 模型库 获取复现预训练模型的训练命令。
深入探讨¶
import os
import mxnet as mx
from mxnet import gluon
import gluoncv
# using cpu
ctx = mx.cpu(0)
KITTI Odometry 数据集¶
准备 KITTI Odometry 数据集
您可以从 http://www.cvlibs.net/datasets/kitti/eval_odometry.php 下载 KITTI Odometry 数据集。
您需要下载 http://www.cvlibs.net/download.php?file=data_odometry_color.zip 和 http://www.cvlibs.net/download.php?file=data_odometry_poses.zip(您将通过电子邮件获取下载链接)到
$(HOME)/.mxnet/datasets/kitti/
,然后解压它们。以下是示例命令cd ~/.mxnet/datasets/kitti/ wget [the link of data_odometry_color.zip file] wget [the link of data_odometry_poses.zip file] unzip data_odometry_color.zip unzip data_odometry_poses.zip mv dataset/ kitti_odom/
KITTI 数据集在 gluoncv.data
中提供。例如,我们可以轻松获取 KITTI Odometry 数据集(我们假设您已按照深入探讨训练 Monodepth2 模型中描述的方式准备了分割文件)。
from gluoncv.data.kitti import readlines, dict_batchify_fn
splits_dir = os.path.join(os.path.expanduser("~"), ".mxnet/datasets/kitti", "splits")
eval_split = "odom_9"
sequence_id = int(eval_split.split("_")[1])
data_path = os.path.join(
os.path.expanduser("~"), '.mxnet/datasets/kitti/kitti_odom')
filenames = readlines(
os.path.join(splits_dir, "odom",
"test_files_{:02d}.txt".format(sequence_id)))
dataset = gluoncv.data.KITTIOdomDataset(
data_path=data_path, filenames=filenames, height=192, width=640, frame_idxs=[0, 1],
num_scales=4, is_train=False, img_ext=".png")
dataloader = gluon.data.DataLoader(
dataset, batch_size=1, shuffle=False, batchify_fn=dict_batchify_fn, num_workers=0,
pin_memory=True, last_batch='keep')
这里,frame_idxs
参数是 [0, 1]。这意味着数据加载器提供当前帧和下一帧作为输入。PoseNet 需要预测两帧之间的相对姿态。
请查看完整的 test_pose.py
获取完整的实现。
预训练的 PoseNet¶
接下来,我们从我们的模型库获取一个预训练模型,
输出
Downloading /root/.mxnet/models/monodepth2_resnet18_posenet_kitti_mono_stereo_640x192-c14979bb.zip from https://apache-mxnet.s3-accelerate.dualstack.amazonaws.com/gluon/models/monodepth2_resnet18_posenet_kitti_mono_stereo_640x192-c14979bb.zip...
0%| | 0/56016 [00:00<?, ?KB/s]
0%| | 102/56016 [00:00<01:10, 798.02KB/s]
1%| | 510/56016 [00:00<00:25, 2203.01KB/s]
4%|3 | 2185/56016 [00:00<00:07, 7166.04KB/s]
14%|#4 | 7870/56016 [00:00<00:02, 23928.26KB/s]
26%|##5 | 14466/56016 [00:00<00:01, 37597.52KB/s]
41%|#### | 22754/56016 [00:00<00:00, 51959.05KB/s]
53%|#####3 | 29877/56016 [00:00<00:00, 57967.43KB/s]
68%|######8 | 38270/56016 [00:00<00:00, 65967.08KB/s]
81%|########1 | 45426/56016 [00:00<00:00, 67674.96KB/s]
95%|#########5| 53368/56016 [00:01<00:00, 69627.11KB/s]
56017KB [00:01, 49968.80KB/s]
测试¶
PoseNet 的推理
首先,我们需要通过 PoseNet 生成两帧之间的变换。PoseNet 将直接输出轴角(axisangle)和位移(translation),我们将其转换为变换矩阵。然后,我们将预测的姿态存储到姿态序列中。
请查看完整的 test_pose.py
获取完整的实现。这是一个测试示例
pred_poses = []
print("-> Computing pose predictions")
opt.frame_ids = [0, 1] # pose network only takes two frames as input
tbar = tqdm(dataloader)
for i, data in enumerate(tbar):
for key, ipt in data.items():
data[key] = ipt.as_in_context(context=opt.ctx[0])
all_color_aug = mx.nd.concat(*[data[("color_aug", i, 0)] for i in opt.frame_ids], dim=1)
axisangle, translation = posenet(all_color_aug)
pred_poses.append(
transformation_from_parameters(
axisangle[:, 0], translation[:, 0]).as_in_context(mx.cpu()).asnumpy()
)
pred_poses = np.concatenate(pred_poses)
计算 ATE
这里,我们使用绝对轨迹误差(ATE)来评估 PoseNet 的性能。由于 PoseNet 也属于单目系统,它存在尺度模糊问题。为了使用地面实况(ground truth)姿态评估模型,我们将第一个姿态与地面实况对齐,并通过比较预测姿态和地面实况姿态来计算比例因子。
ATE 函数定义为
def compute_ate(gtruth_xyz, pred_xyz_o):
offset = gtruth_xyz[0] - pred_xyz_o[0]
pred_xyz = pred_xyz_o + offset[None, :]
# Optimize the scaling factor
scale = np.sum(gtruth_xyz * pred_xyz) / np.sum(pred_xyz ** 2)
alignment_error = pred_xyz * scale - gtruth_xyz
rmse = np.sqrt(np.sum(alignment_error ** 2)) / gtruth_xyz.shape[0]
return rmse
您可以立即开始测试。
参考文献¶
- Godard19
Clement Godard, Oisin Mac Aodha, Michael Firman 和 Gabriel Brostow。“深入探讨自监督单目深度估计”(Digging Into Self-Supervised Monocular Depth Estimation)。IEEE 计算机视觉会议(ICCV)论文集。2019年。
脚本总运行时间: ( 0 分钟 1.850 秒)