【三维目标检测模型】ImVoxelNet

news2024/11/16 23:48:51

 【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。   

参考书籍:《人工智能点云处理及深度学习算法》

        ImVoxelNet是一种基于RGB图像的三维目标检测模型,发表在WACV 2022 《ImVoxelNet: Image to Voxels Projection for Monocular and Multi-View General-Purpose 3D Object Detection》,论文地址为“https://arxiv.org/abs/2106.01178”,官方程序地址为“https://github.com/saic-vul/imvoxelnet”。ImVoxelNet是一种端到端的基于单目或多视图RGB图像的深度学习卷积神经网络3D目标检测检测方法。其中,多视图RGB图像来源于多个传感器或多帧数据,并且该模型结构能够兼容室内和室外场景。截至目前,ImVoxelNet在SUN RGB-D数据集上同类预测任务排名种仍然保持第1名。数据来源于paperwithcode官网,如下图所示,网址为“https://paperswithcode.com/sota/monocular-3d-object-detection-on-sun-rgb-d”。

        ImVoxelNet论文与参考程序同时考虑了室内和室外场景,程序中输入数据集分别为KITTI和SUN RGB-D。室内和室外训练程序命令分别如下:

python tools/train.py configs/imvoxelnet/imvoxelnet_4x8_kitti-3d-car.py
python tools/train.py configs/imvoxelnet/imvoxelnet_4x2_sunrgbd-3d-10class.py

        ImVoxelNet模型结构如下图所示,主要包括图像特征提取、体素分割、3D CNN和Head结构。图像特征采用了ResNet50神经网络进行提取。模型对空间进行体素划分,并且通过其在图像范围内对应坐标与图像特征进行关联,将相应位置的图像特征作为体素特征。经过该步骤后,模型得到了空间中各个体素的特征。基于三维点云的深度学习算法通常是将空间划分为体素化之后,采用PointNet等方式提取体素特征,即VFE层输出。因此,ImVoxelNet将图像特征作为VFE层输出并与体素相对应。那么,模型实际上得到了与基于点云模型一样的输出。因此,后续模型结构网络可按照相同方式进行设计。例如,3D CNN层作用可看作是Middle中间层的一种实现方式。Head则是对分类和回归结果的预测。该模型在室内情况下采用了FCOS模型中的Head结构;在室外情况下则直接使用了BEV视图上的基于二维卷积的Head结构。

下面以室内情况详细介绍ImVoxelNet模型过程,输入数据集为KITTI。

1 主干网络

        ImVoxelNet模型主干网络采用了ResNet50结构,输出四种不同尺寸的特征图,分别对应4倍、8倍、16倍和32倍下采样。输入图像的特征维度为3x416x1312,输出特征维度依次为256x104x328、512x52x164、1024x26x82和2048x13x41。根据之前分析,通常情况下,随着网络深度增加,特征图尺寸减少,通道数量增加,即特征视野范围和特征属性维度增加。主干网络函数入口为self.backbone(img)。

2 Neck网络

        ImVoxelNet模型的Neck网络采用了特征金字塔(FPN)结构。特征金字塔对主干网络不同尺寸特征从最深层特征(尺寸最小)逐一上采样并与更浅一层特征进行融合,从而使浅层特征融合了深层特征以获取全局性更强的特征信息。特征融合采用求和方式实现,因而要求特征图的维度完全一致。特征图维度包括batch size、通道和尺寸。其中,特征图尺寸通过上采样来达成一致;通道数量则通过二维卷积操作来实现一致。ImVoxelNet模型FPN的融合通道数为64,即主干网络输出的特征通道数量经过二维卷积操作后均为64。模型将融合后的最浅层特征作为FPN的输出,特征维度为64x104x328,入口函数为x = self.neck(x)[0]。

        ImVoxelNet模型FPN结构即配置如下。

