Beispiel #1
0
 def test_tensor_fail2(self, tensor, shape, wrong_dtype, device):
     with pytest.raises(
             TypeError,
             match="tensor dtype is torch.float32, should be torch.int64"):
         testing.check_tensor(tensor, shape, wrong_dtype, device)
     assert not testing.check_tensor(
         tensor, shape, wrong_dtype, device, throw=False)
Beispiel #2
0
 def test_tensor_fail1(self, tensor, wrong_shape, dtype, device):
     with pytest.raises(
             ValueError,
             match=
             r"tensor shape is torch.Size\(\[4, 4\]\), should be \(3, 3\)"):
         testing.check_tensor(tensor, wrong_shape, dtype, device)
     assert not testing.check_tensor(
         tensor, wrong_shape, dtype, device, throw=False)
Beispiel #3
0
    def test_module_conv3d(self, height, width, depth, in_channels,
                           out_channels, with_bias, octrees, lengths,
                           coalescent_features, max_level, pyramids, exsum,
                           point_hierarchies, kernel_vectors, jump,
                           with_spc_to_dict):
        conv = spc.Conv3d(in_channels,
                          out_channels,
                          kernel_vectors,
                          jump,
                          bias=with_bias).cuda()
        params = dict(conv.named_parameters())
        weight = params['weight']
        check_tensor(weight,
                     shape=(kernel_vectors.shape[0], in_channels,
                            out_channels),
                     dtype=torch.float,
                     device='cuda')
        if with_bias:
            assert len(params) == 2
            bias = params['bias']
            check_tensor(bias,
                         shape=(out_channels, ),
                         dtype=torch.float,
                         device='cuda')
        else:
            assert len(params) == 1
            bias = None

        buffers = dict(conv.named_buffers())
        assert len(buffers) == 1
        assert torch.equal(buffers['kernel_vectors'], kernel_vectors)

        assert repr(conv) == f'Conv3d(in={in_channels}, out={out_channels}, ' \
                             f'kernel_vector_size={kernel_vectors.shape[0]})'

        if with_spc_to_dict:
            input_spc = Spc(octrees, lengths)
            output, output_level = conv(**input_spc.to_dict(),
                                        level=max_level,
                                        input=coalescent_features)
        else:
            output, output_level = conv(octrees, point_hierarchies, max_level,
                                        pyramids, exsum, coalescent_features)

        expected_output, expected_output_level = spc.conv3d(
            octrees,
            point_hierarchies,
            max_level,
            pyramids,
            exsum,
            coalescent_features,
            weight,
            kernel_vectors,
            jump=jump,
            bias=bias)
        assert torch.equal(output, expected_output)
        assert output_level == expected_output_level
Beispiel #4
0
    def test_sparse_1d_texture_mapping(self, sparse_coords_batch, texture_map_1d, mode):
        interop = texture_mapping(texture_coordinates=sparse_coords_batch, texture_maps=texture_map_1d, mode=mode)

        if mode == 'nearest':
            expected = torch.tensor([[41, 15, 11, 33], [133, 111, 115, 141]]).unsqueeze(-1)
        elif mode == 'bilinear':
            expected = torch.tensor([[41, 15, 11, 28], [128, 111, 115, 141]]).unsqueeze(-1)
        expected = expected.to(texture_map_1d.device).type(texture_map_1d.dtype)
        assert check_tensor(interop, shape=(2,4,1), dtype=texture_map_1d.dtype)
        assert torch.equal(interop, expected)
Beispiel #5
0
 def test_sparse_3d_texture_mapping(self, sparse_coords_batch, texture_map_3d, mode):
     interop = texture_mapping(texture_coordinates=sparse_coords_batch,
                               texture_maps=texture_map_3d,
                               mode=mode)
     if mode == 'nearest':
         expected_d1 = torch.tensor([[41, 15, 11, 33], [133, 111, 115, 141]])
         expected_d2 = -torch.tensor([[41, 15, 11, 33], [133, 111, 115, 141]])
         expected_d3 = torch.tensor([[41, 15, 11, 33], [133, 111, 115, 141]])
         expected = torch.stack([expected_d1, expected_d2, expected_d3], dim=-1)
     elif mode == 'bilinear':
         expected_d1 = torch.tensor([[41, 15, 11, 28], [128, 111, 115, 141]])
         expected_d2 = -torch.tensor([[41, 15, 11, 28], [128, 111, 115, 141]])
         expected_d3 = torch.tensor([[41, 15, 11, 28], [128, 111, 115, 141]])
         expected = torch.stack([expected_d1, expected_d2, expected_d3], dim=-1)
     expected = expected.to(texture_map_3d.device).type(texture_map_3d.dtype)
     assert check_tensor(interop, shape=(2,4,3), dtype=texture_map_3d.dtype)
     assert torch.equal(interop, expected)
