Second模型的基本介绍、稀疏卷积、mini kitti数据集等请参考本专栏的上一篇博文:【三维目标检测】Second 模型 (一)_Coding的叶子的博客-CSDN博客。本节将介绍模型的详细结构与推理过程。文中参考代码来源于mmdetection3d框架中的second模型。mmdetection3d安装和调试验证可参考本博客之前的专栏,里面有详细介绍。

1 second模型总体过程

2 主要模块解析

2.1 体素化

函数:self.voxelize(points)

Voxelization(voxel_size=[0.05, 0.05, 0.1], point_cloud_range=[0, -40, -3, 70.4, 40, 1], max_num_points=5, max_voxels=(16000, 40000), deterministic=True)

输入:

(1)points,Nx4,原始点云,N表示点云数量,4表示特征维度,特征为坐标x、y、z与反射强度r。

(2)voxel_size:单位体素的尺寸,x、y、z方向上的尺度分别为0.05m、0.05m、0.1m。

(3)point_cloud_range:x、y、z方向的距离范围,结合(2)中体素尺寸可以得到总的体素数量为1408x1600x40。

(4)max_num_points:定义每个体素中取值点的最大数量,默认为5,在voxelnet中T=35。

(5)max_voxels:表示含有点云的体素最大数量,默认为16000。可以看到,(3)中体素的数量远大于16000,但是并不是每个体素中都有点云。这也就是说输入的体素是稀疏的,因而会用到上一节中提到的稀疏卷积。

(6)deterministic:取值为True时,表示每次体素化的结果是确定的,而不是随机的。

 输出:
        (1)voxels:16000x5x4,体素中各个点的原始坐标和反射强度,16000个体素,每个体素最多5个点。
        (2)num_points:16000x1,每个体素中点的数量,最小数量为1,最大数量为5。
        (3)coors:体素自身坐标,16000x4,[batch_id, x, y, z]

2.2 体素特征提取VFE(voxel_encoder)

在voxelnet中,体素特征通过SVFE层提取,即连续两层VFE,其中VFE层提取体素特征用的是PointNet网络。而在该Second源码中,VFE层被进行了简化HardSimpleVFE(voxel_encoder),即对每个体素中的点求平均值,用平均值作为体素特征,取平均时点的数量由num_points决定。
16000x5x4的voxels经过VFE后的维度为16000x4,即在第二个维度点的数量上进行了平均。

2.3 稀疏卷积特征提取 middle_encoder

类比VoxelNet中的CML(Convolutional Middle Layer)层,voxelnet中直接用三维卷积进行特征提取,而second采用了连续6个稀疏卷积进行特征提取,特征维度从16000x4变为7561x128,并进一步转化为out 256x200x176。

三维稀疏卷积:16000x4  -> 16000x16
三维稀疏卷积:16000x16 -> 16000x16,f1
三维稀疏卷积:16000x16 -> 26527x32,f2
三维稀疏卷积:26527x32 -> 18184x64,f3
三维稀疏卷积:18184x64 -> 8731x64,f4
三维稀疏卷积:8731x64  -> 7561x128,out
将稀疏特征放回体素:7561x128 -> 128x2x200x176,out
前两维进行合并:128x2x200x176 -> 256x200x176,out

2.4 主干网络特征提取

backbone:SECOND
        1、2.3中out 256x200x176经连续6个3x3卷积:128x200x176,out1
        2、2.3中out 256x200x176经连续6个3x3卷积(其中一个步长为2):256x100x88,out2