FPN(
  (lateral_convs): ModuleList(
    (0): ConvModule(
      (conv): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1))
    )
    (1): ConvModule(
      (conv): Conv2d(512, 64, kernel_size=(1, 1), stride=(1, 1))
    )
    (2): ConvModule(
      (conv): Conv2d(1024, 64, kernel_size=(1, 1), stride=(1, 1))
    )
    (3): ConvModule(
      (conv): Conv2d(2048, 64, kernel_size=(1, 1), stride=(1, 1))
    )
  )
  (fpn_convs): ModuleList(
    (0): ConvModule(
      (conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    )
    (1): ConvModule(
      (conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    )
    (2): ConvModule(
      (conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))

    )
    (3): ConvModule(
      (conv): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    )
  )
)
x = self.neck(x)[0]
x1 conv2d(256, 64) 4x64x104x328 x1
x2 conv2d(512, 64) 4x64x52x164  x2
x3 conv2d(1024, 64) 4x64x26x82 x3
x4 conv2d(2048, 64) 4x64x13x41 x4
x4     x3   x2  x1
upsample

Add upsanple add upsample add
特征融合后的x1 x2 x3 x4
x1 conv2d(64, 64) 4x64x104x328 x1
x2 conv2d(64, 64) 4x64x52x164  x2
x3 conv2d(64, 64) 4x64x26x82 x3
x4 conv2d(64, 64) 4x64x13x41 x4
out = x1 4x64x104x328 neck
self.n_voxels 216x248x12

3 生成点特征

        ImVoxelNet模型将空间划分成216x248x12个体素网格空间,并将每个体素中心看作一个点云中的一个点,从而得到一个完整的点云Points。模型共计生成216x248x12=642816个点。整个体素空间的BEV视图上各个网格设置两种anchor,anchor尺寸为3.9、1.6、1.56,方向分别为0和Π。每个anchor的7个参数组成分别为x、y、z、l、w、h、θ。Anchor的维度为248x216x1x2x7。

        全部体素中心点投影到图像坐标系,并转换到与RGB图像相同分辨率。模型通过对图像特征进行插值得到体素投影后图像的特征,从而Points投影后每个位置获取了来源于图像的特征,进而相当于为每个体素的都赋予了特征属性,即点云空间的特征属性。特征维度为642816x64(64x216x248x12),即点的数量和点的特征维度。由于该特征是由图像特征插值而来,因而特征属性数量保持不变,均为64。 模型用valid_preds(1x216x248x12)来标记特征全为0的体素点,可理解为相应体素内不含有点云。

        获取空间体素或点特征之后,ImVoxelNet结构的后续网络与常规的三维目标检测结构一致,其主要采用了FCOS模型中的模型方法。

4 Neck3d

        Neck3d采用4组残差模块(ResModule,参考ResNet18)和两个卷积模块,共计10个3d卷积模块来进行进行特征提取。提取后特征维度由64x216x248x12更新为256x248x216,深度方向特征维度降为1,特征图尺寸为248x216,特征属性维度为256。三维特征图转变为二维特征图,即BEV视图特征。这是由于在室外场景下,我们主要关注BEV视图上可能存在的目标。此外,转换为二维特征图有利于降低后续运算量并使用二维卷积提取更深层次特征。

OutdoorImVoxelNeck(
  (model): Sequential(
    (0): ResModule(
      (conv0): ConvModule(
        (conv): Conv3d(64, 64, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1), bias=False)
        (bn): BatchNorm3d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (activate): ReLU(inplace=True)
      )
      (conv1): ConvModule(
        (conv): Conv3d(64, 64, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1), bias=False)
        (bn): BatchNorm3d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
      (activation): ReLU(inplace=True)
    )
    (1): ConvModule(
      (conv): Conv3d(64, 128, kernel_size=(3, 3, 3), stride=(1, 1, 2), padding=(1, 1, 1), bias=False)
      (bn): BatchNorm3d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (activate): ReLU(inplace=True)
    )
    (2): ResModule(
      (conv0): ConvModule(
        (conv): Conv3d(128, 128, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1), bias=False)
        (bn): BatchNorm3d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (activate): ReLU(inplace=True)
      )
      (conv1): ConvModule(
        (conv): Conv3d(128, 128, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1), bias=False)
        (bn): BatchNorm3d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
      (activation): ReLU(inplace=True)
    )
    (3): ConvModule(
      (conv): Conv3d(128, 256, kernel_size=(3, 3, 3), stride=(1, 1, 2), padding=(1, 1, 1), bias=False)
      (bn): BatchNorm3d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (activate): ReLU(inplace=True)
    )
    (4): ResModule(
      (conv0): ConvModule(
        (conv): Conv3d(256, 256, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1), bias=False)
        (bn): BatchNorm3d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (activate): ReLU(inplace=True)
      )
      (conv1): ConvModule(
        (conv): Conv3d(256, 256, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1), bias=False)
        (bn): BatchNorm3d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
      (activation): ReLU(inplace=True)
    )
    (5): ConvModule(
      (conv): Conv3d(256, 256, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 0), bias=False)
      (bn): BatchNorm3d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (activate): ReLU(inplace=True)
    )
  )
)

