Пример #1
0
  def test_face_normals_preset(self, test_inputs, test_outputs):
    """Tests the computation of mesh face normals."""
    faces = normals.gather_faces(*test_inputs[:2])
    test_inputs = [faces] + list(test_inputs[2:])

    self.assert_output_is_correct(
        normals.face_normals, test_inputs, test_outputs, tile=False)
Пример #2
0
    def test_face_normals_random(self):
        """Tests the computation of mesh face normals in each axis."""
        tensor_vertex_size = np.random.randint(1, 3)
        tensor_out_shape = np.random.randint(1, 5, size=tensor_vertex_size)
        tensor_out_shape = tensor_out_shape.tolist()
        tensor_vertex_shape = list(tensor_out_shape)
        tensor_vertex_shape[-1] *= 3
        tensor_index_shape = tensor_out_shape[-1]

        for i in range(3):
            vertices = np.random.random(size=tensor_vertex_shape + [3])
            indices = np.arange(tensor_vertex_shape[-1])
            np.random.shuffle(indices)
            indices = np.reshape(indices,
                                 newshape=[1] * (tensor_vertex_size - 1) \
                                 + [tensor_index_shape, 3])
            indices = np.tile(indices, tensor_vertex_shape[:-1] + [1, 1])
            vertices[..., i] = 0.
            expected = np.zeros(shape=tensor_out_shape + [3],
                                dtype=vertices.dtype)
            expected[..., i] = 1.
            faces = normals.gather_faces(vertices, indices)

            self.assertAllClose(tf.abs(normals.face_normals(faces)),
                                expected,
                                rtol=1e-3)
Пример #3
0
    def test_face_normals_jacobian_random(self):
        """Test the Jacobian of the face normals function."""
        tensor_vertex_size = np.random.randint(1, 3)
        tensor_out_shape = np.random.randint(1, 5, size=tensor_vertex_size)
        tensor_out_shape = tensor_out_shape.tolist()
        tensor_vertex_shape = list(tensor_out_shape)
        tensor_vertex_shape[-1] *= 3
        tensor_index_shape = tensor_out_shape[-1]
        vertex_init = np.random.random(size=tensor_vertex_shape + [3])
        index_init = np.arange(tensor_vertex_shape[-1])
        np.random.shuffle(index_init)
        index_init = np.reshape(index_init, newshape=[1] * (tensor_vertex_size - 1) \
                                + [tensor_index_shape, 3])
        index_init = np.tile(index_init, tensor_vertex_shape[:-1] + [1, 1])
        vertex_tensor = tf.convert_to_tensor(value=vertex_init)
        index_tensor = tf.convert_to_tensor(value=index_init)

        face_tensor = normals.gather_faces(vertex_tensor, index_tensor)
        y = normals.face_normals(face_tensor)

        self.assert_jacobian_is_correct(vertex_tensor,
                                        vertex_init,
                                        y,
                                        atol=1e-4,
                                        delta=1e-9)
Пример #4
0
  def test_gather_faces_random(self):
    """Tests the extraction of mesh faces."""
    tensor_size = np.random.randint(3, 5)
    tensor_shape = np.random.randint(1, 5, size=tensor_size).tolist()
    vertices = np.random.random(size=tensor_shape)
    indices = np.arange(tensor_shape[-2])
    indices = indices.reshape([1] * (tensor_size - 1) + [-1])
    indices = np.tile(indices, tensor_shape[:-2] + [1, 1])
    expected = np.expand_dims(vertices, -3)

    self.assertAllClose(
        normals.gather_faces(vertices, indices), expected, rtol=1e-3)
Пример #5
0
    def test_gather_faces_jacobian_random(self):
        """Test the Jacobian of the face extraction function."""
        tensor_size = np.random.randint(2, 5)
        tensor_shape = np.random.randint(1, 5, size=tensor_size).tolist()
        vertex_init = np.random.random(size=tensor_shape)
        indices_init = np.random.randint(0,
                                         tensor_shape[-2],
                                         size=tensor_shape)
        vertex_tensor = tf.convert_to_tensor(value=vertex_init)
        indices_tensor = tf.convert_to_tensor(value=indices_init)

        y = normals.gather_faces(vertex_tensor, indices_tensor)

        self.assert_jacobian_is_correct(vertex_tensor, vertex_init, y)
Пример #6
0
def area_weighted_random_sample_triangle_mesh(vertex_attributes,
                                              faces,
                                              num_samples,
                                              vertex_positions=None,
                                              seed=None,
                                              stateless=False,
                                              name=None):
  """Performs a face area weighted random sampling of a tri mesh.

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

  Args:
    vertex_attributes: A `float` tensor of shape `[A1, ..., An, V, D]`, where V
      is the number of vertices, and D is dimensionality of a feature defined on
      each vertex. If `vertex_positions` is not provided, then first 3
      dimensions of `vertex_attributes` denote the vertex positions.
    faces: A `int` tensor of shape `[A1, ..., An, F, 3]`, where F is the number
      of faces.
    num_samples: An `int` scalar denoting number of samples to be drawn from
      each mesh.
    vertex_positions: An optional `float` tensor of shape `[A1, ..., An, V, 3]`,
      where V is the number of vertices. If None, then vertex_attributes[...,
        :3] is used as vertex positions.
    seed: Optional random seed.
    stateless: Optional flag to use stateless random sampler. If stateless=True,
      then seed must be provided as shape `[2]` int tensor. Stateless random
      sampling is useful for testing to generate same sequence across calls.
    name: Name for op. Defaults to "area_weighted_random_sample_triangle_mesh".

  Returns:
    sample_pts: A `float` tensor of shape `[A1, ..., An, num_samples, D]`,
      where D is dimensionality of each sampled point.
    sample_face_indices: A `int` tensor of shape `[A1, ..., An, num_samples]`.
  """
  with tf.compat.v1.name_scope(name,
                               "area_weighted_random_sample_triangle_mesh"):
    faces = tf.convert_to_tensor(value=faces)
    vertex_attributes = tf.convert_to_tensor(value=vertex_attributes)
    num_samples = tf.convert_to_tensor(value=num_samples)

    shape.check_static(
        tensor=vertex_attributes,
        tensor_name="vertex_attributes",
        has_rank_greater_than=1)
    shape.check_static(
        tensor=vertex_attributes,
        tensor_name="vertex_attributes",
        has_dim_greater_than=(-1, 2))

    if vertex_positions is not None:
      vertex_positions = tf.convert_to_tensor(value=vertex_positions)
    else:
      vertex_positions = vertex_attributes[..., :3]

    shape.check_static(
        tensor=vertex_positions,
        tensor_name="vertex_positions",
        has_rank_greater_than=1)
    shape.check_static(
        tensor=vertex_positions,
        tensor_name="vertex_positions",
        has_dim_equals=(-1, 3))

    triangle_vertex_positions = normals.gather_faces(vertex_positions, faces)
    triangle_areas = triangle_area(triangle_vertex_positions[..., 0, :],
                                   triangle_vertex_positions[..., 1, :],
                                   triangle_vertex_positions[..., 2, :])
    return weighted_random_sample_triangle_mesh(
        vertex_attributes,
        faces,
        num_samples,
        face_weights=triangle_areas,
        seed=seed,
        stateless=stateless)
Пример #7
0
 def gather_faces(vertex_tensor):
   return normals.gather_faces(vertex_tensor, indices_tensor)
Пример #8
0
 def face_normals(vertex_tensor):
   face_tensor = normals.gather_faces(vertex_tensor, index_tensor)
   return normals.face_normals(face_tensor)