Beispiel #6
0
    def test_sample_points(self, vertices, faces, device, dtype):
        batch_size, num_vertices = vertices.shape[:2]
        num_faces = faces.shape[0]
        num_samples = 1000

        points, face_choices = mesh.sample_points(vertices, faces, num_samples)

        check_tensor(points,
                     shape=(batch_size, num_samples, 3),
                     dtype=dtype,
                     device=device)
        check_tensor(face_choices,
                     shape=(batch_size, num_samples),
                     dtype=torch.long,
                     device=device)

        # check that all faces are sampled
        num_0 = torch.sum(face_choices == 0, dim=1)
        assert torch.all(num_0 +
                         torch.sum(face_choices == 1, dim=1) == num_samples)
        sampling_prob = num_samples / 3.
        tolerance = sampling_prob * 0.1
        assert torch.all(num_0 < sampling_prob + tolerance) and \
               torch.all(num_0 > sampling_prob - tolerance)

        face_vertices = mesh.index_vertices_by_faces(vertices, faces)

        face_vertices_choices = torch.gather(
            face_vertices, 1, face_choices[:, :, None,
                                           None].repeat(1, 1, 3, 3))

        # compute distance from the point to the plan of the face picked
        face_normals = mesh.face_normals(face_vertices_choices, unit=True)

        v0_p = points - face_vertices_choices[:, :,
                                              0]  # batch_size x num_points x 3
        len_v0_p = torch.sqrt(torch.sum(v0_p**2, dim=-1))
        cos_a = torch.matmul(v0_p.reshape(-1, 1, 3),
                             face_normals.reshape(-1, 3, 1)).reshape(
                                 batch_size, num_samples) / len_v0_p
        point_to_face_dist = len_v0_p * cos_a

        if dtype == torch.half:
            atol = 1e-2
            rtol = 1e-3
        else:
            atol = 1e-4
            rtol = 1e-5

        # check that the point is close to the plan
        assert torch.allclose(point_to_face_dist,
                              torch.zeros((batch_size, num_samples),
                                          device=device,
                                          dtype=dtype),
                              atol=atol,
                              rtol=rtol)

        # check that the point lie in the triangle
        edges0 = face_vertices_choices[:, :, 1] - face_vertices_choices[:, :,
                                                                        0]
        edges1 = face_vertices_choices[:, :, 2] - face_vertices_choices[:, :,
                                                                        1]
        edges2 = face_vertices_choices[:, :, 0] - face_vertices_choices[:, :,
                                                                        2]

        v0_p = points - face_vertices_choices[:, :, 0]
        v1_p = points - face_vertices_choices[:, :, 1]
        v2_p = points - face_vertices_choices[:, :, 2]

        # Normals of the triangle formed by an edge and the point
        normals1 = torch.cross(edges0, v0_p)
        normals2 = torch.cross(edges1, v1_p)
        normals3 = torch.cross(edges2, v2_p)
        # cross-product of those normals with the face normals must be positive
        margin = -5e-3 if dtype == torch.half else 0.
        assert torch.all(
            torch.matmul(normals1.reshape(-1, 1, 3),
                         face_normals.reshape(-1, 3, 1)) >= margin)
        assert torch.all(
            torch.matmul(normals2.reshape(-1, 1, 3),
                         face_normals.reshape(-1, 3, 1)) >= margin)
        assert torch.all(
            torch.matmul(normals3.reshape(-1, 1, 3),
                         face_normals.reshape(-1, 3, 1)) >= margin)
