EfficientLO代码解析(2)

来看EfficientLO的网络。网络设计主要是在pwclo_model.py文件里面。

发现自己对cnn的理解不够,先看了这篇文章

CNN(卷积神经网络)介绍 - 知乎

1、从if __name__=='__main__'开始

这个我感觉对项目没啥用处?

2、def placeholder_inputs(batch_size, NUM_POINTS)

这里主要是定义了点云数据变量、真实变换矩阵T_gt、估计的变换矩阵T及其逆。

3、def get_loss(l0_q, l0_t, l1_q, l1_t, l2_q, l2_t, l3_q, l3_t, q_gt, t_gt, w_x, w_q)

def get_loss(l0_q, l0_t, l1_q, l1_t, l2_q, l2_t, l3_q, l3_t, q_gt, t_gt, w_x, w_q):#####id

    t_gt = tf.squeeze(t_gt, axis = -1)###  8,3 t_gt 的形状从 (8, 3, 1) 变为 (8, 3). 8是因为输入的batch_size是8

    batch_size = q_gt.get_shape()[0].value


    l0_q_norm = l0_q / (tf.sqrt(tf.reduce_sum(l0_q*l0_q, axis=-1, keep_dims=True)+1e-10) + 1e-10)
    l0_loss_q = tf.reduce_mean(tf.sqrt(tf.reduce_sum((q_gt-l0_q_norm)*(q_gt-l0_q_norm), axis=-1, keep_dims=True)+1e-10)) # 计算l0_q与q_gt之间的欧式距离当作loss
    l0_loss_x = tf.reduce_mean( tf.sqrt((l0_t-t_gt) * (l0_t-t_gt)+1e-10)) # 计算l0_t与t_gt之间的欧式距离当作loss
    
    l0_loss = l0_loss_x * tf.exp(-w_x) + w_x + l0_loss_q * tf.exp(-w_q) + w_q # 论文中的式(16)
    
    tf.summary.scalar('l0 loss', l0_loss)

    省略中间的l1,l2,l3的loss计算过程,和l0是一样的。

    loss_sum = 1.6*l3_loss + 0.8*l2_loss + 0.4*l1_loss + 0.2*l0_loss # 按照权重加起来

    tf.add_to_collection('losses', loss_sum)
    return loss_sum

这里其实就是一个简单的loss计算。但对于loss计算有个问题

1.l3代表的是coarse的pose,误差大,定权大的话使得更快收敛。

2.l0代表的是fine的pose,误差小,定权大的话是否可以更侧重于提升精度。

这里的理解:

4、def get_model

这个get_model函数的原理其实就是论文里面的fig2

    for i in range(1, 6):
        out_h_list.append(math.ceil(out_h_list[i - 1] / stride_h_list[i]))
        out_w_list.append(math.ceil(out_w_list[i - 1] / stride_w_list[i]))  # generate the output shape list

 先在这里做一个步长提取器,对应着理解就算需要从PC中提取F。


    ####  the pre2 select bn3 xyz
    # get_selected_idx就是根据步长选一些点出来
    pre2_selected_idx = get_selected_idx(xyz_f1_input_proj, stride_h_list[1], stride_w_list[1], out_h_list[1], out_w_list[1])  ###   b outh outw 3
    # 使用索引pre2_selected_idx在xyz_f1_input_proj选取特定位置的元素。
    # xyz_f1_input_proj形状为(b, outh, outw, 3),其中 b 是批次大小,outh 和 outw 是输出特征图的高度和宽度,3 是每个位置的元素数量。
    pre2_xyz_proj_f1 = tf.gather_nd(xyz_f1_input_proj, pre2_selected_idx)  ##  b outh outw 3
    pre2_xyz_proj_f2 = tf.gather_nd(xyz_f2_input_proj, pre2_selected_idx)  ##  b outh outw 3


    ####  the l0 select bn3 xyz
    
    l0_selected_idx = get_selected_idx(pre2_xyz_proj_f1, stride_h_list[2], stride_w_list[2], out_h_list[2], out_w_list[2])  ###   b outh outw 3
    l0_xyz_proj_f1 = tf.gather_nd(pre2_xyz_proj_f1, l0_selected_idx)  ##  b outh outw 3
    l0_xyz_proj_f2 = tf.gather_nd(pre2_xyz_proj_f2, l0_selected_idx)  ##  b outh outw 3


    ####  the l1 select bn3 xyz
    
    l1_selected_idx = get_selected_idx(l0_xyz_proj_f1, stride_h_list[3], stride_w_list[3], out_h_list[3], out_w_list[3])  ###   b outh outw 3
    l1_xyz_proj_f1 = tf.gather_nd(l0_xyz_proj_f1, l1_selected_idx)  ##  b outh outw 3
    l1_xyz_proj_f2 = tf.gather_nd(l0_xyz_proj_f2, l1_selected_idx)  ##  b outh outw 3

    ####  the l2 select bn3 xyz
    
    l2_selected_idx = get_selected_idx(l1_xyz_proj_f1, stride_h_list[4], stride_w_list[4], out_h_list[4], out_w_list[4])  ###   b outh outw 3
    l2_xyz_proj_f1 = tf.gather_nd(l1_xyz_proj_f1, l2_selected_idx)  ##  b outh outw 3
    l2_xyz_proj_f2 = tf.gather_nd(l1_xyz_proj_f2, l2_selected_idx)  ##  b outh outw 3

    ####  the l3 select bn3 xyz
    
    l3_selected_idx = get_selected_idx(l2_xyz_proj_f1, stride_h_list[5], stride_w_list[5], out_h_list[5], out_w_list[5])  ###   b outh outw 3

