def get_center_regression_net(object_point_cloud, one_hot_vec, is_training,
                              bn_decay, end_points):
    ''' Regression network for center delta. a.k.a. T-Net.
    Input:
        object_point_cloud: TF tensor in shape (B,M,C)
            point clouds in 3D mask coordinate
        one_hot_vec: TF tensor in shape (B,3)
            length-3 vectors indicating predicted object type
    Output:
        predicted_center: TF tensor in shape (B,3)
    '''
    num_point = object_point_cloud.get_shape()[1].value
    net = tf.expand_dims(object_point_cloud, 2)
    net = tf_util.conv2d(net,
                         128, [1, 1],
                         padding='VALID',
                         stride=[1, 1],
                         bn=True,
                         is_training=is_training,
                         scope='conv-reg1-stage1',
                         bn_decay=bn_decay)
    net = tf_util.conv2d(net,
                         128, [1, 1],
                         padding='VALID',
                         stride=[1, 1],
                         bn=True,
                         is_training=is_training,
                         scope='conv-reg2-stage1',
                         bn_decay=bn_decay)
    net = tf_util.conv2d(net,
                         256, [1, 1],
                         padding='VALID',
                         stride=[1, 1],
                         bn=True,
                         is_training=is_training,
                         scope='conv-reg3-stage1',
                         bn_decay=bn_decay)
    net = tf_util.max_pool2d(net, [num_point, 1],
                             padding='VALID',
                             scope='maxpool-stage1')
    net = tf.squeeze(net, axis=[1, 2])
    net = tf.concat([net, one_hot_vec], axis=1)
    net = tf_util.fully_connected(net,
                                  256,
                                  scope='fc1-stage1',
                                  bn=True,
                                  is_training=is_training,
                                  bn_decay=bn_decay)
    net = tf_util.fully_connected(net,
                                  128,
                                  scope='fc2-stage1',
                                  bn=True,
                                  is_training=is_training,
                                  bn_decay=bn_decay)
    predicted_center = tf_util.fully_connected(net,
                                               3,
                                               activation_fn=None,
                                               scope='fc3-stage1')
    return predicted_center, end_points
    def get_3d_box_estimation_v1_net(self, object_point_cloud, one_hot_vec,
                                     is_training, bn_decay, end_points):
        ''' 3D Box Estimation PointNet v1 network.
        Input:
            object_point_cloud: TF tensor in shape (B,M,C)
                point clouds in object coordinate
            one_hot_vec: TF tensor in shape (B,3)
                length-3 vectors indicating predicted object type
        Output:
            output: TF tensor in shape (B,3+NUM_HEADING_BIN*2+NUM_SIZE_CLUSTER*4)
                including box centers, heading bin class scores and residuals,
                and size cluster scores and residuals
        '''
        num_point = object_point_cloud.get_shape()[1].value
        net = tf.expand_dims(object_point_cloud, 2)
        net = tf_util.conv2d(net,
                             128, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv-reg1',
                             bn_decay=bn_decay)
        net = tf_util.conv2d(net,
                             128, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv-reg2',
                             bn_decay=bn_decay)
        net = tf_util.conv2d(net,
                             256, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv-reg3',
                             bn_decay=bn_decay)
        net = tf_util.conv2d(net,
                             512, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv-reg4',
                             bn_decay=bn_decay)

        features = tf.reduce_max(net, axis=1)

        net = tf_util.max_pool2d(net, [num_point, 1],
                                 padding='VALID',
                                 scope='maxpool2')
        net = tf.squeeze(net, axis=[1, 2])
        net = tf.concat([net, one_hot_vec], axis=1)
        net = tf_util.fully_connected(net,
                                      512,
                                      scope='fc1',
                                      bn=True,
                                      is_training=is_training,
                                      bn_decay=bn_decay)
        net = tf_util.fully_connected(net,
                                      256,
                                      scope='fc2',
                                      bn=True,
                                      is_training=is_training,
                                      bn_decay=bn_decay)

        # The first 3 numbers: box center coordinates (cx,cy,cz),
        # the next NUM_HEADING_BIN*2:  heading bin class scores and bin residuals
        # next NUM_SIZE_CLUSTER*4: box cluster scores and residuals
        output = tf_util.fully_connected(net,
                                         3 + model_util.NUM_HEADING_BIN * 2 +
                                         model_util.NUM_SIZE_CLUSTER * 4,
                                         activation_fn=None,
                                         scope='fc3')
        return output, end_points, features
    def get_instance_seg_v1_net(self, point_cloud, one_hot_vec, is_training,
                                bn_decay, end_points):
        ''' 3D instance segmentation PointNet v1 network.
        Input:
            point_cloud: TF tensor in shape (B,N,4)
                frustum point clouds with XYZ and intensity in point channels
                XYZs are in frustum coordinate
            one_hot_vec: TF tensor in shape (B,3)
                length-3 vectors indicating predicted object type
            is_training: TF boolean scalar
            bn_decay: TF float scalar
            end_points: dict
        Output:
            logits: TF tensor in shape (B,N,2), scores for bkg/clutter and object
            end_points: dict
        '''
        num_point = point_cloud.get_shape()[1].value

        net = tf.expand_dims(point_cloud, 2)

        net = tf_util.conv2d(net,
                             64, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv1',
                             bn_decay=bn_decay)
        net = tf_util.conv2d(net,
                             64, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv2',
                             bn_decay=bn_decay)
        point_feat = tf_util.conv2d(net,
                                    64, [1, 1],
                                    padding='VALID',
                                    stride=[1, 1],
                                    bn=True,
                                    is_training=is_training,
                                    scope='conv3',
                                    bn_decay=bn_decay)
        net = tf_util.conv2d(point_feat,
                             128, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv4',
                             bn_decay=bn_decay)
        net = tf_util.conv2d(net,
                             1024, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv5',
                             bn_decay=bn_decay)

        global_feat = tf_util.max_pool2d(net, [num_point, 1],
                                         padding='VALID',
                                         scope='maxpool')

        global_feat = tf.concat(
            [global_feat,
             tf.expand_dims(tf.expand_dims(one_hot_vec, 1), 1)],
            axis=3)
        global_feat_expand = tf.tile(global_feat, [1, num_point, 1, 1])
        concat_feat = tf.concat(axis=3,
                                values=[point_feat, global_feat_expand])

        net = tf_util.conv2d(concat_feat,
                             512, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv6',
                             bn_decay=bn_decay)
        net = tf_util.conv2d(net,
                             256, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv7',
                             bn_decay=bn_decay)
        net = tf_util.conv2d(net,
                             128, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv8',
                             bn_decay=bn_decay)
        net = tf_util.conv2d(net,
                             128, [1, 1],
                             padding='VALID',
                             stride=[1, 1],
                             bn=True,
                             is_training=is_training,
                             scope='conv9',
                             bn_decay=bn_decay)
        net = tf_util.dropout(net, is_training, 'dp1', keep_prob=0.5)

        logits = tf_util.conv2d(net,
                                2, [1, 1],
                                padding='VALID',
                                stride=[1, 1],
                                activation_fn=None,
                                scope='conv10')
        logits = tf.squeeze(logits, [2])  # BxNxC
        return logits, end_points