コード例 #1
0
    def __call__(self,
                 features,
                 point_cloud,
                 return_sorted=False,
                 return_padded=False):
        """ Computes the 1x1 convolution on a point cloud.

    Note:
      In the following, `A1` to `An` are optional batch dimensions.
      `C_in` is the number of input features.
      `C_out` is the number of output features.

    Args:
      features: A `float` `Tensor` of shape `[N_in, C_in]` or
        `[A1, ..., An, V, C_in]`.
      point_cloud: A 'PointCloud' instance, on which the features are
        defined.
      return_sorted: A `boolean`, if `True` the output tensor is sorted
        according to the batch_ids. (optional)
      return_padded: A `bool`, if 'True' the output tensor is sorted and
        zero padded. (optional)

    Returns:
      A `float` `Tensor` of shape
        `[N_out, C_out]`, if `return_padded` is `False`
      or
        `[A1, ..., An, V_out, C_out]`, if `return_padded` is `True`.

    """
        features = tf.cast(tf.convert_to_tensor(value=features),
                           dtype=tf.float32)
        features = _flatten_features(features, point_cloud)
        features = tf.matmul(features, self._weights_tf) + self._bias_tf
        return _format_output(features, point_cloud, return_sorted,
                              return_padded)
コード例 #2
0
    def __call__(self,
                 features,
                 point_cloud: PointCloud,
                 return_padded=False,
                 name=None):
        """ Performs a global average pooling on a point cloud

    Note:
      In the following, `A1` to `An` are optional batch dimensions.

    Args:
      features: A tensor of shape `[N, C]` or `[A1, ..., An, V, C]`.
      point_cloud: A `PointCloud` instance.
      return_padded: A `bool`, if `True` reshapes the output to match the
        batch shape of `point_cloud`.

    Returns:
      A tensor of same type as `features` and of shape
        `[B, C]`, if not `return_padded`
      or
        `[A1 ,..., An, C]`, if `return_padded`

    """
        features = tf.convert_to_tensor(value=features)
        features = _flatten_features(features, point_cloud)
        features = tf.math.unsorted_segment_mean(
            features,
            segment_ids=point_cloud._batch_ids,
            num_segments=point_cloud._batch_size)
        if return_padded:
            shape = tf.concat((point_cloud._batch_shape, [-1]), axis=0)
            features = tf.reshape(features, shape)
        return features
コード例 #3
0
    def __call__(self,
                 pool_op,
                 features,
                 point_cloud_in: PointCloud,
                 point_cloud_out: PointCloud,
                 pooling_radius,
                 return_sorted=False,
                 return_padded=False,
                 name=None,
                 default_name="custom pooling"):
        """ Computes a local pooling between two point clouds specified by `pool_op`.

    Note:
      In the following, `A1` to `An` are optional batch dimensions.

    Args:
      pool_op: A function of type `tf.math.unsorted_segmented_*`.
      features: A `float` `Tensor` of shape `[N_in, C]` or
        `[A1, ..., An, V_in, C]`.
      point_cloud_in: A `PointCloud` instance on which the features are
        defined.
      point_cloud_out: A `PointCloud` instance, on which the output features
        are defined.
      pooling_radius: A `float` or a `float` `Tensor` of shape `[D]`.
      return_sorted: A `bool`, if 'True' the output tensor is sorted
        according to the sorted batch ids of `point_cloud_out`.
      return_padded: A `bool`, if 'True' the output tensor is sorted and
        zero padded.

    Returns:
      A `float` `Tensor` of shape
        `[N_out, C]`, if `return_padded` is `False`
      or
        `[A1, ..., An, V_out, C]`, if `return_padded` is `True`.

    """
        features = tf.convert_to_tensor(value=features)
        features = _flatten_features(features, point_cloud_in)
        pooling_radius = tf.convert_to_tensor(value=pooling_radius,
                                              dtype=tf.float32)
        if pooling_radius.shape[0] == 1:
            pooling_radius = tf.repeat(pooling_radius,
                                       point_cloud_in._dimension)

        # Compute the grid.
        grid_in = Grid(point_cloud_in, pooling_radius)

        # Compute the neighborhood keys.
        neigh = Neighborhood(grid_in, pooling_radius, point_cloud_out)
        features_on_neighbors = tf.gather(features,
                                          neigh._original_neigh_ids[:, 0])

        # Pool the features in the neighborhoods
        features_out = pool_op(data=features_on_neighbors,
                               segment_ids=neigh._original_neigh_ids[:, 1],
                               num_segments=tf.shape(
                                   point_cloud_out._points)[0])
        return _format_output(features_out, point_cloud_out, return_sorted,
                              return_padded)
