【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。
参考书籍:《人工智能点云处理及深度学习算法》
H3DNet数据和源码配置调试过程以及主干网络介绍请参考上一篇博文:【三维目标检测】H3DNet(一)-CSDN博客和【三维目标检测】H3DNet(二)-CSDN博客。本节主要详细介绍H3DNet的图元预测、Refined候选框和图元匹配过程。
1 图元预测损失
H3DNet模型除预测目标几何中心之外,还预测目标的上下表面、侧面、棱等图元中心。这些图元中心的预测均是一个VoteNet RPN过程。输入种子点和特征仍与主干网络一致。每种图元分别进行预测,各自主要损失包括目标损失、投票损失、尺寸损失、语义分类和语义分类等5种损失,总损失共计15项。
1.1 图元预测
采用VoteNet方法根据主干网络的种子点及其特征分别产生三种图元的投票点及特征、候选点及特征、投票目标概率(投票点是否在图元范围内)、中心坐标、尺寸偏差和语义分类结果。该过程与主干网络RPN产生的过程基本一致。这三种图元分别是2个上下表面、4个侧面和12条棱。
以上下表面图元为例,其过程如下,其中预测特征维度为1024x23,包括3个维度中心坐标偏差、2个维度尺寸偏差和18个维度语义类别。侧面和棱图元则在尺寸偏差这个维度上稍微有所变化。
关键程序如下,基本与VoteNet一致。
Conv1d(256, 128) 1024x128
primitive_flag = self.flag_conv(seed_features)
Conv1d(128, 2) 1024x2
primitive_flag = self.flag_pred(primitive_flag)
# 1. generate vote_points from seed_points
vote_points, vote_features, _ = self.vote_module(seed_points, seed_features)
results['vote_' + self.primitive_mode] = vote_points 1024x3
results['vote_features_' + self.primitive_mode] = vote_features 1024x256
# 2. aggregate vote_points
aggregated_points, features 1024x3 1024x128
# 3. predict primitive offsets and semantic information
Conv1d(128, 128)、Conv1d(128, 128)、Conv1d(128, 23)
predictions = self.conv_pred(features) 1024x23
# 4. decode predictions
decode_ret = self.primitive_decode_scores(predictions, aggregated_points)
center[:, 0:3] 1024x3
size_residuals[:, 3:5] 1024x2
sem_cls_scores[:, 5:23] 1024x18
#选择softmax得分大于0.5的面中心pred_ind 1024
#得分不大于0.5的中心加上一个较大偏移值,让其结果远离真实值 center 1024x3
center, pred_ind = self.get_primitive_center(primitive_flag, decode_ret['center_' + self.primitive_mode])
1.2 图元标签
将距目标图元附近0.2范围内的点定义为真实投票点,目标图元分别包括2个上下表面、4分侧面和12条棱。例如,上下底面附近厚度为0.2的点属于真实投票点。分别计算出各个图元下的point_mask、point_sem和point_offset。
point_mask:真实投票点mask,1表示属于厚度为0.2点云范围内。
point_sem:真实投票点中心坐标(x、y、z)、尺寸(w、l)和类别标签cls_id
point_offset:中心坐标相对于真实投票点的偏差。
1.3 损失计算
损失计算过程与VoteNet的RPN损失一致。本质上,这部分相对于采用VoteNet分别预测目标的类别、面中心、棱中心和尺寸。损失主要包括投票目标损失pred_flag(CrossEntropyLoss)、投票损失vote_loss(ChamferDistance)、中心损失center_loss(ChamferDistance)、尺寸损失size_loss(ChamferDistance)和语义分类损失(CrossEntropyLoss)。3种图元分别计算这5种损失,共计15项损失。
2 Refined RPN
采用图元中心特征来对主干网络提取的候选点特征进行改善。面和棱图元经过再次聚合后共预测了4608个候选点,每个点特征维度为32。聚合后的候选点对应256个候选框,每个候选框特征由18个图元特征组成,维度为256x576。将候选框576维特征通过卷积转换成128维后与主干网络的候选点特征进行加法融合得到256x128维度的融合特征。
改进后RPN Loss的计算过程与主干网络RPN损失计算完全一致,仅仅是将预测结果替换成改进后的候选框。损失包括objectness_loss_optimized、semantic_loss_optimized、center_loss_optimized_optimized、dir_class_loss_optimized、dir_res_loss_optimized、size_class_loss_optimized、size_res_loss_optimized,共计7项损失。
3 图元匹配
图元预测会对主干网络中匹配的候选框进行微调,相当于对主干网络种预测正确的点进行改善。这也要求图元预测也是正确的。整体目标是让两种方法匹配的预测结果达成一致。
3.1 目标标签
同样地,每个候选点的类别、预测面中心、预测棱中心与最近邻的目标一致。obj_surface_center为面中心预测标签,维度为1536x3。obj_line_center为棱中心预测标签,维度为3072x3。从2048个预测面中心中选择与1536个距离面中心标签最近的点作为有效预测点。从1024个预测棱中心中选择与3072个距离棱中心标签最近的点作为有效预测点,同一个点可重复选择。这样做的目的是将预测中心与标签中心进行对应。
输出标签如下:
- cues_objectness_label:位置匹配的正样本图元,预测的图元中心与目标中心和proposal中心距离均在阈值0.3之内,含面和棱(4608),objectness_label_surface和objectness_label_line的叠加。
- cues_sem_label:位置匹配且目标类别预测正确的正样本图元mask,4608。
- proposal_objectness_label:候选点(聚合点)距目标中心距离小于0.3的为正样本点,256,正样本标签。
- cues_mask:候选点正样本对应的图元mask,4608。
- cues_match_mask:位置匹配的cues_objectness_label分配到256个proposal,proposal中只要存在一个位置匹配的图元预测结果,则标签为1。
- cues_matching_label,#正样本图元且与候选点正样本标签一一对应的mask,即候选点和图元同时预测正确,并且二者偏差较小,这样样本之间是匹配的,4608。
- obj_surface_line_center:候选点对应目标的真实面中心和棱中心,4608x3。
3.2 损失计算
图元预测的主要作用之一是对主干网络预测的候选框进行改进微调,特别是对正样本原始候选框的优化。匹配图元的损失主要包括图元目标损失(CrossEntropyLoss)、图元语义损失(CrossEntropyLoss)、图元匹配损失(CrossEntropyLoss)、图元语义匹配损失(CrossEntropyLoss)和图元中心损失(MSELoss),共计5项。
#由于weight为候选点正样本mask,计算的是候选点正样本对应的位置匹配损失,相当于候选点预测和图元远测同时正确。
primitive_objectness_loss = self.cues_objectness_loss(objectness_scores.transpose(2, 1), cues_objectness_label, weight=cues_mask, avg_factor=cues_mask.sum() + 1e-6)
#图元语义损失,匹配图元预测的类别标签需正确。
primitive_sem_loss = self.cues_semantic_loss(objectness_scores_sem.transpose(2, 1), cues_sem_label, weight=cues_mask, avg_factor=cues_mask.sum() + 1e-6)
#图元匹配损失,是改进后选框的目标损失,重点关注含有匹配图元的候选框。
objectness_scores = bbox_preds['obj_scores_optimized']
objectness_loss_refine = self.proposal_objectness_loss(objectness_scores.transpose(2, 1), proposal_objectness_label) #CrossEntropyLoss
primitive_matching_loss = (objectness_loss_refine * cues_match_mask).sum() / (cues_match_mask.sum() + 1e-6) * 0.5
#图元语义匹配损失,对正负样本原始候选框采用改进后特征预测结果进行调整。
primitive_sem_matching_loss = (objectness_loss_refine * proposal_objectness_mask).sum() / (proposal_objectness_mask.sum() + 1e-6) * 0.5
#图元中心损失(MSELoss),即匹配的图元预测中心与真实标签之间的直接偏差。
square_dist = self.primitive_center_loss(pred_surface_line_center, obj_surface_line_center)
match_dist = torch.sqrt(square_dist.sum(dim=-1) + 1e-6)
primitive_centroid_reg_loss = torch.sum(match_dist * cues_matching_label) / (cues_matching_label.sum() + 1e-6)
4 总体损失
H3DNet总体损失包含主干网络的RPN损失、图元RPN损失、改进的RPN损失和匹配图元改进损失,损失数量分别为8、15、7、5,共计30项。
5 顶层结构
顶层结构主要包含以下四部分:
主干网络特征提取:self.extract_feat,通过4个PointNet2SASSG主干网络进行特征提取,输出结果,见上一博文。
RPN Head:主干网络结果预测与解码,见上一博文。
Roi Head:Roi部分包括图元预测、候选框改进和图元匹配部分,见1~3节。
损失函数:共35项损失函数,见4节。
def forward_train(self, points, img_metas, gt_bboxes_3d, gt_labels_3d, pts_semantic_mask=None, pts_instance_mask=None, gt_bboxes_ignore=None):
points_cat = torch.stack(points)
feats_dict = self.extract_feat(points_cat)
feats_dict['fp_xyz'] = [feats_dict['fp_xyz_net0'][-1]]
feats_dict['fp_features'] = [feats_dict['hd_feature']]
feats_dict['fp_indices'] = [feats_dict['fp_indices_net0'][-1]]
losses = dict()
if self.with_rpn:
rpn_outs = self.rpn_head(feats_dict, self.train_cfg.rpn.sample_mod)
feats_dict.update(rpn_outs)
rpn_loss_inputs = (points, gt_bboxes_3d, gt_labels_3d, pts_semantic_mask, pts_instance_mask, img_metas)
rpn_losses = self.rpn_head.loss(rpn_outs, *rpn_loss_inputs, gt_bboxes_ignore=gt_bboxes_ignore, ret_target=True)
feats_dict['targets'] = rpn_losses.pop('targets')
losses.update(rpn_losses)
# Generate rpn proposals
proposal_cfg = self.train_cfg.get('rpn_proposal', self.test_cfg.rpn)
proposal_inputs = (points, rpn_outs, img_metas)
proposal_list = self.rpn_head.get_bboxes(*proposal_inputs, use_nms=proposal_cfg.use_nms)#候选框
feats_dict['proposal_list'] = proposal_list
else:
raise NotImplementedError
roi_losses = self.roi_head.forward_train(feats_dict, img_metas, points, gt_bboxes_3d, gt_labels_3d, pts_semantic_mask, pts_instance_mask, gt_bboxes_ignore)
losses.update(roi_losses)
return losses
6 训练命令
python tools/train.py configs/h3dnet/h3dnet_3x8_scannet-3d-18class.py
7 运行结果
8 【python三维深度学习】python三维点云从基础到深度学习_Coding的叶子的博客-CSDN博客_python 数学形态 点云
【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。
更多python与C++技巧、三维算法、深度学习算法总结、大模型请关注我的博客,欢迎讨论与交流:https://blog.csdn.net/suiyingy,或”乐乐感知学堂“公众号。Python三维领域专业书籍推荐:《人工智能点云处理及深度学习算法》。