【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。
参考书籍:《人工智能点云处理及深度学习算法》
Group-Free-3D是由微软亚洲研究院于2021年提出的三维目标检测模型,发表在ICCV2021《Group-Free 3D Object Detection via Transformers》,论文地址为“https://arxiv.org/abs/2104.00678”。Group-Free-3D核心之处在于采用transformer结构实现了自适应分组,将候选点与种子点进行了长程关联,并采用级联transformer方法实现特征深度融合,最终促使模型检测精度得以提升。论文发表时主要针对三维室内数据集 ScanNetv2和SUN RGB-D数据集进行了测试,并在当时取得了最佳效果。目前,Group-Free-3D在paperwithcode网站上的排名仍然处于前十的位置,如下图所示,图片来源于“https://paperswithcode.com/sota/3d-object-detection-on-scannetv2”。
之前介绍的候选点(proposal)生成方法大多采用类似PointNet ++采样分组的方法来实现,属于人工设置候选点生成的规则。人工设置方法有可能导致真实场景中的目标被分配给了错误的候选点,从而降低了三维目标的检测性能。如下图所示,以VoteNet为例,在蓝色球形内的点大部分属于被错误分配的点。
1 示例程序与数据
Group-Free-3D官方程序地址为“https://github.com/zeliu98/Group-Free-3D”,而本节主要基于mmdetection3d框架中的实现程序进行介绍。输入数据集采用Scannet v2,输入数据维度为50000x3,共18个类别。模型中transformer级联数量设置为6。因而,Group-Free-3D的训练程序运行命令如下:
python train.py configs/groupfree3d/groupfree3d_8x4_scannet-3d-18class-L6-O256.py
2 模型结构
2.1 主干网络
Group-Free-3D的主干网络采用PointNet ++的PointNet2SASSG网络结构,用于提取点云高维特征。主干网络关键输出为经过特征上采样后得到的点云及其特征。输出点云数量为1024,特征维度为Mx(3+C)维特征。输出的点称为种子点,数量M为1024。种子点PointNet特征维度C为256,与坐标拼接后得到1024x288维特征。
Group-Free-3D主干网络主要输出结果如下,入口程序为x = self.extract_feat(points_cat)。
#PointNet2SASSG完整输出
(1)sa_xyz:[xyz_0, xyz_1, xyz_2, xyz_3, xyz_4],[50000x3, 2048x3, 1024x3, 512x3, 256x3]
(2)sa_features:[features_0, features_1, features_2, features_3, features_4],[None, 2048x128, 1024x256, 512x256, 256x256]
(3)sa_indices:[indices_0, indices_1, indices_2, indices_3, indices_4],[50000, 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, 1024x288]
(6)fp_indices:[indices_4, fp_indices_1, fp_indices_2],[256, 512, 1024]
#产生M=1024个种子点
seed_xyz, seed_features, seed_indices = self._extract_input(feat_dict)
seed_points = feat_dict['fp_xyz'][-1] 1024x3
seed_features = feat_dict['fp_features'][-1] 1024x288
seed_indices = feat_dict['fp_indices'][-1] 1024
2.2 候选框特征生成
Group-Free-3D属于anchor-free三维目标检测方法,直接从点云来生成初始的候选对象(proposal)。文章介绍了三种候选点采样生成方式Farthest Point Sampling (FPS)、 k-Closest Points Sampling (KPS)和KPS with non-maximal suppression (KPS-NMS)。FPS为最远点采样,采样结果依赖于点云的分布,未充分考虑点云中的目标位置。KPS在目标内部选择K个距离目标最近的点作为候选点,候选点质量更高。程序中K的取值为4。KPS-NMS是在KPS的基础之上采用非极大值抑制避免候选点过近或重复采样的问题。程序中默认采用KPS实现方式,其步骤如下:
- 根据种子点及其特征,采用卷积和sigmoid操作预测种子点成为候选点的概率。
- 选择概率最大的256个点作为初始候选点。
- 通过KPS(K=4)的方法对1024个种子点进行标签赋值,满足要求的赋值为1,否则为0。
- 通过损失函数和训练迭代来使初始候选点结果逐步与KPS标签逼近。
Group-Free-3D生成目标候选点维度为Kx(3+C),其中K、C均为256,即维度为256x288。该特征即为候选框特征。关键程序如下:
#初始化目标候选点,可类比VoteNet中聚合点, KPS
points_obj_cls_logits = self.points_obj_cls(seed_features) #Conv1d(288, 288)、Conv1d(288, 1)
#种子点属于目标的概率得分
points_obj_cls_scores = points_obj_cls_logits.sigmoid().squeeze(1) 1024
#选出概率最高的前256个种子点
sample_inds = torch.topk(points_obj_cls_scores, self.num_proposal)[1].int() 256
results['seeds_obj_cls_logits'] = points_obj_cls_logits #1024个种子点类别特征
#采样,选出分类概率较高点的点作为候选点256x3,特征256x288
candidate_xyz, candidate_features, sample_inds = self.gsample_module(seed_xyz, seed_features, sample_inds)
2.3 Bbox Head
bbox head主要作用是根据候选框特征生成目标类别和位置预测结果。输入数据集共有18个类别,因此模型通过卷积通道设置并根据候选框特征生成19个维度预测结果,其中第1个维度(obj_scores)用于预测候选框是否处于目标之中,后18个维度(sem_scores)表示目标所属类别概率。目标位置预测结果采用bin-based方式,方向和类别均采用分类、回归结合的方式进行预测。目标位置预测包括3个维度目标中心偏差(center)、1个维度方向类别(dir_class)、1个维度方向偏差(dir_res)、18个维度尺寸类别(size_class)和54个维度尺寸偏差(18x3,size_res),共即77个维度。因此模型通过卷积通道设置并根据候选框特征生成77个维度预测结果。
Group-Free-3D的bbox head 入口程序为bbox_preds = self.bbox_head(x, self.train_cfg.sample_mod)。其bbox head包含了7个组成部分。第1个组成部分是根据候选框初步特征直接预测结果,后6个部分则分别采用transformer进行结果预测。这7个部分均分别预测19个分类结果和77个位置结果。
(1)直接预测结果
根据256个候选点及其特征(256x288)并通过卷积和解码操作得到上述19个分类预测结果和77个位置预测结果。关键程序如下:
#输入256x288
#Conv1d(288, 288)、Conv1d(288, 288)
#Conv1d(288, 19、Conv1d(288, 77))
cls_predictions, reg_predictions = self.conv_pred(candidate_features) 256x19,256x77
#预测解码 decode_res
reg_preds_trans[..., 0:3]:目标中心相对于候选点的偏差 3
reg_preds_trans[..., 3:4]:方向类别 1
reg_preds_trans[..., 4:5]:方向偏差 1
reg_preds_trans[..., 5:23]:尺寸类别 18
reg_preds_trans[..., 23:77]:尺寸偏差 18x3
(2)transformer预测结果
Group-Free-3D模型采用了6个级联的transformer结构来进行更深层次的特征提取与融合。。Transformer模块的直接输出一方面作为新的候选框特征,分别再次预测19个分类输出和77个位置输出;另一方面作为下一个transformer的query输出。
Group-Free-3D模型的transformer结构如下图所示。Transformer结构关键中间输入变量包括query(Q)、key(K)、V(value)。K和V可分别理解为特征变量的索引和取值,Q则为待提取特征的目标索引。通过计算Q和K之间的相似性来决定特征取值V对Q的贡献程度,即权重大小。由于Q、K、V来源于同一原始数据,因而Q和(K、V)相当于是同一数据在不同参数空间下表征结果。Transformer的编码层重点考虑了Q和(K、V)之间的关联性,特别是(K,V)对Q的贡献程度。
因此,Group-Free-3D模型的transformer结构则是提取了种子点对候选框的贡献程度。Q为候选框特征,K和V均为种子点特征。候选框自动选择关联性较大的种子点而不需要人工设置。每个transformer输出特征作为新的候选框特征。并且下一层的Q将更新为新的候选框特征。通过这种级联操作,一方面模型可以获取更深维度特征,另一方面起到逐步改进预测结果的作用,最终使得目标检测精度得以提升。
在transformer中,我们通常还会考虑输入目标的位置编码。候选框的位置(x、y、z、w、l、h)可通过77维预测结果得到,并通过卷积编码成256x288的维度。种子点位置(x、y、z)则通过卷积编码成1024 x 288的维度。关键程序如下,需要注意,在诸如transformer和lstm等模型中,输入为数据的维度维NxBxC,N表示特征数量,B表示batch size,C表示通道数量。B在第2个维度,而通常情况下B在第一个维度,即BxCxN。
Q:候选特征 256x288
K:种子点特征 seed_features 1024x288
V:种子点特征 seed_features 1024x288
Q_pos:上一层候选点的预测目标框信息(x、y、z、w、l、h)卷积编码 256 x 288
K_pos:种子点(x、y、z)卷积编码 1024 x 288query = self.decoder_query_proj(candidate_features).permute(2, 0, 1)
key = self.decoder_key_proj(seed_features).permute(2, 0, 1)
value = key
query_pos = self.decoder_self_posembeds[i](base_bbox3d).permute(2, 0, 1) 256x288
key_pos = self.decoder_cross_posembeds[i](seed_xyz).permute(2, 0, 1) 1024x288
query = self.decoder_layers[i](query, key, value, query_pos=query_pos, key_pos=key_pos).permute(1, 2, 0)
results[f'{prefix}query'] = query 288x256
cls_predictions, reg_predictions = self.prediction_heads[i](query) 19x256, 77x256
decode_res = self.bbox_coder.split_pred(cls_predictions, reg_predictions, candidate_xyz, prefix)
#预测解码
reg_preds_trans[..., 0:3]:目标中心相对于候选点的偏差 3
reg_preds_trans[..., 3:4]:方向类别 1
reg_preds_trans[..., 4:5]:方向偏差 1
reg_preds_trans[..., 5:23]:尺寸类别 18
reg_preds_trans[..., 23:77]:尺寸偏差 18x3
cls_preds_trans[..., 0:1]:目标损失,是否在目标内
cls_preds_trans[..., 1:19]:目标语义分类损失,18种类别
3 损失函数
计算损失函数需要将上述预测结果与标签一一对应。计算标签的函数入口为self.get_targets(points, gt_bboxes_3d, gt_labels_3d, pts_semantic_mask, pts_instance_mask, bbox_preds)。每个候选点对应的真实标签与所隶属的目标一致。
pts_instance_mask为实例mask,属于同一个目标的点用相同标签id表示,属于一种更加精细的目标标注方法,其中0表示背景,其它数值表示第id个目标。pts_semantic_mask为语义分割mask,标注了每个点所属的类别,类别id范围为0~num_classes-1,类别总数num_classes则用来表示背景点。这两者构成了实例分割标注,为了便于计算点属于哪个类别的实例目标。
各个标签如下所示。
- sampling_targets(1024),每个真实候选框最多选择与其中心最近的4个种子点,种子点被采样选中则取值为1,维度为1024。这一步对应KPS采样操作。
- 目标物体几何中心标签center_targets,即重心。维度为Kx3,K表示batch中单个样本含目标最多的数量,不足时补0,0,0,并用valid_gt_masks标识出补齐部分。这主要是为了将维度进行对齐,便于统一进行矩阵计算。
- 目标方向类别标签dir_class_targets,目标角度从0~2Π范围划分为12个子区间,每个区间作为一个类别。每个投票聚合点aggregated_points分配到距离中心最近的目标,方向分类与其一致,因此dir_class_targets维度为256x12。目标方向偏移标签dir_res_targets(256x1),角度相对子区间中心的偏移值,并除以区间大小进行归一化。程序中默认不对方向进行预测,因而将方向类别和偏移取值都设置为0。
- 目标尺寸标签size_class_targets(256x1)尺寸类别与物体类别保持一致,默认不同物体有不同的尺寸,即平均尺寸。size_res_targets(256x3)物体尺寸与平均尺寸的差值除以平均尺寸。
- 目标分类标签objectness_targets(256x1),候选点属于某个目标则取值为1,否则为0。
- 语义分类mask_targets (256x1)每个候选点所属目标的分类标签,0表示背景。
center_targets 物体几何中心,即重心。Kx3,K为batch中单个样本含目标最多的数量,不足时补0,0,0,并用valid_gt_masks进行标识。
size_target:真实目标几何尺寸
size_class_targets 尺寸类别与物体类别保持一致,默认不同物体有不同的尺寸,即平均尺寸
size_res_targets 物体尺寸与平均尺寸的差值除以平均尺寸。
dir_class_targets 目标角度从0~2Π范围划分为12个子区间,每个区间作为一个类别
dir_res_targets 角度相对子区间中心的偏移值,并除以区间大小进行归一化
objectness_targets 候选点是否包含在目标之中
mask_targets 每个候选点所属目标的分类标签,0表示背景。
assigned_center_targets 每个候选点所属目标的几何中心。
损失计算
Group-Free-3D模型损失主要包含KPS采样损失、分类预测损失和位置预测损失。KPS采样损失(sampling_objectness_loss)函数为FocalLoss,标签为sampling_targets。候选框分类损失包括目标损失(objectness_loss, FocalLoss)和语义分类损失(semantic_loss,CrossEntropyLoss)。位置预测损失包括中心损失(center_loss,SmoothL1Loss)、方向分类损失(dir_class_loss,CrossEntropyLoss)、方向回归损失(dir_res_loss,SmoothL1Loss)、尺寸分类损失(size_class_loss,CrossEntropyLoss)和尺寸回归损失(size_res_loss,SmoothL1Loss)。
分类预测损失和为位置预测损失共计7部分损失,而bbox head中分别计算得到了7阶段的预测结果。因此,Group-Free-3D模型总体损失函数包括50个组成部分。
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)
x = self.extract_feat(points_cat)
bbox_preds = self.bbox_head(x, self.train_cfg.sample_mod)
loss_inputs = (points, gt_bboxes_3d, gt_labels_3d, pts_semantic_mask, pts_instance_mask, img_metas)
losses = self.bbox_head.loss( bbox_preds, *loss_inputs, gt_bboxes_ignore=gt_bboxes_ignore)
return losses
5 【python三维深度学习】python三维点云从基础到深度学习_python3d点云从基础到深度学习-CSDN博客
【版权声明】
本文为博主原创文章,未经博主允许严禁转载,我们会定期进行侵权检索。
更多python与C++技巧、三维算法、深度学习算法总结、大模型请关注我的博客,欢迎讨论与交流:https://blog.csdn.net/suiyingy,或”乐乐感知学堂“公众号。Python三维领域专业书籍推荐:《人工智能点云处理及深度学习算法》。