示例#1
0
    def __init__(self, radius, num_inputs, num_outputs, config):
        super(KPConvLayer, self).__init__()
        self.radius = radius
        self.num_inputs = num_inputs
        self.num_outputs = num_outputs
        self.config = config
        self.extent = self.config.NETWORK.KP_EXTENT * self.radius /\
            self.config.NETWORK.DENSITY_PARAMETER

        # Initial kernel extent for this layer
        K_radius = 1.5 * self.extent
        K_points_numpy = create_kernel_points(
            K_radius,
            self.config.NETWORK.NUM_KERNEL_POINTS,
            num_kernels=1,
            dimension=self.config.INPUT.POINTS_DIM,
            fixed=self.config.NETWORK.FIXED_KERNEL_POINTS)

        self.K_points = Parameter(torch.from_numpy(K_points_numpy.reshape((
            self.config.NETWORK.NUM_KERNEL_POINTS,
            self.config.INPUT.POINTS_DIM))).to(torch.float),
                                  requires_grad=False)

        self.weight = Parameter(
            weight_variable([self.config.NETWORK.NUM_KERNEL_POINTS,
                             self.num_inputs,
                             self.num_outputs]))
示例#2
0
def KPConv(query_points,
           support_points,
           neighbors_indices,
           features,
           K_values,
           fixed='center',
           KP_extent=1.0,
           KP_influence='linear',
           aggregation_mode='sum'):
    """
    This function initiates the kernel point disposition before building KPConv graph ops

    :param query_points: float32[n_points, dim] - input query points (center of neighborhoods)
    :param support_points: float32[n0_points, dim] - input support points (from which neighbors are taken)
    :param neighbors_indices: int32[n_points, n_neighbors] - indices of neighbors of each point
    :param features: float32[n_points, in_fdim] - input features
    :param K_values: float32[n_kpoints, in_fdim, out_fdim] - weights of the kernel
    :param fixed: string in ('none', 'center' or 'verticals') - fix position of certain kernel points
    :param KP_extent: float32 - influence radius of each kernel point
    :param KP_influence: string in ('constant', 'linear', 'gaussian') - influence function of the kernel points
    :param aggregation_mode: string in ('closest', 'sum') - whether to sum influences, or only keep the closest

    :return: output_features float32[n_points, out_fdim]
    """

    # Initial kernel extent for this layer
    K_radius = 1.5 * KP_extent

    # Number of kernel points
    num_kpoints = int(K_values.shape[0])

    # Check point dimension (currently only 3D is supported)
    points_dim = int(query_points.shape[1])

    # Create one kernel disposition (as numpy array). Choose the KP distance to center thanks to the KP extent
    K_points_numpy = create_kernel_points(K_radius,
                                          num_kpoints,
                                          num_kernels=1,
                                          dimension=points_dim,
                                          fixed=fixed)
    K_points_numpy = K_points_numpy.reshape((num_kpoints, points_dim))

    # Create the tensorflow variable
    K_points = tf.Variable(K_points_numpy.astype(np.float32),
                           name='kernel_points',
                           trainable=False,
                           dtype=tf.float32)

    return KPConv_ops(query_points,
                      support_points,
                      neighbors_indices,
                      features,
                      K_points,
                      K_values,
                      KP_extent,
                      KP_influence,
                      aggregation_mode)
示例#3
0
    def __init__(self, radius, num_inputs,
                 num_outputs, config, version=0, modulated=False):
        """
        it doesn't work yet :
        """
        super(DeformableKPConvLayer, self).__init__()
        self.radius = radius
        self.num_inputs = num_inputs
        self.num_outputs = num_outputs
        self.config = config
        self.extent = self.config.NETWORK.KP_EXTENT * self.radius /\
            self.config.NETWORK.DENSITY_PARAMETER
        self.version = version
        self.modulated = modulated

        # Initial kernel extent for this layer
        K_radius = 1.5 * self.extent
        K_points_numpy = create_kernel_points(
            K_radius,
            self.config.NETWORK.NUM_KERNEL_POINTS,
            num_kernels=1,
            dimension=self.config.INPUT.POINTS_DIM,
            fixed=self.config.NETWORK.FIXED_KERNEL_POINTS)

        self.K_points = Parameter(torch.from_numpy(K_points_numpy.reshape((
            self.config.NETWORK.NUM_KERNEL_POINTS,
            self.config.INPUT.POINTS_DIM))).to(torch.float),
                                  requires_grad=False)

        # Parameter of the deformable convolution
        self.weight = Parameter(
            weight_variable([self.config.NETWORK.NUM_KERNEL_POINTS,
                             self.num_inputs,
                             self.num_outputs]))
        if(self.modulated):
            offset_dim = (self.config.INPUT.POINTS_DIM+1) * (self.config.NETWORK.NUM_KERNEL_POINTS -1)
        else:
            offset_dim = (self.config.INPUT.POINTS_DIM) * (self.config.NETWORK.NUM_KERNEL_POINTS -1)

        if(self.version == 0):
            # kp conv to estimate the offset
            self.deformable_weight = Parameter(
                weight_variable([self.config.NETWORK.NUM_KERNEL_POINTS,
                                 self.num_inputs,
                                 offset_dim]))
        elif(self.version == 1):
            # MLP to estimate the offset
            self.deformable_weight = Parameter(
                weight_variable([self.num_inputs,
                                 offset_dim]))
        self.bias = torch.nn.Parameter(
            torch.zeros(offset_dim, dtype=torch.float32), requires_grad=True)