コード例 #4
0
    def __call__(self,
                 features,
                 point_cloud_in: PointCloud,
                 point_cloud_out: PointCloud,
                 radius,
                 neighborhood=None,
                 bandwidth=0.2,
                 return_sorted=False,
                 return_padded=False,
                 name=None):
        """ Computes the Monte-Carlo Convolution between two point clouds.

    Note:
      In the following, `A1` to `An` are optional batch dimensions.
      `C_in` is the number of input features.
      `C_out` is the number of output features.

    Args:
      features: A `float` `Tensor` of shape `[N_in, C_in]` or
        `[A1, ..., An,V, C_in]`.
      point_cloud_in: A 'PointCloud' instance, on which the features are
        defined.
      point_cloud_out: A `PointCloud` instance, on which the output
        features are defined.
      radius: A `float`, the convolution radius.
      neighborhood: A `Neighborhood` instance, defining the neighborhood
        with centers from `point_cloud_out` and neighbors in `point_cloud_in`.
        If `None` it is computed internally. (optional)
      bandwidth: A `float`, the bandwidth used in the kernel density
        estimation on the input point cloud. (optional)
      return_sorted: A `boolean`, if `True` the output tensor is sorted
        according to the batch_ids. (optional)
      return_padded: A `bool`, if 'True' the output tensor is sorted and
        zero padded. (optional)

    Returns:
      A `float` `Tensor` of shape
        `[N_out, C_out]`, if `return_padded` is `False`
      or
        `[A1, ..., An, V_out, C_out]`, if `return_padded` is `True`.

    """

        features = tf.cast(tf.convert_to_tensor(value=features),
                           dtype=tf.float32)

        tf.assert_equal(tf.shape(features)[-1], self._num_features_in)

        features = _flatten_features(features, point_cloud_in)

        #Create the radii tensor.
        radius = tf.reshape(
            tf.convert_to_tensor(value=radius, dtype=tf.float32), [1, 1])
        radii_tensor = tf.repeat(radius, self._num_dims)
        #Create the bandwidth tensor.
        bwTensor = tf.repeat(bandwidth, self._num_dims)

        if neighborhood is None:
            #Compute the grid
            grid = Grid(point_cloud_in, radii_tensor)
            #Compute the neighborhoods
            neigh = Neighborhood(grid, radii_tensor, point_cloud_out)
        else:
            neigh = neighborhood
        pdf = neigh.get_pdf(bandwidth=bwTensor, mode=KDEMode.constant)

        #Compute kernel inputs.
        neigh_point_coords = tf.gather(point_cloud_in._points,
                                       neigh._original_neigh_ids[:, 0])
        center_point_coords = tf.gather(point_cloud_out._points,
                                        neigh._original_neigh_ids[:, 1])
        points_diff = (neigh_point_coords - center_point_coords) / \
            tf.reshape(radii_tensor, [1, self._num_dims])

        #Compute Monte-Carlo convolution
        convolution_result = self._monte_carlo_conv(points_diff, neigh, pdf,
                                                    features,
                                                    self._non_linearity_type)

        return _format_output(convolution_result, point_cloud_out,
                              return_sorted, return_padded)
コード例 #5
0
  def __call__(self,
               features,
               point_cloud_in: PointCloud,
               point_cloud_out: PointCloud,
               conv_radius,
               neighborhood=None,
               kernel_influence_dist=None,
               return_sorted=False,
               return_padded=False,
               name=None):
    """ Computes the Kernel Point Convolution between two point clouds.

    Note:
      In the following, `A1` to `An` are optional batch dimensions.
      `C_in` is the number of input features.
      `C_out` is the number of output features.

    Args:
      features: A `float` `Tensor` of shape `[N1, C_in]` or
        `[A1, ..., An,V, C_in]`.
      point_cloud_in: A 'PointCloud' instance, on which the features are
        defined.
      point_cloud_out: A `PointCloud` instance, on which the output
        features are defined.
      conv_radius: A `float`, the convolution radius.
      neighborhood: A `Neighborhood` instance, defining the neighborhood
        with centers from `point_cloud_out` and neighbors in `point_cloud_in`.
        If `None` it is computed internally. (optional)
      kernel_influence_dist = A `float`, the influence distance of the kernel
        points. If `None` uses `conv_radius / 2.5`, as suggested in Section 3.3
        of the paper. (optional)
      return_sorted: A `boolean`, if `True` the output tensor is sorted
        according to the batch_ids. (optional)
      return_padded: A `bool`, if 'True' the output tensor is sorted and
        zero padded. (optional)

    Returns:
      A `float` `Tensor` of shape
        `[N2, C_out]`, if `return_padded` is `False`
      or
        `[A1, ..., An, V_out, C_out]`, if `return_padded` is `True`.

    """

    features = tf.cast(tf.convert_to_tensor(value=features),
                       dtype=tf.float32)
    features = _flatten_features(features, point_cloud_in)
    self._num_output_points = point_cloud_out._points.shape[0]

    if kernel_influence_dist is None:
      # normalized
      self._sigma = tf.constant(1.0)
    else:
      self._sigma = tf.convert_to_tensor(
        value=kernel_influence_dist / conv_radius, dtype=tf.float32)
    #Create the radii tensor.
    conv_radius = tf.reshape(tf.convert_to_tensor(value=conv_radius,
                                                  dtype=tf.float32),
                             [1, 1])
    radii_tensor = tf.repeat(conv_radius, self._num_dims)

    if neighborhood is None:
      #Compute the grid
      grid = Grid(point_cloud_in, radii_tensor)
      #Compute the neighborhoods
      neigh = Neighborhood(grid, radii_tensor, point_cloud_out)
    else:
      neigh = neighborhood

    #Compute kernel inputs.
    neigh_point_coords = tf.gather(
        point_cloud_in._points, neigh._original_neigh_ids[:, 0])
    center_point_coords = tf.gather(
        point_cloud_out._points, neigh._original_neigh_ids[:, 1])
    points_diff = (neigh_point_coords - center_point_coords) / \
        tf.reshape(radii_tensor, [1, self._num_dims])
    #Compute Monte-Carlo convolution
    convolution_result = self._kp_conv(points_diff, neigh, features)
    return _format_output(convolution_result,
                          point_cloud_out,
                          return_sorted,
                          return_padded)