0


单目3D车辆检测全流程实战分享-附完整代码

完整的项目代码在这里哦~

基于M3D-RPN实现单目3D检测 - 飞桨AI Studio

1. 项目说明

  当前,3D 检测作为核心技术点,在机器人、增强现实等场景下应用广泛,发挥着至关重要的作用。传统依赖激光雷达的 3D 检测方法存在传感器昂贵难以部署,点云缺失纹理信息,分辨率低等诸多问题。

  针对于此,开发单目 3D 检测模型,有效的利用图像相对于点云的种种优势,可以降低产业落地门槛,更广泛简单的部署到实际应用场景中。

  单目的 3D 目标检测近几年一直是研究的热点,虽然往算法中添加先验知识,能够一定程度的提升准确率,但是也增加了获取标签的难度和算法设计的复杂性。

图 1 - 单目 3D 检测示例

欢迎扫码获取视频课程讲解,加入单目3D检测技术交流群,欢迎志同道合的同学:

方案难点:

  • 深度信息缺失,由 2D 图像预测 3D 位置困难
  • 相机传感器敏感,受环境影响(夜晚、雨天)等较大
  • 图像层面,遮挡、截断等问题严重影响感知精度

2. 安装说明

2.1 环境要求

  • Python >= 3.6
  • paddlepaddle >= 2.0.2
  • cuda >= 9
  • boost 库
  • 常见 Python 库

In [ ]

# 安装库
! pip install shapely

2.2 解压数据及代码

项目代码在

M3D-RPN-2.0.tar

文件中,数据集在

kitti.tar

文件中,解压到合适路径即可使用。

In [ ]

# 如果希望解压到其他目录
# 可选择其他路径(默认 /home/aistudio )
! tar xf ~/data/data141443/kitti.tar
! unzip -qo ~/data/data141443/M3D-RPN-2.0.zip
! rm -rf __MACOSX

2.3 安装依赖

In [ ]

# 删除已有软连接
! rm -rf ~/M3D-RPN-2.0/dataset/kitti_split1/training
! rm -rf ~/M3D-RPN-2.0/dataset/kitti_split1/validation

In [ ]

%cd ~/M3D-RPN-2.0/
! python dataset/kitti_split1/setup_split.py
! sh dataset/kitti_split1/devkit/cpp/build.sh
! cd lib/nms && make

3. 数据准备

3.1 数据介绍

KITTI 数据集是一个用于自动驾驶场景下的计算机视觉算法测评数据集,由德国卡尔斯鲁厄理工学院(KIT)和丰田工业大学芝加哥分校(TTIC)共同创立。包含场景有市区、乡村和高速公路。本案例使用公开的 KITTI 数据集用于训练测试,共有 14999 张图片,分为训练集 3712 张,验证集 3769 张,测试集 7518 张。示例图片如下图所示:

图 2 - KITTI 数据集示例图片

3.2 数据结构

整个数据集包含图片 images,标签 labels 和相机参数 calib,每个标签文件种包含以下字段:

type---物体类别

truncated---是否截断

occluded---是否遮挡

alpha---观测角

bbox---障碍物2D框

dimension---障碍物的3D大小

location---障碍物的3D底面中心点位置

rotation_y---障碍物的朝向角

最终数据集文件组织结构为:

kitti
└── training
    ├── calib
    ├── image_2
    └── label_2

4. 模型选择

单目 3D 检测提供两种选择:基于 anchor 的方案和 anchor-free 的方案

基于anchor:从图像中估计出 3D 检测框,也无需预测中间的 3D 场景表示,可以直接利用一个区域提案网络,生成给点图像的 3D 锚点。不同于以往与类别无关的 2D 锚点,3D 锚点的形状通常与其语义标签有很强的相关性。

Anchor-free:将 2D 检测方法 CenterNet 扩展到基于图像的 3D 检测器,该框架将对象编码为单个点(对象的中心点)并使用关键点估计来找到它。此外,几个平行的头被用来估计物体的其他属性,包括深度、尺寸、位置和方向。

采用 anchor 的方法使用了 3D 障碍物的平均信息作为先验知识,3D 检测效果实际落地更好,所以我们采用经典的基于 anchor 的方法。在骨干网络部分,我们选择的是 DenseNet,这种网络建立的是前面所有层与后面层的密集连接,实现特征重用,有着省参数,扛过拟合等优点。我们提供了如下不同版本

图 3 - 不同版本 DenseNet

根据单目 3D 检测实时性的要求,这里我们选择了 DenseNet121 作为我们的骨干网络。

5. 模型训练

训练被拆分成了热身配置和主要配置。详细信息可查看 config 中的配置。

首先,在启动模型训练之前,可以修改配置文件中相关内容, 主要包括数据集的地址以及类别数量。对应到配置文件中的位置如下所示:

基础配置
  solver_type:         'sgd'
  lr:              0.004
  momentum:         0.9
  weight_decay:     0.0005
  max_iter:         50000
  snapshot_iter:     10000
  display:         20
  do_test:         True
数据集路径
  dataset_test: 'kitti_split1'
  datasets_train:
    name:         'kitti_split1'
    anno_fmt:         'kitti_det'
    im_ext:         '.png'
    scale:         1

还有一些其他的配置诸如优化器配置标签信息检测器样本等,可以在

config

目录下查看。

  • 启动热身配置训练 (不包含 depth-aware)