示例#4
0
def KPConv_deformable_v2(query_points,
                         support_points,
                         neighbors_indices,
                         features,
                         K_values,
                         fixed='center',
                         KP_extent=1.0,
                         KP_influence='linear',
                         aggregation_mode='sum',
                         modulated=False):
    """
    This alternate version uses a pointwise MLP instead of KPConv to get the offset. It has thus less parameters.
    It also fixes the center point to remain in the center in any case. This definition offers similar performances

    :param query_points: float32[n_points, dim] - input query points (center of neighborhoods)
    :param support_points: float32[n0_points, dim] - input support points (from which neighbors are taken)
    :param neighbors_indices: int32[n_points, n_neighbors] - indices of neighbors of each point
    :param features: float32[n_points, in_fdim] - input features
    :param K_values: float32[n_kpoints, in_fdim, out_fdim] - weights of the kernel
    :param fixed: string in ('none', 'center' or 'verticals') - fix position of certain kernel points
    :param KP_extent: float32 - influence radius of each kernel point
    :param KP_influence: string in ('constant', 'linear', 'gaussian') - influence function of the kernel points
    :param aggregation_mode: string in ('closest', 'sum') - behavior of the convolution
    :param modulated: bool - If deformable conv should be modulated

    :return: output_features float32[n_points, out_fdim]
    """

    ############
    # Parameters
    ############

    # Check point dimension (currently only 3D is supported)
    points_dim = int(query_points.shape[1])

    # Number of kernel points
    num_kpoints = int(K_values.shape[0])

    #################
    # MLP for offsets
    #################

    # Create independant weight for the first convolution and a bias term as no batch normalization happen
    if modulated:
        offset_dim = (points_dim + 1) * (num_kpoints - 1)
    else:
        offset_dim = points_dim * (num_kpoints - 1)
    shape0 = K_values.shape.as_list()

    w0 = tf.Variable(tf.zeros([shape0[1], offset_dim], dtype=tf.float32),
                     name='offset_mlp_weights')
    b0 = tf.Variable(tf.zeros([offset_dim], dtype=tf.float32),
                     name='offset_mlp_bias')

    # Get features from mlp
    features0 = unary_convolution(features, w0) + b0

    if modulated:

        # Get offset (in normalized scale) from features
        offsets = features0[:, :points_dim * (num_kpoints - 1)]
        offsets = tf.reshape(offsets, [-1, (num_kpoints - 1), points_dim])

        # Get modulations
        modulations = 2 * tf.sigmoid(features0[:, points_dim *
                                               (num_kpoints - 1):])

        #  No offset for the first Kernel points
        offsets = tf.concat([tf.zeros_like(offsets[:, :1, :]), offsets],
                            axis=1)
        modulations = tf.concat(
            [tf.zeros_like(modulations[:, :1]), modulations], axis=1)

    else:

        # Get offset (in normalized scale) from features
        offsets = tf.reshape(features0, [-1, (num_kpoints - 1), points_dim])

        # No offset for the first Kernel points
        offsets = tf.concat([tf.zeros_like(offsets[:, :1, :]), offsets],
                            axis=1)

        # No modulations
        modulations = None

    # Rescale offset for this layer
    offsets *= KP_extent

    #################################
    # Initiate kernel point positions
    #################################

    # Radius of the initial positions of the kernel points
    K_radius = 1.5 * KP_extent

    # Create one kernel disposition (as numpy array). Choose the KP distance to center thanks to the KP extent
    K_points_numpy = create_kernel_points(K_radius,
                                          num_kpoints,
                                          num_kernels=1,
                                          dimension=points_dim,
                                          fixed=fixed)
    K_points_numpy = K_points_numpy.reshape((num_kpoints, points_dim))

    # Create the tensorflow variable
    K_points = tf.Variable(K_points_numpy.astype(np.float32),
                           name='kernel_points',
                           trainable=False,
                           dtype=tf.float32)

    ###############################
    # Build deformable KPConv graph
    ###############################

    # Apply deformed convolution
    return KPConv_deform_ops(query_points, support_points, neighbors_indices,
                             features, K_points, offsets, modulations,
                             K_values, KP_extent, KP_influence,
                             aggregation_mode)