5 Head和损失函数

        ImVoxelNet模型的Head结构包括目标分类、方向分类和位置回归三部分,三者损失函数分别为FocalLoss、CrossEntropyLoss和SmoothL1Loss,参配置如下所示:

Anchor3DHead(
  (loss_cls): FocalLoss()
  (loss_bbox): SmoothL1Loss()
  (loss_dir): CrossEntropyLoss(avg_non_ignore=False)
  (conv_cls): Conv2d(256, 2, kernel_size=(1, 1), stride=(1, 1))
  (conv_reg): Conv2d(256, 14, kernel_size=(1, 1), stride=(1, 1))
  (conv_dir_cls): Conv2d(256, 4, kernel_size=(1, 1), stride=(1, 1))
)

        分类head:256x248x216特征经过conv_cls(256x2)得到2x248x216个预测结果。

        位置head:256x248x216特征经过conv_reg(256x14)得到14x248x216个预测结果。

        方向head:256x248x216特征经过conv_reg(256x4)得到4x248x216个预测结果。

6 顶层结构

        ImVoxelNet模型的顶层结构的入口函数如下所示,主要包含了特征提取、Head和损失函数等部分。

def forward_train(self, img, img_metas, gt_bboxes_3d, gt_labels_3d,
                  **kwargs):
    x, valid_preds = self.extract_feat(img, img_metas)
    # For indoor datasets ImVoxelNet uses ImVoxelHead that handles
    # mask of visible voxels.
    if self.coord_type == 'DEPTH':
        x += (valid_preds, )
    losses = self.bbox_head.loss(*x, gt_bboxes_3d, gt_labels_3d, img_metas)
    return losses

7 室内情况

        ImVoxelNet模型在室内场景下采用了SUN RGB-D数据集,模型总体结构保持一致。下面重点介绍与室外场景不一致之处。室内场景下模型的训练命令如下:

python tools/train.py ../configs/imvoxelnet/imvoxelnet_4x2_sunrgbd-3d-10class

        输入图像维度为3x512x672,经过ResNet结构的主干网络后得到4种不同尺度特征,维度分别为256x128x168、512x64x84、1024x32x42、2048x16x21,并在FPN操作之后得到256x128x168维特征。室内场景体素数量设置为40x40x16,共计25000个体素。类似地,根据图像特征和上采样操作,模型得到各个体素特征,维度为256x40x40x16。

        Neck3d网络采用采用ResNet FPN网络结构计算得到3种不同尺度特征,128x40x40x16、128x20x20x8、128x10x10x4。这与室内情况存在两种差异。首先,特征尺度数量增加为3,原因在于室外情形下仅检测一种目标,而室内情形则检测多个目标。多尺度特征意味着多特征图视野,从而可匹配不同尺寸的目标。其次,特征空间保持为三维空间,而室外情形则转为BEV视图空间。这是因为室内我们不仅关注水平面上的目标,也需要将高度方向上的目标进行充分区分。室外条件下,垂直方向上目标出现叠加的情况较少。相比之下,室内条件则较容易出现垂直方向上的目标重叠情况。

        针对室内情况,ImVoxelNet模型的bbox_head结构主要采用了FCOS HEAD结构,并且增加了中心度预测。其结构配置参数如下所示。

