【论文解读】单目3D目标检测 CUPNet(ICCV 2021)

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时计算 Flink 版,1000CU*H 3个月
简介: 本文分享单目3D目标检测,CUPNet 模型的论文解读,了解它的设计思路,论文核心观点,模型结构,以及效果和性能。

 本文分享单目3D目标检测,CUPNet 模型的论文解读,了解它的设计思路,论文核心观点,模型结构,以及效果和性能。

image.gif

一、CUPNet简介

CUPNet是基于几何约束和回归方式输出3D框信息,在不依赖dcn的情况下获得了较好的性能。

它也是一款两阶段的单目3d检测器,先回归2D框信息,在ROI区域进一步提取特征,生成3D框信息。

开源地址:https://github.com/SuperMHP/GUPNet

论文地址:Geometry Uncertainty Projection Network for Monocular 3D Object Detection


二、论文核心观点

论文核心观点,主要包括为两点:

    • 1、物体高度估计误差,对深度计算有着较大的影响。
    • 2、模型训练的稳定性。在模型训练初期,物体高度的预测往往存在较大偏差,也因此导致了深度估算偏差较大。较大误差往往导致网络训练困难,从而影响整体网络性能。
    • 3、推断可靠性问题。如果物体的高度预测存在较大偏差,相应计算出的深度值也会存在较大误差。



    三、模型框架

    CUPNet是一个两阶段的框架,实现单目3d检测的。模型结构如下:

    Backbone:DLA34

    Neck:DLAUp

    第一部分 2D 检测:3个分支

      • 分支一 通过输出heatmap,预测所有类别的中心点(默认类别为3)。
      • 分支二 预测的2D框中心点的偏移。
      • 分支三 预测2D框的size。

      第二部分 3D 检测:4个分支

        • 分支一 预测偏航角。
        • 分支二 预测3D框的size。
        • 分支三 预测中心点的深度值,和和其不确定性(深度学习偏差)。
        • 分支四 预测2D框中心点与真实的3D投影坐标之间的偏移。

        模型结构如下图所示:(基于CenterNet的2D检测+ROI特征提取+基础3D检测头)

        image.gif

        整体的模型结构,可分为4步:

          1. 输入图像,经过主干网络提取特征。
          2. 基于CenterNet的2D框预测部分,用于输出热力图,信息包括:2D中心点、偏移量、2D框的尺寸。
          3. 提取出ROI的特征。
          4. 利用所提取的ROI特征,输入到不同的网络头,以获得物体3D框信息,包括:偏转角度、尺寸、深度值、物体3d框中心在图像投影点的偏移量。

          在第四步时,首先估计出3D框除了“深度值”以外的所有参数,然后2D框与3D框的高度将被输入到GUP模块中,提取出最终的depth。

          image.gif

          在输入端,图像将缩放到384×1280的大小,然后经过DLA的backbone获得96×320,通道数为64的特征图。随后经过三个简单的网络头输出2d信息

          2D 检测3个分支结构代码:

          self.heatmap = nn.Sequential(nn.Conv2d(channels[self.first_level], self.head_conv, kernel_size=3, padding=1, bias=True),
                                      nn.ReLU(inplace=True),
                                      nn.Conv2d(self.head_conv, 3, kernel_size=1, stride=1, padding=0, bias=True))
          self.offset_2d = nn.Sequential(nn.Conv2d(channels[self.first_level], self.head_conv, kernel_size=3, padding=1, bias=True),
                                      nn.ReLU(inplace=True),
                                      nn.Conv2d(self.head_conv, 2, kernel_size=1, stride=1, padding=0, bias=True))
          self.size_2d = nn.Sequential(nn.Conv2d(channels[self.first_level], self.head_conv, kernel_size=3, padding=1, bias=True),
                                      nn.ReLU(inplace=True),
                                      nn.Conv2d(self.head_conv, 2, kernel_size=1, stride=1, padding=0, bias=True))

          image.gif

          3D 检测4个分支结构代码:

          self.depth = nn.Sequential(nn.Conv2d(channels[self.first_level]+2+self.cls_num, self.head_conv, kernel_size=3, padding=1, bias=True),
                                          nn.BatchNorm2d(self.head_conv),
                                          nn.ReLU(inplace=True),nn.AdaptiveAvgPool2d(1),
                                          nn.Conv2d(self.head_conv, 2, kernel_size=1, stride=1, padding=0, bias=True))
          self.offset_3d = nn.Sequential(nn.Conv2d(channels[self.first_level]+2+self.cls_num, self.head_conv, kernel_size=3, padding=1, bias=True),
                                          nn.BatchNorm2d(self.head_conv),
                                          nn.ReLU(inplace=True),nn.AdaptiveAvgPool2d(1),
                                          nn.Conv2d(self.head_conv, 2, kernel_size=1, stride=1, padding=0, bias=True))
          self.size_3d = nn.Sequential(nn.Conv2d(channels[self.first_level]+2+self.cls_num, self.head_conv, kernel_size=3, padding=1, bias=True),
                                          nn.BatchNorm2d(self.head_conv),
                                          nn.ReLU(inplace=True),nn.AdaptiveAvgPool2d(1),
                                          nn.Conv2d(self.head_conv, 4, kernel_size=1, stride=1, padding=0, bias=True))
          self.heading = nn.Sequential(nn.Conv2d(channels[self.first_level]+2+self.cls_num, self.head_conv, kernel_size=3, padding=1, bias=True),
                                          nn.BatchNorm2d(self.head_conv),
                                          nn.ReLU(inplace=True),nn.AdaptiveAvgPool2d(1),
                                          nn.Conv2d(self.head_conv, 24, kernel_size=1, stride=1, padding=0, bias=True))

          image.gif


          四、损失函数

          CUPNet 的损失由7部分组成,

          2D 框检测损失:3部分

            • 分支一 通过输出heatmap,预测所有类别的中心点;使用 Focal Loss 函数。
            • 分支二 预测的2D框中心点的偏移;使用 L1 Loss 函数。
            • 分支三 预测2D框的size;使用 L1 Loss 函数。

            image.gif

            3D Detection损失:4部分

              • 分支一 预测偏航角。类别使用交叉熵损失,偏航角使用L1 Loss。
              • 分支二 预测3D框的size。长和宽为L1 Loss,权重占2/3,3D 高使用laplacian_aleatoric_uncertainty_loss() 函数,权重占1/3。
              • 分支三 预测中心点的深度值,和和其不确定性;使用 laplacian_aleatoric_uncertainty_loss() 函数。
              • 分支四 预测2D框中心点与真实的3D投影坐标之间的偏移;使用 L1 Loss 函数。

              image.gif



              五、核心观点——3D高度估计误差 引起深度推断误差

              在相机投影模型引入几何信息,在估计深度时采用“相似三角形模型”,如下图所示:

              depth 是深度值、f是焦距、h_3d是实际物体高度、h_2d是图像中物体的高度。(h_3d、h_2d这种表述方式是打字比较方便,有些编辑公式支持)

              image.gif

              在该关系下,depth估计可以转化为先估计h_3d与h_2d,再通过投影的方式得到。如果物体的高度预测存在较大偏差,相应计算出的深度值也会存在较大误差。

              下面作者做了实验,由 ±0.1m 3D 高度抖动引起的深度偏移的可视化示例,图中画了一些BEV鸟瞰图的例子来展示误差放大的效果。

              image.gif

              该图中,横轴和纵轴的单位均为米,纵轴对应深度方向。 绿色框表示原始投影输出。 蓝色和红色框分别是由 +0.1m和 -0.1m 3D高度偏差引起的移位框。

              从图中可以看出,即使高度估计误差只有0.1m,也可能导致4m的深度值偏差

              解决方案:

              解决的问题其实是投影模型中的误差放大现象。我们对投影模型的输入加入一个微小的偏置,其输出则会变成原始的投影结果不确定性项(偏差项)引发的depth误差的和:

              image.gif

              详细设计看GUP模块



              六、核心内容——GUP模块、HTL模块

              6.1 提出GUP模块处理推断可靠性问题

              如果只会输出单一的深度值,作者提出Geometry Uncertainty Projection (GUP) 模块,它输出深度值+不确定度,这里的不确定度是用来表征当前深度值的可靠性。

              思路流程:预测物体3D高度 → 做映射得到深度值 → 预测偏移量 → 深度值+偏移量得到最终的不确定度

              a)预测物体3D高度。作者这里引入了Laplace distribution的假设,也就是假设物体3D高度的预测值是符合拉普拉斯分布的。

              拉普拉斯分布可以用两个变量描述,均值和方差。期望3D高度预测值,均值越接近于ground-truth,方差=1最好。方差越趋近于1,表明当前高度预测值越稳定。

              通过设计损失函数,让网络朝着我们希望的方向发展:

              image.gif

              b)做映射得到深度值,如下式:

              image.gif

              将预测出的3D高度带入,即可得到深度值。

              c)预测偏移量,给深度值又加了一层不确定度的保障。

              d)深度值+偏移量得到最终的不确定度。假设深度值和偏移量是符合拉普拉斯分布,最终的深度估计值可以有如下表示:

              image.gif

              希望depth的均值无限接近于真值,其方差无限趋近于1。也就得到了下式的损失函数

              image.gif


              6.2 提出HTL模块处理训练稳定性问题

              在训练开始时,对h_2d和h_3d的预测都很不准确,会误导整体训练,损害训练表现。

                • 作者提出了一个多级task学习策略Hierarchical Task Learning (HTL) ,来进行多任务学习。
                • 既然所有模块合在一起训练不稳定,那就分开好了,分级训练,为不同模块指定不同的训练权重,用以控制其在模型训练中的重要性。



                七、实验对比与模型效果

                在KITTI 测试集上的 3D物体检测,用以粗体突出显示最佳结果

                image.gif

                在KITTI 验证集,汽车类别,进行消融实验:

                image.gif

                模型效果:

                image.gif

                image.gif

                image.gif

                image.gif

                分享完成~

                相关文章
                |
                机器学习/深度学习 传感器 算法
                【论文速递】AAAI2023 - BEVDepth: 用于多视图三维物体检测的可靠深度采集
                【论文速递】AAAI2023 - BEVDepth: 用于多视图三维物体检测的可靠深度采集
                |
                网络安全
                应用开发通过nfs来mount失败解决办法mount.nfs: Connection timed out
                应用开发通过nfs来mount失败解决办法mount.nfs: Connection timed out
                2520 0
                |
                XML 存储 分布式计算
                hbase构建二级索引解决方案
                HBase的一级索引就是rowkey,我们仅仅能通过rowkey进行检索。假设我们相对Hbase里面列族的列列进行一些组合查询,就只能全表扫描了。表如果较大的话,代价是不可接受的,所以要提出二级索引的方案。
                1320 0
                hbase构建二级索引解决方案
                |
                算法框架/工具 C++ Python
                根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
                根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
                1332 0
                |
                传感器 机器学习/深度学习 人工智能
                超全汇总 | 基于Camera的3D目标检测算法综述!(单目/双目/伪激光雷达)
                目前3D目标检测领域方案主要包括基于单目、双目、激光雷达点云、多模态数据融合等方式,本文主要介绍基于单目、双目和伪激光雷达数据的相关算法,下面展开讨论下~
                超全汇总 | 基于Camera的3D目标检测算法综述!(单目/双目/伪激光雷达)
                |
                机器学习/深度学习 传感器 算法
                单目3D目标检测 方法综述——直接回归方法、基于深度信息方法、基于点云信息方法
                本文综合整理单目3D目标检测的方法模型,包括:基于几何约束的直接回归方法,基于深度信息的方法,基于点云信息的方法。万字长文,慢慢阅读~ 直接回归方法 涉及到模型包括:MonoCon、MonoDLE、MonoFlex、CUPNet、SMOKE等。 基于深度信息的方法 涉及到模型包括:MF3D、MonoGRNet、D4LCN、MonoPSR等。 基于点云信息的方法 涉及到模型包括:Pseudo lidar、DD3D、CaDDN、LPCG等。
                2729 2
                |
                Java 关系型数据库 MySQL
                mysql5.7 jdbc驱动
                遵循上述步骤,即可在Java项目中高效地集成MySQL 5.7 JDBC驱动,实现数据库的访问与管理。
                2573 1
                |
                数据可视化 计算机视觉 异构计算
                【论文解读】单目3D目标检测 MonoCon(AAAI2022)
                本文分享单目3D目标检测,MonoCon模型的论文解读,了解它的设计思路,论文核心观点,模型结构,以及效果和性能。
                786 0
                |
                传感器 机器学习/深度学习 人工智能
                史上最全综述 | 3D目标检测算法汇总!(单目/双目/LiDAR/多模态/时序/半弱自监督)(下)
                近年来,自动驾驶因其减轻驾驶员负担、提高行车安全的潜力而受到越来越多的关注。在现代自动驾驶系统中,感知系统是不可或缺的组成部分,旨在准确估计周围环境的状态,并为预测和规划提供可靠的观察结果。3D目标检测可以智能地预测自动驾驶车辆附近关键3D目标的位置、大小和类别,是感知系统的重要组成部分。本文回顾了应用于自动驾驶领域的3D目标检测的进展。
                史上最全综述 | 3D目标检测算法汇总!(单目/双目/LiDAR/多模态/时序/半弱自监督)(下)
                |
                机器学习/深度学习 设计模式 人工智能
                人工智能和机器学习技术来优化微服务架构
                人工智能和机器学习技术来优化微服务架构
                361 1