示例#5
0
def KPConv_deformable(query_points,
                      support_points,
                      neighbors_indices,
                      features,
                      K_values,
                      fixed='center',
                      KP_extent=1.0,
                      KP_influence='linear',
                      aggregation_mode='sum',
                      modulated=False):
    """
    This function initiates the kernel point disposition before building deformable KPConv graph ops

    :param query_points: float32[n_points, dim] - input query points (center of neighborhoods)
    :param support_points: float32[n0_points, dim] - input support points (from which neighbors are taken)
    :param neighbors_indices: int32[n_points, n_neighbors] - indices of neighbors of each point
    :param features: float32[n_points, in_fdim] - input features
    :param K_values: float32[n_kpoints, in_fdim, out_fdim] - weights of the kernel
    :param fixed: string in ('none', 'center' or 'verticals') - fix position of certain kernel points
    :param KP_extent: float32 - influence radius of each kernel point
    :param KP_influence: string in ('constant', 'linear', 'gaussian') - influence function of the kernel points
    :param aggregation_mode: string in ('closest', 'sum') - behavior of the convolution
    :param modulated: bool - If deformable conv should be modulated

    :return: output_features float32[n_points, out_fdim]
    """

    ############
    # Parameters
    ############

    # Radius of the initial positions of the kernel points
    K_radius = 1.5 * KP_extent

    # Number of kernel points
    num_kpoints = int(K_values.shape[0])

    # Check point dimension (currently only 3D is supported)
    points_dim = int(query_points.shape[1])

    #################################
    # Initiate kernel point positions
    #################################

    # Create one kernel disposition (as numpy array). Choose the KP distance to center thanks to the KP extent
    K_points_numpy = create_kernel_points(K_radius,
                                          num_kpoints,
                                          num_kernels=1,
                                          dimension=points_dim,
                                          fixed=fixed)
    K_points_numpy = K_points_numpy.reshape((num_kpoints, points_dim))

    # Create the tensorflow variable
    K_points = tf.Variable(K_points_numpy.astype(np.float32),
                           name='kernel_points',
                           trainable=False,
                           dtype=tf.float32)

    #############################
    # Standard KPConv for offsets
    #############################

    # Create independant weight for the first convolution and a bias term as no batch normalization happen
    if modulated:
        offset_dim = (points_dim + 1) * num_kpoints
    else:
        offset_dim = points_dim * num_kpoints
    shape0 = K_values.shape.as_list()
    shape0[-1] = offset_dim
    K_values0 = tf.Variable(tf.zeros(shape0, dtype=tf.float32),
                            name='offset_conv_weights')
    b0 = tf.Variable(tf.zeros(offset_dim, dtype=tf.float32),
                     name='offset_conv_bias')

    # Get features from standard convolution
    features0 = KPConv_ops(query_points, support_points, neighbors_indices,
                           features, K_points, K_values0, KP_extent,
                           KP_influence, aggregation_mode) + b0

    if modulated:

        # Get offset (in normalized scale) from features
        offsets = features0[:, :points_dim * num_kpoints]
        offsets = tf.reshape(offsets, [-1, num_kpoints, points_dim])

        # Get modulations
        modulations = 2 * tf.sigmoid(features0[:, points_dim * num_kpoints:])

    else:

        # Get offset (in normalized scale) from features
        offsets = tf.reshape(features0, [-1, num_kpoints, points_dim])

        # No modulations
        modulations = None

    # Rescale offset for this layer
    offsets *= KP_extent

    ###############################
    # Build deformable KPConv graph
    ###############################

    # Apply deformed convolution
    return KPConv_deform_ops(query_points, support_points, neighbors_indices,
                             features, K_points, offsets, modulations,
                             K_values, KP_extent, KP_influence,
                             aggregation_mode)