Beispiel #7
0
    def test_packed_sample_points(self, packed_vertices_info,
                                  packed_faces_info, device, dtype):
        vertices, first_idx_vertices = packed_vertices_info
        faces, num_faces_per_mesh = packed_faces_info

        total_num_vertices = vertices.shape[0]
        total_num_faces = faces.shape[0]
        batch_size = num_faces_per_mesh.shape[0]
        num_samples = 1000

        points, face_choices = mesh.packed_sample_points(
            vertices, first_idx_vertices, faces, num_faces_per_mesh,
            num_samples)

        check_tensor(points,
                     shape=(batch_size, num_samples, 3),
                     dtype=dtype,
                     device=device)
        check_tensor(face_choices,
                     shape=(batch_size, num_samples),
                     dtype=torch.long,
                     device=device)

        # check that all faces are sampled
        assert torch.all(face_choices[1] == 2)
        num_0 = torch.sum(face_choices[0] == 0)
        assert num_0 + torch.sum(face_choices[0] == 1) == num_samples
        sampling_prob = num_samples / 3.
        tolerance = sampling_prob * 0.1
        assert (num_0 < sampling_prob + tolerance) and \
               (num_0 > sampling_prob - tolerance)

        merged_faces = faces + tile_to_packed(
            first_idx_vertices[:-1].to(vertices.device), num_faces_per_mesh)

        face_vertices = torch.index_select(vertices, 0,
                                           merged_faces.reshape(-1)).reshape(
                                               total_num_faces, 3, 3)

        face_vertices_choices = torch.gather(
            face_vertices, 0,
            face_choices.reshape(-1, 1,
                                 1).repeat(1, 3,
                                           3)).reshape(batch_size, num_samples,
                                                       3, 3)

        # compute distance from the point to the plan of the face picked
        face_normals = mesh.face_normals(face_vertices_choices, unit=True)
        v0_p = points - face_vertices_choices[:, :,
                                              0]  # batch_size x num_points x 3
        len_v0_p = torch.sqrt(torch.sum(v0_p**2, dim=-1))
        cos_a = torch.matmul(v0_p.reshape(-1, 1, 3),
                             face_normals.reshape(-1, 3, 1)).reshape(
                                 batch_size, num_samples) / len_v0_p
        point_to_face_dist = len_v0_p * cos_a

        if dtype == torch.half:
            atol = 1e-2
            rtol = 1e-3
        else:
            atol = 1e-4
            rtol = 1e-5

        # check that the point is close to the plan
        assert torch.allclose(point_to_face_dist,
                              torch.zeros((batch_size, num_samples),
                                          device=device,
                                          dtype=dtype),
                              atol=atol,
                              rtol=rtol)

        # check that the point lie in the triangle
        edges0 = face_vertices_choices[:, :, 1] - face_vertices_choices[:, :,
                                                                        0]
        edges1 = face_vertices_choices[:, :, 2] - face_vertices_choices[:, :,
                                                                        1]
        edges2 = face_vertices_choices[:, :, 0] - face_vertices_choices[:, :,
                                                                        2]

        v0_p = points - face_vertices_choices[:, :, 0]
        v1_p = points - face_vertices_choices[:, :, 1]
        v2_p = points - face_vertices_choices[:, :, 2]

        # Normals of the triangle formed by an edge and the point
        normals1 = torch.cross(edges0, v0_p)
        normals2 = torch.cross(edges1, v1_p)
        normals3 = torch.cross(edges2, v2_p)
        # cross-product of those normals with the face normals must be positive
        margin = -2e-3 if dtype == torch.half else 0.
        assert torch.all(
            torch.matmul(normals1.reshape(-1, 1, 3),
                         face_normals.reshape(-1, 3, 1)) >= margin)
        assert torch.all(
            torch.matmul(normals2.reshape(-1, 1, 3),
                         face_normals.reshape(-1, 3, 1)) >= margin)
        assert torch.all(
            torch.matmul(normals3.reshape(-1, 1, 3),
                         face_normals.reshape(-1, 3, 1)) >= margin)
Beispiel #8
0
def test_random_tensor(low, high, shape, dtype, device):
    tensor = random_tensor(low, high, shape, dtype, device)
    check_tensor(tensor, shape, dtype, device)
    assert (low <= tensor).all()
    assert (tensor <= high).all()
Beispiel #9
0
 def test_tensor_fail3(self, tensor, shape, dtype, wrong_device):
     with pytest.raises(TypeError,
                        match="tensor device is cpu, should be cuda"):
         testing.check_tensor(tensor, shape, dtype, wrong_device)
     assert not testing.check_tensor(
         tensor, shape, dtype, wrong_device, throw=False)