Backbone
Out1:256x200x176 -> 128x200x176
Sequential((0): Conv2d(256, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(5): ReLU(inplace=True)(6): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(7): BatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(8): ReLU(inplace=True)(9): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(10): BatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(11): ReLU(inplace=True)(12): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(13): BatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(14): ReLU(inplace=True)(15): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(16): BatchNorm2d(128, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(17): ReLU(inplace=True)
)Out2:128x200x176 -> 256x100x88
Sequential((0): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)(1): BatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(5): ReLU(inplace=True)(6): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(7): BatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(8): ReLU(inplace=True)(9): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(10): BatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(11): ReLU(inplace=True)(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(13): BatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(14): ReLU(inplace=True)(15): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(16): BatchNorm2d(256, eps=0.001, momentum=0.01, affine=True, track_running_stats=True)(17): ReLU(inplace=True)
)
Out = [out1, out2] [128x200x176, 256x100x88]

2.5 上采样拼接 self.neck

分别对out1、out2进行上采样:
        out1:128x200x176 -> 256x200x176
        out2:256x100x88 -> 256x200x176
        拼接out:256x200x176、256x200x176 -> 512x200x176 (self.extract_feat

2.6 检测头 self.bbox_head

分类head:512x200x176特征经过conv_cls(512x2)得到2x200x176个预测结果。
        位置head:512x200x176特征经过conv_reg(512x14)得到14x200x176个预测结果。
        方向head:512x200x176特征经过conv_reg(512x4)得到4x200x176个预测结果。

与VoxelNet不同之处在于,Second增加了对方向的预测,更有利于模型的训练,特别是更加适用于方向预测相反的情况。如果仅采用位置head,那么在方向正好相反时,前6个参数的损失会非常小,而最后一个角度参数的损失会非常大。而损失函数是进行整体判别的,并不能区分这6个参数哪一个带来了损失函数的巨大变化,因而在反向传播时会对7个参数都进行调整。

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

2.7 损失函数

分类损失:FocalLoss。
        三维目标框回归损失:SmoothL1Loss。
        方向损失:CrossEntropyLoss。

2.8 顶层结构

顶层结构主要包含以下三部分:

(1)特征提取:self.extract_feat,得到512x200x176特征,见2.5节。

(2)检测头:见2.6节。

(3)损失函数:见2.7节。

def forward_train(self, points, img_metas, gt_bboxes_3d, gt_labels_3d, gt_bboxes_ignore=None):x = self.extract_feat(points, img_metas)outs = self.bbox_head(x)loss_inputs = outs + (gt_bboxes_3d, gt_labels_3d, img_metas)losses = self.bbox_head.loss(*loss_inputs, gt_bboxes_ignore=gt_bboxes_ignore)return losses#extract_feat模块
def extract_feat(self, points, img_metas=None):"""Extract features from points."""voxels, num_points, coors = self.voxelize(points)voxel_features = self.voxel_encoder(voxels, num_points, coors)batch_size = coors[-1, 0].item() + 1x = self.middle_encoder(voxel_features, coors, batch_size)x = self.backbone(x)if self.with_neck:x = self.neck(x)return x

3 训练命令

 python tools/train.py  configs/second/hv_second_secfpn_6x8_80e_kitti-3d-car.py

4 运行结果

5 【python三维深度学习】python三维点云从基础到深度学习_Coding的叶子的博客-CSDN博客_三维点云深度学习

更多三维、二维感知算法和金融量化分析算法请关注“乐乐感知学堂”微信公众号,并将持续进行更新。

【三维目标检测】Second 模型 (二)相关推荐

  1. 三维目标检测:(二)用ROS获取传感器(Kinect DK)点云并滤波

    前期工作 [ 1] 需要配置Clion https://blog.csdn.net/weixin_38593194/article/details/85122716 [ 2] 创建ros工作空间和功能 ...

  2. 【三维目标检测】CenterPoint(一)

    CenterPoint是一种anchor free的三维目标检测算法模型,发表在CVPR 2021,论文名称为<Center-based 3D Object Detection and Trac ...

  3. Complexer-YOLO:基于语义点云的实时三维目标检测与跟踪

    泡泡点云时空,带你精读点云领域顶级会议文章 标题:Complexer-YOLO: Real-Time 3D Object Detection and Tracking on Semantic Poin ...

  4. 【三维目标检测】SSN(一)

    本文为博主原创文章,未经博主允许不得转载. 本文为专栏<python三维点云从基础到深度学习>系列文章,地址为"https://blog.csdn.net/suiyingy/ar ...

  5. 【三维目标检测】Complex-Yolov4详解(二):模型结构

    Complex-Yolo网络模型的核心思想是用鸟瞰图BEV替换Yolo网络输入的RGB图像.因此,在完成BEV处理之后,模型的训练和推理过程基本和Yolo完全一致.Yolov4中输入的RGB图片的尺寸 ...

  6. 【三维目标检测】3DSSD(二)

    数据和源码请参考上一篇博文:[三维目标检测]3DSSD(一)_Coding的叶子的博客-CSDN博客. 3DSSD三维目标检测模型发表在CVPR2020<3DSSD: Point-based 3 ...

  7. 【三维目标检测】Second 模型 (一)

    Second算法是一种基于三维点云的目标检测算法.Second算法采用了几乎与Voxelnet三维目标检测算法完全一致的设计思路,主要差异表现在将Voxelnet CML(Convolutional ...

  8. 【三维目标检测】FCAF3D(二)

    FCAF3D数据和源码配置调试过程请参考上一篇博文:[三维目标检测]FCAF3D(一)_Coding的叶子的博客-CSDN博客.本文主要详细介绍FCAF3D网络结构及其运行中间状态. 1 模型总体过程 ...

  9. 【三维目标检测】Part-A2(二)

    本文为博主原创文章,未经博主允许不得转载. 本文为专栏<python三维点云从基础到深度学习>系列文章,地址为"https://blog.csdn.net/suiyingy/ar ...

最新文章

  1. 2022-2028年中国碲化镉薄膜太阳能电池行业发展现状分析及投资前景趋势报告
  2. ansible模块---续
  3. 计算机专业新老生交流会ppt,铜陵学院实践部新老生交流会.ppt
  4. 在64位windows下使用instsrv.exe和srvany.exe创建windows服务
  5. 网易10万+课程迅速刷屏又迅速被封:“违规”背后的思考
  6. php flush nginx,Nginx+phpfastcgi下flush输出问题
  7. error:java:无效的源发行版_IDEA java出现无效的源发行版14解决方案_java
  8. [Node.js] 使用nodejs操作mysql数据库
  9. lua io.read()
  10. 如何在mysql查询结果集中得到记录行号_如何在MySQL查询结果集中得到记录行号...
  11. iOS App常用的宏
  12. 平面设计师学习指南,平面设计都要学什么
  13. SpringBoot验证码
  14. 如何下载自己喜欢的网站
  15. Python学习之路(2)
  16. javascript:html嵌入javascript代码的三种方式
  17. iOS 开发修改app名称(display Name)后实际app名称没有变的情况
  18. HBuilder(uniapp) 配置android模拟器
  19. css-filter属性-融合效果-1.1
  20. golang路由mux的介绍及基本使用

热门文章

  1. 业界新闻: JAVA 7新特性让JVM“瘦身”成功!
  2. 众安在线2018半年报:亏损6.668亿元,综合成本率高达124.0%
  3. 小宝贝流鼻血,治疗方法
  4. tea系列加密算法学习笔记
  5. 这位年轻人,把CryptoPunks送给了无聊猿公司?B轮4个亿?
  6. Android百度地图地理围栏定位间隔
  7. 从底层结构开始学习FPGA(1)----可配置逻辑块CLB(Configurable Logic Block)
  8. 华为ENSP之MPLS V HubSpoke架构
  9. jquery Callbacks 回调对象的读书笔记-源码分析
  10. Base64与图片之间互相转换