x = self.bbox_head(x)ImVoxelHead(
  (center_loss): CrossEntropyLoss(avg_non_ignore=False)
  (bbox_loss): RotatedIoU3DLoss()
  (cls_loss): FocalLoss()
  (conv_center): Conv3d(128, 1, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1), bias=False)
  (conv_reg): Conv3d(128, 7, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1), bias=False)
  (conv_cls): Conv3d(128, 10, kernel_size=(3, 3, 3), stride=(1, 1, 1), padding=(1, 1, 1))
  (scales): ModuleList(
    (0): Scale()
    (1): Scale()
    (2): Scale()
中心度
   def _get_centerness(face_distances):
        """Compute point centerness w.r.t containing box.
        Args:
            face_distances (Tensor): Face distances of shape (B, N, 6),
                (dx_min, dx_max, dy_min, dy_max, dz_min, dz_max).
        Returns:
            Tensor: Centerness of shape (B, N).

        """
        x_dims = face_distances[..., [0, 1]]
        y_dims = face_distances[..., [2, 3]]
        z_dims = face_distances[..., [4, 5]]
        centerness_targets = x_dims.min(dim=-1)[0] / x_dims.max(dim=-1)[0] * \
            y_dims.min(dim=-1)[0] / y_dims.max(dim=-1)[0] * \
            z_dims.min(dim=-1)[0] / z_dims.max(dim=-1)[0]
        return torch.sqrt(centerness_targets)

8 【python三维深度学习】python三维点云从基础到深度学习_python3d点云从基础到深度学习-CSDN博客

【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。  

更多python与C++技巧、三维算法、深度学习算法总结、大模型请关注我的博客,欢迎讨论与交流:https://blog.csdn.net/suiyingy,或”乐乐感知学堂“公众号。Python三维领域专业书籍推荐:《人工智能点云处理及深度学习算法》。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2052929.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记事本/软件商店/xbox打不开(不会丢失数据)(保姆级教程)

软件商店的安装 : 在某些情况下,系统更新可能导致本地账户和微软账户出现问题, 使得更新似乎只影响到了一个账户,而非我当前使用的账户。 这会导致我环境中的某些Windows自带应用,如微软商店、电影与电视、画图、记事…

鸿蒙开发入门day10-组件导航

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,还请三连支持一波哇ヾ(@^∇^@)ノ) 目录 组件导航 (Navigation) 设置页面显示模式 设置标题栏模式 设置菜…

论文降重切勿“本末倒置”!一文教你如何有效降重

【SciencePub学术】本期热点 论文降重 原创性是评价论文质量的重要标准之一。许多读者在撰写论文都担心重复率过高的问题。 本篇文章旨在分享有效降低学术论文重复率的策略,从而促进学术诚信,提高研究工作的创新性和学术价值。通过一系列实用的写作技巧…

高可用集群keepalived 原理+实战

keepalived 1.高可用集群1.1简介1.2原理1.3 集群类型1.4实现高可用1.5VRRP:Virtual Router Redundancy Protocol1.5.1 VRRP 相关术语1.5.2VRRP 相关技术 2.实验2.1keepalived环境部署2.2抢占模式和非抢占模式2.2.1非抢占模式2.2.2抢占延迟模式 preempt_delay 2.3VIP…

MATLAB 手动实现投影密度法分割建筑物立面 (73)

专栏文章往期回顾,包含本文章 MATLAB 手动实现投影密度法分割建筑物立面 (73) 一、算法介绍二、算法实现1.代码2.效果总结一、算法介绍 从原始点云中,自动分割提取建筑物立面点云用于立面绘图,可以减少人为操作流程。这里从0开始,手动实现一种基于投影密度法的建筑物立…

Unity动画模块 之 3D模型导入基础设置Animation页签

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正 基础设置就截图看看辣,只有实际应用中才会使用到,现在死记硬背也不可能记住 1.基础设置 笔记来…

STM32常用C语言知识总结

目录 一、引言 二、C 语言基础 1.数据类型 2.变量与常量 3.控制结构 4.数组与指针 5.字符串 6. extern变量声明 7.内存管理 三、STM32 中的 C 语言特性 1.位操作 2.寄存器操作 一、引言 STM32 作为一款广泛应用的微控制器,其开发离不开 C 语言的支持。C …

编写日志文件

精灵程序 #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <sys/stat.h> #include…

vue3 响应式 API:ref() 和 reactive()

在 Vue 3 中&#xff0c;响应式系统是其核心特性之一&#xff0c;它使得数据的变化能够自动触发视图的更新。 官方文档&#xff1a; 响应式 API&#xff1a;核心 要更好地了解响应式 API&#xff0c;推荐阅读官方指南中的章节&#xff1a; 响应式基础 (with the API preference…