In [ ]

! python train.py --conf=kitti_3d_multi_warmup

6. 模型评估

评估默认配置:

output/kitti_3d_multi_warmup/conf.pkl
pkl配置
  model:         "model_3d_dilate"
  solver_type:         "sgd"
  lr:             0.004
  momentum:         0.9
  max_iter:         50000
  snapshot_iter:     10000
  do_test:         "True"
  test_scale:         512
  crop_size:         [512, 1760]
  mirror_prob:         0.5
  distort_prob:     -1
  dataset_test:     "kitti_split1"
  datasets_train:
    name:             "kitti_split1"
    anno_fmt:             "kitti_det"
    im_ext:             ".png"
    scale:             1

可视化

pkl

配置文件方法

In [ ]

import pickle
import numpy as np

PKL_PATH = 'output/kitti_3d_multi_warmup/conf.pkl'

f = open(PKL_PATH,'rb')
data = pickle.load(f)
print(data)

In [1]

%cd ~/M3D-RPN-2.0
! python test.py \
  --conf_path output/kitti_3d_multi_warmup/conf.pkl \
  --weights_path output/kitti_3d_multi_warmup/weights/iter50000.0_params.pdparams

预模型

output/kitti_3d_multi_warmup/weights/iter50000.0_params.pdparams

效果

Car
EasyModHard2D detection87.2781.7466.603D BEV24.9318.5816.693D detection19.1015.6913.15
Ped
EasyModHard2D detection72.4758.2850.073D BEV4.124.553.443D detection3.773.453.07
Cyclist
EasyModHard2D detection63.9745.9739.733D BEV11.7210.1610.163D detection10.5610.0710.07

7. 模型优化

本小节侧重展示在模型迭代过程中优化精度的思路

数据过滤:根据 bbox 可见程度、大小来过滤每个 bbox 标签,根据有无保留 bbox 过滤每张图片,整体平衡前后背景,保证训练的稳定性。

数据增强:主要使用 RandomFlip、Resize 两种数据增强策略

Anchor定义:模型输出

2D anchor定义3D anchor定义

后处理优化: 根据将 3D 相关信息组成 3D 框,投影到图像上得到投影的八点框,取八点最小外接包围框与 2D 预测结果算 IOU,通过不断的调整旋转角 ry 或深度 z,来使得 IOU 最大。此算法利用了 2D 检测的结果要比 3D 检测的结果准确的先验知识,用 2D 框来纠正预测的 3D 属性,来达到优化 3D 定位精度的目的。整体框架如下图所示:

经过调整后,在 car 类前后效果对比如下:
3D detectionEasyModHard优化前16.5713.8212.30优化后19.0915.7013.15增量+2.52+1.88+0.85

8. 模型推理

推理过程包括两个步骤:1)导出推理模型 2)执行推理代码

导出推理模型

PaddlePaddle 框架保存的权重文件分为两种:支持前向推理和反向梯度的训练模型和只支持前向推理的推理模型。二者的区别是推理模型针对推理速度和显存做了优化,裁剪了一些只在训练过程中才需要的 tensor,降低显存占用,并进行了一些类似层融合,kernel 选择的速度优化。因此可执行如下命令导出推理模型。

In [2]

! python export_model.py \
  --conf_path output/kitti_3d_multi_warmup/conf.pkl \
  --weights_path output/kitti_3d_multi_warmup/weights/iter50000.0_params.pdparams

生成的推理模型位于

inference

目录,里面包含三个文件,分别为

  • inference.pdmodel
  • inference.pdiparams
  • inference.pdiparams.info。

其中 inference.pdmodel 用来存储推理模型的结构, inference.pdiparams 和 inference.pdiparams.info 用来存储推理模型相关的参数信息。

结果保存在

inference_result

目录下。

In [4]

! python infer.py \
  --conf_path output/kitti_3d_multi_warmup/conf.pkl

9. 模型可视化

In [ ]

! python vis.py

10. 模型部署

使用飞桨原生推理库 paddle-inference,用于服务端模型部署

总体上分为三步:

  1. 创建 PaddlePredictor,设置所导出的模型路径
  2. 创建输入用的 PaddleTensor,传入到 PaddlePredictor 中
  3. 获取输出的 PaddleTensor ,将结果取出
#include "paddle_inference_api.h"
 
// 创建一个 config,并修改相关设置
paddle::NativeConfig config;
config.model_dir = "xxx";
config.use_gpu = false;
// 创建一个原生的 PaddlePredictor
auto predictor =
      paddle::CreatePaddlePredictor<paddle::NativeConfig>(config);
// 创建输入 tensor
int64_t data[4] = {1, 2, 3, 4};
paddle::PaddleTensor tensor;
tensor.shape = std::vector<int>({4, 1});
tensor.data.Reset(data, sizeof(data));
tensor.dtype = paddle::PaddleDType::INT64;
// 创建输出 tensor,输出 tensor 的内存可以复用
std::vector<paddle::PaddleTensor> outputs;
// 执行预测
CHECK(predictor->Run(slots, &outputs));
// 获取 outputs ...

更多内容详见 > C++ 预测 API介绍


本文转载自: https://blog.csdn.net/yiquanchao/article/details/125318255
版权归原作者 一拳超超 所有, 如有侵权,请联系我们删除。

“单目3D车辆检测全流程实战分享-附完整代码”的评论:

还没有评论