请点击此处查看本环境基本用法.

Please click here for more detailed instructions.

Monodepth-基于自监督学习的单目深度估计模型

1. 简介

Monodepth是通过自监督学习进行单目深度估计的一种方法。其主要通过预测中间变量disparity(视差)来对一侧图像进行变换重建另一侧图像,并以重构损失进行训练。视差d与真正的深度图D之间存在着变换:D=bf/d,其中b为双目相机的间距,f为相机焦距。故当某一组相机配置固定时,得知视差图便相当于得到了深度图。

以下为官方模型在KITTI测试图像上的预测结果:

论文: Unsupervised Monocular Depth Estimation with Left-Right Consistency

参考repo: monodepth

在此非常感谢@mrharicot等人贡献的nomodepth,提高了本repo复现论文的效率。

aistudio体验教程: 地址

2. 数据集

本项目使用两种数据集:KITTI数据集和Cityscapes数据集。

KITTI是一个自动驾驶领域常用的数据集,其由配置了传感器的汽车于德国卡尔斯鲁厄采集,数据中包含了双目彩色图像、深度图像、雷达点云等传感数据,并提供目标检测、实例分割等常见CV任务的标签。本项目使用AI Studio上的KITTI压缩数据集,全部数据可从此处下载。在训练过程中只需要双目图像,所以只解压jpg_images.tar.*即可。

KITTI数据集存在两种划分,一种是官方标准划分,称为KITTI划分,另一种是Eigen et. al.提出的Eigen划分方式。领域内更常用Eigen划分进行评估。由于在评估时需要点云数据来计算深度图的groundtruth,解压全部点云数据集占用硬盘空间过大,我们对Eigen划分的测试集进行了单独的打包,可在此处下载。

Cityscapes也是自动驾驶领域的常用数据集,出现时间晚于KITTI,其同样是配置了传感器的汽车进行采集,采集的范围扩大到了德国的50座城市,包含了20k+对高清的双目城市图像,并提供了实例分割任务标签。数据集中原始数据为.png格式,占用空间较大,按照原仓库设置,使用convert -quality 92 -sampling-factor 2x2,1x1,1x1 {.}.png {.}.jpg && rm {}.png压缩为.jpg格式。压缩后的双目数据集可从此处下载。

本地运行代码的同学需自行下载三个数据集进行解压。

3. 复现精度

按照原文中最优结果的设置,首先在Cityscapes数据集上预训练模型,之后在KITTI上进行finetune。

两次训练采用相同且与原文代码一致的训练参数:batch size 8,epoch 50,优化器Adam,初始学习率1e-4,30个epoch后减小为5e-5,40个epoch后减小为2.5e-5。原文和仓库并没有提供最优模型的选择方法,我们保存验证集loss最低的模型为最优模型。

abs_relsq_relrmslog_rmsd1_alla1a2a3
原文精度0.13041.19655.2220.2260.0000.8430.9400.971
复现精度0.12901.23935.2650.2260.0000.8430.9410.972

训练日志链接:cityscapes log, eigen log
权重文件链接:official tensorflow weight, cityscapes pretrained weight, city2eigen finetuned weight

4. 快速开始

准备数据

根据需要训练、测试需求准备数据,由于AI Studio最多只能加载2份数据集,所以以下数据集只能使用两个,同学们根据需求自行挂载、解压数据。

# 解压Cityscapse数据集,用于预训练
%cd /home/aistudio/data/data124090
!unzip cityspaces.zip
# 解压KITTI数据集,用于训练
%cd /home/aistudio/data/data15348
!rm non_image.tar.xz.* # 删除数据节省空间,避免超过AI Studio限制
!cat jpg_images.tar.* | tar -x
!rm jpg_images.tar.*
# 解压Eigen Split测试集,用于测试和评估
%cd /home/aistudio/data/data124009
!tar -xzf eigen_test.tgz

配置环境

%cd ~/work/monodepth-paddle/
!pip install -r requirements.txt

训练

本部分提供了完整的pretrain+finetune训练代码,大家根据自己的挂载的数据集进行选择。也可以选择跳过训练,直接用weights文件夹中提供的权重进行测试。weights中包含了三个模型:

  • tensorflow_city2eigen_resnet.h5 官方仓库的最优模型
  • city_resnet.pdparams 本项目预训练模型,为第一条训练指令的结果
  • city2eigen_resnet.pdparams 本项目的最终模型,为第二条训练指令的结果
# 在cityscapes上预训练
!python main.py --mode train \
    --data_path /home/aistudio/data/data124090 --dataset cityscapes \
    --filenames_train filenames/cityscapes_train_files.txt --filenames_val filenames/cityscapes_val_files.txt \
    --log_directory logs --model_name city_resnet 
# 在KITTI-Eigen上finetune
!python main.py --mode train \
    --data_path /home/aistudio/data/data15348/kitti --dataset kitti \
    --filenames_train filenames/eigen_train_files.txt --filenames_val filenames/eigen_val_files.txt \
    --log_directory logs --model_name city2eigen_resnet \
    --checkpoint_path logs/city_resnet/best_val_weight.pdparams

测试

!python main.py --mode test \
    --data_path /home/aistudio/data/data124009/eigen \
    --filenames_test filenames/eigen_test_files.txt --log logs \
    --output_directory outputs \
t_directory outputs \
    --encoder resnet --checkpoint_path logs/city2eigen_resnet/best_val_weight.pdparams

评估

!python eval/evaluate_kitti.py --split eigen --predicted_disp_path outputs/disparities_pp.npy --gt_path /home/aistudio/data/data124009/eigen/

对单个图像进行深度估计

**注意:**预测得到的结果为视差图d,真正的深度图D=k/d,其中k为某与相机相关的常数,需要深度图的同学可以针对自己的问题手动调整这个常数得到合理的深度图。

!python demo.py --image_path pic/demo.jpg --checkpoint_path weights/city2eigen_resnet.pdparams

4. 代码结构

├── eval
|   ├── evaluation_utils.py # 评测辅助函数
│   └── evaluate_kitti.py # 评测脚本
├── filenames/ # 各个数据集的训练、验证、测试集划分
├── LICENSE
├── README.md
├── data.py # 数据集定义
├── main.py # 主入口,训练/测试
├── model.py # 网络定义
├── demo.py # 单张图像深度估计脚本
├── requirements.txt # 依赖包
└── utils.py # 功能函数

5. 复现心得

需要注意的细节:

  • paddle.meshgridnp.meshgrid效果不同,np.meshgrid(x, y)等价于paddle.meshgrid(y, x)
  • paddle.gather存在bug,会强行对不可导的index进行求导,导致报错,故需要对index进行detach
  • 进行水平翻转数据增强时,左右图像需要换位。(非常重要,否则模型会躺平…)
  • 在Cityscapes数据集在Eigen测试集上的表现并不好,这是由于两个数据集的相机不同内参及配置方式不同,导致了两者的视差图相差了某常数倍。

也许是受限于当时的显存限制,原文的训练使用了仅为8的batchsize,这对于进行了如此复杂的数据增强的模型来说可能过小,增大batch size或许有助于进一步提升性能;另外,在实验中我注意到在每次lr decay时验证集损失会有一个阶梯式的下降并迅速饱和,这与之前resnet在图像分类时的实验现象一致,所以相应的,改变学习率衰减策略为cosine也许会更好。感兴趣的同学可以继续调参~

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