Beispiel #10
0
 def test_tensor_default_success(self, tensor):
     assert testing.check_tensor(tensor)
Beispiel #11
0
 def test_tensor_partial_shape_success(self, tensor, partial_shape, dtype,
                                       device):
     assert testing.check_tensor(tensor, partial_shape, dtype, device)
Beispiel #12
0
 def test_tensor_success(self, tensor, shape, dtype, device):
     assert testing.check_tensor(tensor, shape, dtype, device)
Beispiel #13
0
    def test_sample_points(self, vertices, faces, face_features, use_features,
                           device, dtype):
        batch_size, num_vertices = vertices.shape[:2]
        num_faces = faces.shape[0]
        num_samples = 1000

        if use_features:
            points, face_choices, interpolated_features = mesh.sample_points(
                vertices, faces, num_samples, face_features=face_features)
        else:
            points, face_choices = mesh.sample_points(vertices, faces,
                                                      num_samples)

        check_tensor(points,
                     shape=(batch_size, num_samples, 3),
                     dtype=dtype,
                     device=device)
        check_tensor(face_choices,
                     shape=(batch_size, num_samples),
                     dtype=torch.long,
                     device=device)

        # check that all faces are sampled
        num_0 = torch.sum(face_choices == 0, dim=1)
        assert torch.all(num_0 +
                         torch.sum(face_choices == 1, dim=1) == num_samples)
        sampling_prob = num_samples / 2
        tolerance = sampling_prob * 0.2
        assert torch.all(num_0 < sampling_prob + tolerance) and \
               torch.all(num_0 > sampling_prob - tolerance)

        face_vertices = mesh.index_vertices_by_faces(vertices, faces)

        face_vertices_choices = torch.gather(
            face_vertices, 1, face_choices[:, :, None,
                                           None].repeat(1, 1, 3, 3))

        # compute distance from the point to the plan of the face picked
        face_normals = mesh.face_normals(face_vertices_choices, unit=True)

        v0_p = points - face_vertices_choices[:, :,
                                              0]  # batch_size x num_points x 3
        len_v0_p = torch.sqrt(torch.sum(v0_p**2, dim=-1))
        cos_a = torch.matmul(v0_p.reshape(-1, 1, 3),
                             face_normals.reshape(-1, 3, 1)).reshape(
                                 batch_size, num_samples) / len_v0_p
        point_to_face_dist = len_v0_p * cos_a

        if dtype == torch.half:
            atol = 1e-2
            rtol = 1e-3
        else:
            atol = 1e-4
            rtol = 1e-5

        # check that the point is close to the plan
        assert torch.allclose(point_to_face_dist,
                              torch.zeros((batch_size, num_samples),
                                          device=device,
                                          dtype=dtype),
                              atol=atol,
                              rtol=rtol)

        # check that the point lie in the triangle
        edges0 = face_vertices_choices[:, :, 1] - face_vertices_choices[:, :,
                                                                        0]
        edges1 = face_vertices_choices[:, :, 2] - face_vertices_choices[:, :,
                                                                        1]
        edges2 = face_vertices_choices[:, :, 0] - face_vertices_choices[:, :,
                                                                        2]

        v0_p = points - face_vertices_choices[:, :, 0]
        v1_p = points - face_vertices_choices[:, :, 1]
        v2_p = points - face_vertices_choices[:, :, 2]

        # Normals of the triangle formed by an edge and the point
        normals1 = torch.cross(edges0, v0_p)
        normals2 = torch.cross(edges1, v1_p)
        normals3 = torch.cross(edges2, v2_p)
        # cross-product of those normals with the face normals must be positive
        margin = -5e-3 if dtype == torch.half else 0.
        assert torch.all(
            torch.matmul(normals1.reshape(-1, 1, 3),
                         face_normals.reshape(-1, 3, 1)) >= margin)
        assert torch.all(
            torch.matmul(normals2.reshape(-1, 1, 3),
                         face_normals.reshape(-1, 3, 1)) >= margin)
        assert torch.all(
            torch.matmul(normals3.reshape(-1, 1, 3),
                         face_normals.reshape(-1, 3, 1)) >= margin)
        if use_features:
            feat_dim = face_features.shape[-1]
            check_tensor(interpolated_features,
                         shape=(batch_size, num_samples, feat_dim),
                         dtype=dtype,
                         device=device)
            # face_vertices_choices (batch_size, num_samples, 3, 3)
            # points (batch_size, num_samples, 3)
            ax = face_vertices_choices[:, :, 0, 0]
            ay = face_vertices_choices[:, :, 0, 1]
            bx = face_vertices_choices[:, :, 1, 0]
            by = face_vertices_choices[:, :, 1, 1]
            cx = face_vertices_choices[:, :, 2, 0]
            cy = face_vertices_choices[:, :, 2, 1]
            m = bx - ax
            p = by - ay
            n = cx - ax
            q = cy - ay
            s = points[:, :, 0] - ax
            t = points[:, :, 1] - ay

            # sum_weights = torch.sum(weights, dim=-1)
            # zeros_idxs = torch.where(sum_weights == 0)
            #weights = weights / torch.sum(weights, keepdims=True, dim=-1)
            k1 = s * q - n * t
            k2 = m * t - s * p
            k3 = m * q - n * p
            w1 = k1 / (k3 + 1e-7)
            w2 = k2 / (k3 + 1e-7)
            w0 = (1. - w1) - w2
            weights = torch.stack([w0, w1, w2], dim=-1)

            gt_points = torch.sum(face_vertices_choices *
                                  weights.unsqueeze(-1),
                                  dim=-2)
            assert torch.allclose(points, gt_points, atol=atol, rtol=rtol)

            _face_choices = face_choices[..., None,
                                         None].repeat(1, 1, 3, feat_dim)
            face_features_choices = torch.gather(face_features, 1,
                                                 _face_choices)

            gt_interpolated_features = torch.sum(face_features_choices *
                                                 weights.unsqueeze(-1),
                                                 dim=-2)
            assert torch.allclose(interpolated_features,
                                  gt_interpolated_features,
                                  atol=atol,
                                  rtol=rtol)