【STM32单片机_(HAL库)】3-2-1【中断EXTI】【电动车报警器项目】震动点灯

1.硬件 STM32单片机最小系统LED灯模块震动传感器模块 2.软件 exti驱动文件添加GPIO常用函数中断配置流程main.c程序 #include "sys.h" #include "delay.h" #include "led.h" #include "exti.h"int main(void) {HAL_Init(); …

Linux常用命令 ---- rmdir 命令[删除一个空目录]

rmdir 命令 功能&#xff1a;删除一个空目录 我们使用 mkdir 命令创建一个名为 test 空文件夹&#xff0c;如下图所示。 现在使用 rmdir 命令将 test 文件夹进行删除&#xff0c;如下图所示。 注意&#xff1a;rmdir 命令只能删除一个空目录&#xff0c;如果这个目录中有其他文…

【云原生】Kubernetes中的名称空间和资源配额详细用法与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

医疗器械维修其实没有想的那么难

在很多人的印象中&#xff0c;医疗器械维修是一项极其复杂且神秘的工作&#xff0c;似乎只有专业的技术精英才能胜任。然而&#xff0c;事实并非如此&#xff0c;医疗器械维修其实并没有想象中那么难。 首先&#xff0c;现代医疗器械的设计越来越注重人性化和可维护性。制造商…

迎接开学新生活!高三开学必备物品推荐~

步入高三&#xff0c;意味着每一位学子都将面临人生中重要的转折点——高考。为了帮助高三学生们准备充分&#xff0c;让学习生活之路更加顺畅。今天小编综合了实用性、性价比以及学生需求的考量&#xff0c;精选了一系列必备物品&#xff0c;旨在为高三学生创造一个更为舒适、…

ICMP互联网控制报文协议

ICMP 互联网控制报文协议 ICMP &#xff08; Internet Control Message Protocol &#xff0c;也就是互联⽹控制报⽂协议&#xff09;。 ⽹络包在复杂的⽹络传输环境⾥&#xff0c;常常会遇到各种问题。 当遇到问题的时候&#xff0c;总不能死个不明不⽩&#xff0c;没头没脑…

4. kafka消息监控客户端工具

KafkaKing官网地址 : https://github.com/Bronya0/Kafka-King github下载地址 : Releases Bronya0/Kafka-King (github.com) (windows、macos、linux版本) 云盘下载地址 : https://pan.baidu.com/s/1dzxTPYBcNjCTSsLuHc1TZw?pwd276i (仅windows版本) 连接kafka 输入本地地址…

基于Java语言的私家车充电桩系统+私家车充电平台+充电桩系统项目

介绍 SpringBoot 框架&#xff0c;私家车充电桩平台充电桩系统充电平台充电桩云快充协议1.5-1.6协议新能源汽车二充电平台源码Java源码私家车充电系统 源码合作 提供无加密源代码和数据库&#xff0c;支持二次开发 SpringMVC架构完整充电桩系统源代码-充电桩系统-家充公充-新…

大数据报表如何免费设计?本攻略附赠强大报表工具!

在当今信息爆炸的时代&#xff0c;大数据跃升为企业战略决策的核心支撑点。如何有效地从浩瀚的数据海洋中精炼出富含洞察力的信息&#xff0c;并将其转化为直观易懂的报表&#xff0c;是每个数据分析师和决策者都需要面对的挑战。这需要掌握一定的技巧和经验&#xff0c;本文将…

C语言03--控制流

1.二路分支 逻辑&#xff1a;程序中某段代码需要在满足某个条件时才能运行形式&#xff1a; if 语句&#xff1a;表达一种 如果-则 的条件执行关系if-else 语句&#xff1a;表达一种 如果-否则 的互斥分支关系 语法&#xff1a; if ( 判断表达式 ) { // 代码块 } 解…

大学生最佳就业城市排行榜出炉!

最佳就业城市 随着秋招陆续开始&#xff0c;不少高校毕业生迎来了人生转折点。 其中一个需要重点考虑的点&#xff0c;是要前往哪座城市作为就业第一站。 不妨参考一下就业蓝皮书的统计数据&#xff1a; 可以发现&#xff0c;一线城市的就业人数正逐步减少&#xff0c;"新…