这里就是点数由多到少的进行提取。l0对应的是最多的点、最fine的pose,那么这个就多一些点。l3对应最少的点、最coarse的pose,那么这个就少一点。其实这个从循环:

    for i in range(1, 6):
        out_h_list.append(math.ceil(out_h_list[i - 1] / stride_h_list[i]))
        out_w_list.append(math.ceil(out_w_list[i - 1] / stride_w_list[i]))  # generate the output shape list

这里也可以看出来,out_h_list和out_w_list大小都是不断减少的。

    with tf.variable_scope('sa1') as scope:
        l0_points_f1, l0_xyz_proj_f1 = down_conv(xyz_f1_input_proj, points_f1_input_proj, l0_selected_idx, \
            K_sample = 32, kernel_size =  [9, 15], distance = Down_conv_dis[0], mlp = [8,8,16], mlp2 = None, flag_add=False, is_training=is_training, bn_decay=bn_decay, scope='layer0')
        l0_points_proj_f1 = tf.reshape(l0_points_f1, [batch_size, out_h_list[2], out_w_list[2], -1])

        l1_points_f1, l1_xyz_proj_f1 = down_conv(l0_xyz_proj_f1, l0_points_proj_f1, l1_selected_idx, \
            K_sample = 32, kernel_size =  [7, 11], distance = Down_conv_dis[1], mlp = [16,16,32], mlp2 = None, flag_add=False, is_training=is_training, bn_decay=bn_decay, scope='layer1')
        l1_points_proj_f1 = tf.reshape(l1_points_f1, [batch_size, out_h_list[3], out_w_list[3], -1])
        
        ############# 接下来的l2、l3同样处理方法,省略 ####################

        scope.reuse_variables()
    
        ############# 接下来是对f2的处理,与f1处理类似 ####################
        l0_points_f2, l0_xyz_proj_f2 = down_conv(xyz_f2_input_proj, points_f2_input_proj, l0_selected_idx, \
            K_sample = 32, kernel_size =  [9, 15], distance = Down_conv_dis[0], mlp = [8,8,16], mlp2 = None, flag_add=False, is_training=is_training, bn_decay=bn_decay, scope='layer0')
        l0_points_proj_f2 = tf.reshape(l0_points_f2, [batch_size, out_h_list[2], out_w_list[2], -1])

        l1_points_f2, l1_xyz_proj_f2 = down_conv(l0_xyz_proj_f2, l0_points_proj_f2, l1_selected_idx, \
            K_sample = 32, kernel_size =  [7, 11], distance = Down_conv_dis[1], mlp = [16,16,32], mlp2 = None, flag_add=False, is_training=is_training, bn_decay=bn_decay, scope='layer1')
        l1_points_proj_f2 = tf.reshape(l1_points_f2, [batch_size, out_h_list[3], out_w_list[3], -1])

        ############# 接下来的l2、l3同样处理方法,省略 ####################

这里分别对f1和f2进行了down_conv的处理,以f1为例。

对第0层:

输入:xyz_f1_input_proj, points_f1_input_proj, l0_selected_idx

其中xyz_f1_input_proj, points_f1_input_proj暂时还是一个东西。l0_selected_idx是选中的H和W的步长所对应的点。

其实在这里就是选取了一个特征图出来。对应做出来的东西就是fig2中的PC和F。


紧接着就是进行cost volume的计算

在这里

l2_points_f1_new = cost_volume(l2_xyz_proj_f1, l2_xyz_proj_f2, l2_points_proj_f1, l2_points_proj_f2, \
        kernel_size1 = [3, 5], kernel_size2 = [5, 35] , nsample=4, nsample_q=32, distance = Cost_volume_dis[2], mlp1=[128,64,64], mlp2 = [128,64], \
        is_training=is_training, bn_decay=bn_decay, scope='flow_embedding_l2_origin', bn=True, pooling='max', knn=True, corr_func='concat')

l2_xyz_proj_f1和l2_xyz_proj_f2:(8,4,57,3)

l2_points_proj_f1和l2_points_proj_f2:(8,4,57,64)

这里用的是最大池化,更好的提取特征。

这里还对l3进行了为mlp准备的操作

    l3_points_f1_cost_volume, _ = down_conv(l2_xyz_proj_f1, l2_points_new_proj_f1, l3_selected_idx, \
        K_sample = 16, kernel_size =  [5, 9], distance = Down_conv_dis[3], mlp = [128,64,64], mlp2 = None, \
        flag_add=False, is_training=is_training, bn_decay=bn_decay, scope='new_layer3')

对应fig2中连接MLP的那个F_1^3.


接下来的操作就是通过几个warp-refinement来进行pose的精确估计。

最后将每一层估计的q和t输出出来即可。

  • 43
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值