示例#6
0
def KPConv_deformable(query_points,
                      support_points,
                      neighbors_indices,
                      features,
                      K_values,
                      fixed='center',
                      KP_extent=1.0,
                      KP_influence='linear',
                      aggregation_mode='sum',
                      modulated=False):
    """
    This function initiates the kernel point disposition before building deformable KPConv graph ops

    :param query_points: float32[n_points, dim] - input query points (center of neighborhoods)
    :param support_points: float32[n0_points, dim] - input support points (from which neighbors are taken)
    :param neighbors_indices: int32[n_points, n_neighbors] - indices of neighbors of each point
    :param features: float32[n_points, in_fdim] - input features
    :param K_values: float32[n_kpoints, in_fdim, out_fdim] - weights of the kernel
    :param fixed: string in ('none', 'center' or 'verticals') - fix position of certain kernel points
    :param KP_extent: float32 - influence radius of each kernel point
    :param KP_influence: string in ('constant', 'linear', 'gaussian') - influence function of the kernel points
    :param aggregation_mode: string in ('closest', 'sum') - behavior of the convolution
    :param modulated: bool - If deformable conv should be modulated

    :return: output_features float32[n_points, out_fdim]
    """

    ############
    # Parameters
    ############

    #####Change####

    indices = pf.knn_indices_general(qrs, pts, K, True)

    nn_pts = tf.gather_nd(pts, indices, name=tag + 'nn_pts')  # (N, P, K, 3)
    nn_pts_center = tf.expand_dims(qrs, axis=2,
                                   name=tag + 'nn_pts_center')  # (N, P, 1, 3)
    nn_pts_local = tf.subtract(nn_pts,
                               nn_pts_center,
                               name=tag + 'nn_pts_local')  # (N, P, K, 3)

    [N, P, K, dim] = nn_pts_local.shape  # (N, P, K, 3)
    nn_fts_local = None
    C_pts_fts = 64
    if with_local:
        nn_fts_local = dense(nn_pts_local,
                             C_pts_fts // 2,
                             is_training,
                             tag + 'nn_fts_from_pts_0',
                             bn_decay=bn_decay)
        nn_fts_local = dense(nn_fts_local,
                             C_pts_fts,
                             is_training,
                             tag + 'nn_fts_from_pts',
                             bn_decay=bn_decay)
    else:
        nn_fts_local = nn_pts_local

    if fts_prev is not None:
        fts_prev = tf.gather_nd(fts_prev, indices,
                                name=tag + 'fts_prev')  # (N, P, K, 3)
        pts_X_0 = tf.concat([nn_fts_local, fts_prev], axis=-1)
    else:
        pts_X_0 = nn_fts_local

    s = int(K.value / D)  # no. of divisions
    feat_max = tf.layers.max_pooling2d(pts_X_0, [1, s],
                                       strides=[1, s],
                                       padding='valid',
                                       name=tag + 'maxpool_0')

    fts_X = conv2d(feat_max,
                   C,
                   name=tag + 'conv',
                   is_training=is_training,
                   kernel_size=[1, feat_max.shape[-2].value])

    fts_X = tf.squeeze(fts_X, axis=-2)

    ###Change####

    # Radius of the initial positions of the kernel points
    K_radius = 1.5 * KP_extent

    # Number of kernel points
    num_kpoints = int(K_values.shape[0])

    # Check point dimension (currently only 3D is supported)
    points_dim = int(query_points.shape[1])

    #################################
    # Initiate kernel point positions
    #################################

    # Create one kernel disposition (as numpy array). Choose the KP distance to center thanks to the KP extent
    K_points_numpy = create_kernel_points(K_radius,
                                          num_kpoints,
                                          num_kernels=1,
                                          dimension=points_dim,
                                          fixed=fixed)
    K_points_numpy = K_points_numpy.reshape((num_kpoints, points_dim))

    # Create the tensorflow variable
    K_points = tf.Variable(K_points_numpy.astype(np.float32),
                           name='kernel_points',
                           trainable=False,
                           dtype=tf.float32)

    #############################
    # Standard KPConv for offsets
    #############################

    # Create independant weight for the first convolution and a bias term as no batch normalization happen
    if modulated:
        offset_dim = (points_dim + 1) * num_kpoints
    else:
        offset_dim = points_dim * num_kpoints
    shape0 = K_values.shape.as_list()
    shape0[-1] = offset_dim
    K_values0 = tf.Variable(tf.zeros(shape0, dtype=tf.float32),
                            name='offset_conv_weights')
    b0 = tf.Variable(tf.zeros(offset_dim, dtype=tf.float32),
                     name='offset_conv_bias')

    # Get features from standard convolution
    features0 = KPConv_ops(query_points, support_points, neighbors_indices,
                           features, K_points, K_values0, KP_extent,
                           KP_influence, aggregation_mode) + b0

    if modulated:

        # Get offset (in normalized scale) from features
        offsets = features0[:, :points_dim * num_kpoints]
        offsets = tf.reshape(offsets, [-1, num_kpoints, points_dim])

        # Get modulations
        modulations = 2 * tf.sigmoid(features0[:, points_dim * num_kpoints:])

    else:

        # Get offset (in normalized scale) from features
        offsets = tf.reshape(features0, [-1, num_kpoints, points_dim])

        # No modulations
        modulations = None

    # Rescale offset for this layer
    offsets *= KP_extent

    ###############################
    # Build deformable KPConv graph
    ###############################

    # Apply deformed convolution
    return KPConv_deform_ops(query_points, support_points, neighbors_indices,
                             features, K_points, offsets, modulations,
                             K_values, KP_extent, KP_influence,
                             aggregation_mode)