Beispiel #14
0
    def test_module_conv_transpose3d(self, height, width, depth, in_channels,
                                     out_channels, with_bias, octrees, lengths,
                                     max_level, pyramids, exsum,
                                     point_hierarchies, kernel_size,
                                     kernel_vectors, jump, with_spc_to_dict):
        stride = 2**jump

        if stride > kernel_size:
            pytest.skip('stride higher than kernel_size is not tested')

        in_level = max_level - jump
        in_num_nodes = torch.sum(pyramids[:, 0, -(2 + jump)])
        coalescent_features = torch.rand((in_num_nodes, in_channels),
                                         device='cuda',
                                         requires_grad=True)

        conv = spc.ConvTranspose3d(in_channels,
                                   out_channels,
                                   kernel_vectors,
                                   jump,
                                   bias=with_bias).cuda()
        params = dict(conv.named_parameters())
        weight = params['weight']
        check_tensor(weight,
                     shape=(kernel_vectors.shape[0], in_channels,
                            out_channels),
                     dtype=torch.float,
                     device='cuda')
        if with_bias:
            assert len(params) == 2
            bias = params['bias']
            check_tensor(bias,
                         shape=(out_channels, ),
                         dtype=torch.float,
                         device='cuda')
        else:
            assert len(params) == 1
            bias = None

        buffers = dict(conv.named_buffers())
        assert len(buffers) == 1
        assert torch.equal(buffers['kernel_vectors'], kernel_vectors)

        assert repr(conv) == f'ConvTranspose3d(in={in_channels}, ' \
                             f'out={out_channels}, ' \
                             f'kernel_vector_size={kernel_vectors.shape[0]})'

        if with_spc_to_dict:
            input_spc = Spc(octrees, lengths)
            output, output_level = conv(**input_spc.to_dict(),
                                        level=in_level,
                                        input=coalescent_features)
        else:
            output, output_level = conv(octrees, point_hierarchies, in_level,
                                        pyramids, exsum, coalescent_features)

        expected_output, expected_output_level = spc.conv_transpose3d(
            octrees,
            point_hierarchies,
            in_level,
            pyramids,
            exsum,
            coalescent_features,
            weight,
            kernel_vectors,
            jump=jump,
            bias=bias)
        assert torch.equal(output, expected_output)
        assert output_level == expected_output_level