【三维目标检测】H3DNet(二)

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

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

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

1 模型总体过程

        H3DNet模型属于anchor-free的三维目标检测算法,并且是在VoteNet模型基础上进行的改进。H3DNet的核心特点在于采用目标表面和棱中心的预测来对目标几何中心和尺寸的直接预测结果进行约束和改进。模型的整体结构如下图所示,采用1个几何中心、6个面中心和12个棱中心共三种图元来预测目标的候选框,并对几何中心候选框进行匹配和refine,使最终检测结果更加准确。这样一方面能够获取更加丰富的特征,另一方面对目标形状提供了更加完整的约束。另一个优势是模型对图元预测噪点的容忍度更高,结果更具鲁棒性。

 2 主要模块解析

        H3DNet的主要网络基础是VoteNet,可以先充分了解VoteNet的模型结构,参考博文:【三维目标检测】VoteNet(一)_Coding的叶子的博客-CSDN博客_votenet。用于H3DNet的代码结构更加复杂,本节主要介绍主干网络与几何中心图元预测候选框(Init. BB)的部分。面中心和棱中心图元预测请参考下一节。

        2.1 主干网络

        H3DNet采用了四个相同结构子主干网络来提取特征,并且提取的特征进行拼接融合。每个子主干网络结构与VoteNet主干网络结构完全一致。主干网络最终主要得到1024个种子点seed_points(1024x3)及其特征seed_features(1024x256)。

         主干网络入口函数为self.backbone(points),关键部分介绍如下。

Net0~3 PointNet2SASSG
points -> xyz_0 40000x3,features_0 40000x1,indices_0 40000
SA1:num=2048,radius:0~0.2,g_sample_num=64,Conv2d(4, 64)、Conv2d(64, 64)、Conv2d(64, 128) -> xyz_1 2048x3,features_1 2048x128,indices_1 2048
SA2:num=1024,radius:0~0.4,g_sample_num=32,Conv2d(131, 128)、Conv2d(128, 128)、Conv2d(128, 256) -> xyz_2 1024x3,features_2 1024x256,indices_2 1024
SA3:num=512,radius:0~0.8,g_sample_num=16,Conv2d(259, 128)、Conv2d(128, 128)、Conv2d(128, 256) -> xyz_3 512x3,features_3 512x256,indices_3 512
SA4:num=256,radius:0~1.2,g_sample_num=16,Conv2d(259, 128)、Conv2d(128, 128)、Conv2d(128, 256) -> xyz_4 256x3,features_4 256x256,indices_4 256
FP1:fp_xyz_1 512x3,fp_features_1 512x256,fp_indices_1 512
FP2:fp_xyz_2 1024x3,fp_features_2 1024x256,fp_indices_2 1024
输出
(1)sa_xyz:[xyz_0, xyz_1, xyz_2, xyz_3, xyz_4],[40000x3, 2048x3, 1024x3, 512x3, 256x3]
(2)sa_features:[features_0, features_1, features_2, features_3, features_4],[40000x1, 2048x128, 1024x256, 512x256, 256x256]
(3)sa_indices:[indices_0, indices_1, indices_2, indices_3, indices_4],[40000, 2048, 1024, 512, 256]
(4)fp_xyz:[xyz_4, fp_xyz_1, fp_xyz_2],[256x3, 512x3, 1024x3]
(5)fp_features:[features_4, fp_features_1, fp_features_2],[256x256, 512x256, 1024x256]
(6)fp_indices:[indices_4, fp_indices_1, fp_indices_2],[256, 512, 1024]
4个PointNet2SASSG
fp_features[-1]x4 -> 1024x1024 hd_feature
hd_feature = self.aggregation_layers(hd_feature)
Conv1d(1024, 512)、Conv1d(512, 256) 1024x256 hd_feature
feats_dict['fp_xyz'] = [feats_dict['fp_xyz_net0'][-1]] 1024x3
feats_dict['fp_features'] = [feats_dict['hd_feature']] 1024x256
feats_dict['fp_indices'] = [feats_dict['fp_indices_net0'][-1]] 1024

        2.2 RPN Head

        rpn_outs = self.rpn_head(feats_dict, self.train_cfg.rpn.sample_mod)

        H3DNet的RPN Head与VoteNet一致,主要包括投票点生成、聚合、候选框预测和解码4个步骤。

           (1)投票点生成

        H3DNet主干网络中得到了具有投票资格的1024个点seed_points(1024x3)及其特征seed_features(1024x256)。每个种子点通过卷积网络会产生一个投票点vote_points(1024x3)及其特征vote_features(1024x256)。这里目标中心用几何中心来表示,而后续图元投票过程中分别采用的是面和棱中心。关键程序部分如下。

