pointnet++语义分割PointNet2_sem_seg.py代码解读

get_model()

特征提取层

在这里插入图片描述

l1_xyz, l1_points, l1_indices = pointnet_sa_module(l0_xyz, l0_points, npoint=1024, radius=0.1, nsample=32, mlp=[32,32,64], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer1')
l2_xyz, l2_points, l2_indices = pointnet_sa_module(l1_xyz, l1_points, npoint=256, radius=0.2, nsample=32, mlp=[64,64,128], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer2')
l3_xyz, l3_points, l3_indices = pointnet_sa_module(l2_xyz, l2_points, npoint=64, radius=0.4, nsample=32, mlp=[128,128,256], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer3')
l4_xyz, l4_points, l4_indices = pointnet_sa_module(l3_xyz, l3_points, npoint=16, radius=0.8, nsample=32, mlp=[256,256,512], mlp2=None, group_all=False, is_training=is_training, bn_decay=bn_decay, scope='layer4')

point_sa_module() 包含了一个完整的set abstraction抽象集过程

sampling layers

  • 利用FPS算法,farthest_point_sample(npoint,xyz),采样出球的质心点的索引(32,1024)
  • gather_point(xyz,farthest_point_sample(npoint,xyz))提取采样点的xyz坐标
    获得new_xyz(32,1024,3)
    ---------------------------------------------------点集划分完成--------------------------------------------------------------

grouping layers

  • idx, pts_cnt = query_ball_point(radius,nsample,xyz,new_xyz)获取半径中的局部点,
    idx(32,1024,32)为采样点1024个点所包含的32个局部点索引。

  • grouped_xyz = group_point(xyz,idx) 获取局部32个点的坐标,(32,1024,32,3)

  • grouped_xyz 标准化:32个点坐标分别减去质心点坐标

  • 若为第一层,则new_points = grouped_points 为(32,1024,32,3)后经过pointne获取特征,变为(32,1024,64)

  • 如果为中间层,则将上一层提取到的特征进行维度处理,以第二层为例(例如从(32,1024,64)提取出 idx(32,256,32)的点得到 grouped_points (32,256,32,64)),与grouped_xyz做拼接得到new_points

  • 最后返回new_xyz(FPS采样点(32,1024,3)), (这是第一层输出)
    new_points(多尺度组合后的点特征(32,1024,32,3))
    idx(点球获得的局部点索引(32,1024,32))(第一层输出)

  • 第二层
    new_xyz (32,256,3)
    new_points (32,256,32,64+3)
    idx (32,256,32)

----------------------------------------------球半径内局部特征获取完成-------------------------------------------------

pointnet layers

  • 对得到的new_points进行低维到高维的特征提取
  • 池化完成

----在局部区域重复使用pointnet生成新的点,新的点形成新的点集又定义小区域,形成多级学习-----

要素传播层

在这里插入图片描述

l3_points = pointnet_fp_module(l3_xyz, l4_xyz, l3_points, l4_points, [256,256], is_training, bn_decay, scope='fa_layer1')
l2_points = pointnet_fp_module(l2_xyz, l3_xyz, l2_points, l3_points, [256,256], is_training, bn_decay, scope='fa_layer2')
l1_points = pointnet_fp_module(l1_xyz, l2_xyz, l1_points, l2_points, [256,128], is_training, bn_decay, scope='fa_layer3')
l0_points = pointnet_fp_module(l0_xyz, l1_xyz, l0_points, l1_points, [128,128,128], is_training, bn_decay, scope='fa_layer4')

用作者的话说就是最后得到的点利用up-convolution的方法再重新传回到原来的点上实现分割
在语义点编著分个任务中,我们需要获取所有原始点的点特征。方法是将特征从自采样点传播到原始点。采用基于距离的内插和跨层跳跃链路的分层传播策略。

pointnet_fp_module()

  • dist,idx = three_nn(xyz1,xyz2) ,(这里以第一层为例)
    输入xyz1(32,64,3),xyz2(32,16,3),输出dist(32,64,3),idx (32,64,3)
    通过依次遍历每个点的xyz坐标,求出xyz2中16个点到xyz1中每个点的最小的三个距离写入dist张量
    中,以及16个点中的对应编号写入idx中。

    使用基于k个最近邻的距离加权逆平均
    在这里插入图片描述

  • 数据处理

 dist = tf.maximum(dist, 1e-10)
 norm = tf.reduce_sum((1.0/dist),axis=2,keep_dims=True)
 norm = tf.tile(norm,[1,1,3])
 weight = (1.0/dist) / norm

剔除最小距离为0的距离,之后 d = (1 / best1 ) + (1 / best2 ) + (1 / best3 ) 最小距离倒数相加求和。
norm(32,64,3)–>norm (32,64,1),再将第三维度复制3次–> norm(32,64,3)
再用 (1 / best1)/ d 三个距离都除获得新的weight(32,64,3)

 interpolated_points = three_interpolate(points2, idx, weight)

3D插值,找出对应64个点最近距离的16个点中的3个点按权重比例相加,也就是weight[0],weight[1],weight[2]构建好比例,从points2(32,16,512)中按照idx(32,64,3)的最近三点的编号提取3个点的特征,再乘比例相加,达成(32,16,512)–>(32,64,512)填充值的过程。

new_points1 = tf.concat(axis=2, values=[interpolated_points, points1])
new_points1 = tf.expand_dims(new_points1, 2)

再将points(32,64,256)与 interpolated_points (32,64,512)拼接,
并扩维(32,64,1,768)进行pointnet提取特征,最终返回new_points1(32,64,mlp[-1])

l3_points = pointnet_fp_module(l3_xyz, l4_xyz, l3_points, l4_points, [256,256], is_training, bn_decay, scope='fa_layer1')
l2_points = pointnet_fp_module(l2_xyz, l3_xyz, l2_points, l3_points, [256,256], is_training, bn_decay, scope='fa_layer2')
l1_points = pointnet_fp_module(l1_xyz, l2_xyz, l1_points, l2_points, [256,128], is_training, bn_decay, scope='fa_layer3')
l0_points = pointnet_fp_module(l0_xyz, l1_xyz, l0_points, l1_points, [128,128,128], is_training, bn_decay, scope='fa_layer4')

经过4层3D插值后,最终返回l0_points(32,2048,128)

net = tf_util.conv1d(l0_points, 128, 1, padding='VALID', bn=True, is_training=is_training, scope='fc1', bn_decay=bn_decay)
end_points['feats'] = net 
net = tf_util.dropout(net, keep_prob=0.5, is_training=is_training, scope='dp1')
net = tf_util.conv1d(net, num_class, 1, padding='VALID', activation_fn=None, scope='fc2')

经过FC最终将所有点都分类10类,net(32,2048,10)

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值