results[‘vote_points’], results[‘vote_features’], results[‘vote_offset’] = self.vote_module(seed_points, seed_features)
seed_features 1024x256 Conv1d(256, 256)、Conv1d(256, 256)、Conv1d(256, 259)
votes 1024x259
offset = votes[:, :, :, 0:3]#投票点相对于种子点的偏移
vote_points = seed_points + offset
vote_feats_features = seed_features + votes[:, :, :, 3:] 1024x256

        (2)投票点聚合

        投标点聚合的方式仍然是采用PointNet中的SA模块,将1024个投票点聚合成256个点。这说明1024个种子点一共预测了256个目标,这些目标的中心坐标为aggregated_points(256x3),其特征为aggregated_features(256x128)。这256个点即为候选点。关键程序部分如下。

aggregated_points, aggregated_features, aggregated_indices = self.vote_aggregation(vote_points, vote_features)
SA:num=256,radius:0~0.3,g_sample_num=16,Conv2d(259, 128)、Conv2d(128, 128)、Conv2d(128, 128 ->  aggregated_points 256x3,aggregated_features 256x128,aggregated_indices 256

        (3)候选框预测

        每个聚合后的点会投票产生一个候选结果,进一步得到候选框(proposal)信息。根据聚合后的特征,H3DNet通过分类head和回归head产生预测的候选框结果。aggregated_features(256x128)通过shared_convs卷积 Conv1d(128, 128)和Conv1d(128, 128)进行更深层特征提取,提取后的特征分别经过卷积Conv1d(128, 20)和 Conv1d(128, 123) 得到分类预测结果cls_precls_predictions(256x20)和位置回归预测结果reg_predictions(256x123)。

        关键程序部分如下。

cls_predictions, reg_predictions = self.conv_pred(aggregated_features)
aggregated_features 256x128 Conv1d(128, 128)、Conv1d(128, 128) 256x128特征
分类head:conv_cls Conv1d(128, 20) 256x20 cls_prediction
回归head:conv_reg Conv1d(128, 123) 256x123 reg_predictions
BaseConvBboxHead(
  (shared_convs): Sequential(
    (layer0): ConvModule(
      (conv): Conv1d(128, 128, kernel_size=(1,), stride=(1,))
      (bn): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (activate): ReLU(inplace=True)
    )
    (layer1): ConvModule(
      (conv): Conv1d(128, 128, kernel_size=(1,), stride=(1,))
      (bn): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (activate): ReLU(inplace=True)
    )
  )
  (conv_cls): Conv1d(128, 20, kernel_size=(1,), stride=(1,))
  (conv_reg): Conv1d(128, 123, kernel_size=(1,), stride=(1,))
)

        (4)预测解码

        上一步我们得到了模型预测结果,那么预测结果如何与真实标签关联需要一一进行解码。真实标签主要包含目标有无、类别标签和目标回归位置。

        解码结果的关键程序如下。

(1)目标中心位置
results['center'] = aggregated_points + reg_predictions[..., :3] 256x3
(2)目标方向类别
results['dir_class'] = reg_predictions..., 3:27] 256x24
(3)目标方向偏移
results['dir_res_norm'] = reg_predictions[..., 27:51] 256x24
results['dir_res'] = results['dir_res_norm'] * (np.pi / 12)
(4)目标尺寸类别
results['size_class'] = reg_predictions[..., 51:69] 256x18
(5)目标尺寸偏移
results['size_res_norm'] = reg_predictions[..., 69:123] 256x18x3
results['size_res'] = size_res_norm * mean_sizes 256x18x3
(6)目标有无得分,候选点时否成功预测了目标
results['obj_scores'] = cls_preds_trans[..., 0:2] 256x2
(7)目标语义得分(预测的目标所属类别)
results['obj_scores'] = cls_preds_trans[..., 2:20] 256x18

        2.3 RPN损失函数

        2.3.1 标签计算

        各个标签如下所示。

#表明哪些点落在目标框内
vote_target_masks = points.new_zeros([num_points], dtype=torch.long)
box_indices_all = gt_bboxes_3d.points_in_boxes_all(points) 20000xM
votes点云中的点相对于目标几何中心的偏移
vote_targets 每个点投给相应目标的中心偏移。
vote_target_mask表示每个点是否参与了投票。1表示参与了投票,0表示未参与投票。
valid_gt_weights 有效真实标签除以标签数量得到,真实标签权重
center_targets 物体几何中心,即重心。Kx3,K为batch中单个样本含目标最多的数量,不足时补0,0,0,并用valid_gt_masks进行标识。
size_class_targets 尺寸类别与物体类别保持一致,默认不同物体有不同的尺寸,即平均尺寸
size_res_targets 物体尺寸与平均尺寸的差值除以平均尺寸。
dir_class_targets 目标角度从0~2Π范围划分为12个子区间,每个区间作为一个类别
dir_res_targets  角度相对子区间中心的偏移值,并除以区间大小进行归一化
objectness_targets聚合后的点aggregated_points距离最近目标中心点如果小于0.3则为1,即正样本标签,否则为0。正样本标签除以正样本数量得到box损失权重box_loss_weights,即仅对正样本进行box预测。
objectness_masks 聚合后的点aggregated_points距离最近目标中心点如果小于0.3或大于0.6则为1,否则为0。这表示将不考虑处于中间状态的目标,即困难样本。正负样本标签除以正负样本数量得到权重objectness_weights。
mask_targets 每个聚合点距离最近目标的分类标签。
assigned_center_targets 每个聚合点距离最近目标的分类中心。

        2.3.2 损失计算

        H3DNet总体损失计算关键程序及类型如下所示。

(1)投票损失vote_loss:ChamferDistance,计算投票中心与目标中心标签的最小倒角距离。
vote_loss = self.vote_module.get_loss(bbox_preds['seed_points'], bbox_preds['vote_points'], bbox_preds['seed_indices'], vote_target_masks, vote_targets)
#根据vote_target_mask(40000)和bbox_preds['seed_indices'](1024)得到投票成功的种子点,seed_gt_votes_mask(1024)
#根据vote_targets和bbox_preds['seed_indices']得到投票成功的种子点的目标中心偏移seed_gt_votes(1024x9)加上bbox_preds['seed_points']得到种子点对应投票的目标中心坐标标签。
# seed_gt_votes_mask除以投票成功的种子点总数得到权重weights。
#计算vote_points和seed_gt_votes之间的倒角距离。
(2)目标有无损失objectness_loss:CrossEntropyLoss
objectness_loss = self.objectness_loss(bbox_preds['obj_scores'].transpose(2, 1), objectness_targets, weight=objectness_weights)
(3)中心损失center_loss:ChamferDistance
source2target_loss, target2source_loss = self.center_loss(bbox_preds['center'], center_targets, src_weight=box_loss_weights, dst_weight=valid_gt_weights)
center_loss = source2target_loss + target2source_loss
(4)方向分类损失dir_class_loss:CrossEntropyLoss
dir_class_loss = self.dir_class_loss(bbox_preds['dir_class'].transpose(2, 1), dir_class_targets, weight=box_loss_weights)
(5)方向回归损失dir_res_loss:SmoothL1Loss
dir_res_loss = self.dir_res_loss(dir_res_norm, dir_res_targets, weight=box_loss_weights)
(6)尺寸分类损失size_class_loss:CrossEntropyLoss
size_class_loss = self.size_class_loss(bbox_preds['size_class'].transpose(2, 1), size_class_targets, weight=box_loss_weights)
(7)尺寸回归损失size_res_loss:SmoothL1Loss
size_res_loss = self.size_res_loss(size_residual_norm, size_res_targets, weight=box_loss_weights_expand)
(8)语义分类损失semantic_loss:CrossEntropyLoss
semantic_loss = self.semantic_loss(bbox_preds['sem_scores'], mask_targets, weight=box_loss_weights)

        2.4 图元预测、Refined BB和图元匹配

        由于总体内容较多,这部分放在下一节。预计明天更新。

【python三维深度学习】python三维点云从基础到深度学习_Coding的叶子的博客-CSDN博客_python 数学形态 点云

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

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

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coding的叶子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值