Exemplo n.º 1
0
    def test_centers_for_image(self):
        maps = torch.rand(size=(1, 257, 129, 3))
        verts_uvs = torch.FloatTensor([[[0.25, 0.125], [0.5, 0.625], [0.5, 0.5]]])
        faces_uvs = torch.zeros(size=(1, 0, 3), dtype=torch.int64)
        tex = TexturesUV(maps=maps, faces_uvs=faces_uvs, verts_uvs=verts_uvs)

        expected = torch.FloatTensor([[32, 224], [64, 96], [64, 128]])
        self.assertClose(tex.centers_for_image(0), expected)
Exemplo n.º 2
0
 def test_clone(self):
     tex = TexturesUV(
         maps=torch.ones((5, 16, 16, 3)),
         faces_uvs=torch.rand(size=(5, 10, 3)),
         verts_uvs=torch.rand(size=(5, 15, 2)),
     )
     tex.faces_uvs_list()
     tex.verts_uvs_list()
     tex_cloned = tex.clone()
     self.assertSeparate(tex._faces_uvs_padded,
                         tex_cloned._faces_uvs_padded)
     self.assertClose(tex._faces_uvs_padded, tex_cloned._faces_uvs_padded)
     self.assertSeparate(tex._verts_uvs_padded,
                         tex_cloned._verts_uvs_padded)
     self.assertClose(tex._verts_uvs_padded, tex_cloned._verts_uvs_padded)
     self.assertSeparate(tex._maps_padded, tex_cloned._maps_padded)
     self.assertClose(tex._maps_padded, tex_cloned._maps_padded)
     self.assertSeparate(tex.valid, tex_cloned.valid)
     self.assertTrue(tex.valid.eq(tex_cloned.valid).all())
     for i in range(tex._N):
         self.assertSeparate(tex._faces_uvs_list[i],
                             tex_cloned._faces_uvs_list[i])
         self.assertClose(tex._faces_uvs_list[i],
                          tex_cloned._faces_uvs_list[i])
         self.assertSeparate(tex._verts_uvs_list[i],
                             tex_cloned._verts_uvs_list[i])
         self.assertClose(tex._verts_uvs_list[i],
                          tex_cloned._verts_uvs_list[i])
         # tex._maps_list is not use anywhere so it's not stored. We call it explicitly
         self.assertSeparate(tex.maps_list()[i], tex_cloned.maps_list()[i])
         self.assertClose(tex.maps_list()[i], tex_cloned.maps_list()[i])
Exemplo n.º 3
0
 def test_to(self):
     tex = TexturesUV(
         maps=torch.ones((5, 16, 16, 3)),
         faces_uvs=torch.randint(size=(5, 10, 3), high=15),
         verts_uvs=torch.rand(size=(5, 15, 2)),
     )
     device = torch.device("cuda:0")
     tex = tex.to(device)
     self.assertEqual(tex._faces_uvs_padded.device, device)
     self.assertEqual(tex._verts_uvs_padded.device, device)
     self.assertEqual(tex._maps_padded.device, device)
Exemplo n.º 4
0
 def test_clone(self):
     tex = TexturesUV(
         maps=torch.ones((5, 16, 16, 3)),
         faces_uvs=torch.rand(size=(5, 10, 3)),
         verts_uvs=torch.rand(size=(5, 15, 2)),
     )
     tex_cloned = tex.clone()
     self.assertSeparate(tex._faces_uvs_padded,
                         tex_cloned._faces_uvs_padded)
     self.assertSeparate(tex._verts_uvs_padded,
                         tex_cloned._verts_uvs_padded)
     self.assertSeparate(tex._maps_padded, tex_cloned._maps_padded)
     self.assertSeparate(tex.valid, tex_cloned.valid)
Exemplo n.º 5
0
 def test_detach(self):
     tex = TexturesUV(
         maps=torch.ones((5, 16, 16, 3), requires_grad=True),
         faces_uvs=torch.rand(size=(5, 10, 3)),
         verts_uvs=torch.rand(size=(5, 15, 2)),
     )
     tex.faces_uvs_list()
     tex.verts_uvs_list()
     tex_detached = tex.detach()
     self.assertFalse(tex_detached._maps_padded.requires_grad)
     self.assertClose(tex._maps_padded, tex_detached._maps_padded)
     self.assertFalse(tex_detached._verts_uvs_padded.requires_grad)
     self.assertClose(tex._verts_uvs_padded, tex_detached._verts_uvs_padded)
     self.assertFalse(tex_detached._faces_uvs_padded.requires_grad)
     self.assertClose(tex._faces_uvs_padded, tex_detached._faces_uvs_padded)
     for i in range(tex._N):
         self.assertFalse(tex_detached._verts_uvs_list[i].requires_grad)
         self.assertClose(tex._verts_uvs_list[i],
                          tex_detached._verts_uvs_list[i])
         self.assertFalse(tex_detached._faces_uvs_list[i].requires_grad)
         self.assertClose(tex._faces_uvs_list[i],
                          tex_detached._faces_uvs_list[i])
         # tex._maps_list is not use anywhere so it's not stored. We call it explicitly
         self.assertFalse(tex_detached.maps_list()[i].requires_grad)
         self.assertClose(tex.maps_list()[i], tex_detached.maps_list()[i])
Exemplo n.º 6
0
    def test_getitem(self):
        N = 5
        V = 20
        F = 10
        source = {
            "maps": torch.rand(size=(N, 1, 1, 3)),
            "faces_uvs": torch.randint(size=(N, F, 3), high=V),
            "verts_uvs": torch.randn(size=(N, V, 2)),
        }
        tex = TexturesUV(
            maps=source["maps"],
            faces_uvs=source["faces_uvs"],
            verts_uvs=source["verts_uvs"],
        )

        verts = torch.rand(size=(N, V, 3))
        faces = torch.randint(size=(N, F, 3), high=V)
        meshes = Meshes(verts=verts, faces=faces, textures=tex)

        tryindex(self, 2, tex, meshes, source)
        tryindex(self, slice(0, 2, 1), tex, meshes, source)
        index = torch.tensor([1, 0, 1, 0, 0], dtype=torch.bool)
        tryindex(self, index, tex, meshes, source)
        index = torch.tensor([0, 0, 0, 0, 0], dtype=torch.bool)
        tryindex(self, index, tex, meshes, source)
        index = torch.tensor([1, 2], dtype=torch.int64)
        tryindex(self, index, tex, meshes, source)
        tryindex(self, [2, 4], tex, meshes, source)
Exemplo n.º 7
0
    def test_extend(self):
        B = 5
        mesh = init_mesh(B, 30, 50)
        V = mesh._V
        num_faces = mesh.num_faces_per_mesh()
        num_verts = mesh.num_verts_per_mesh()
        faces_uvs_list = [
            torch.randint(size=(f, 3), low=0, high=V) for f in num_faces
        ]
        verts_uvs_list = [torch.rand(v, 2) for v in num_verts]
        tex_uv = TexturesUV(
            maps=torch.ones((B, 16, 16, 3)),
            faces_uvs=faces_uvs_list,
            verts_uvs=verts_uvs_list,
        )
        tex_mesh = Meshes(verts=mesh.verts_list(),
                          faces=mesh.faces_list(),
                          textures=tex_uv)
        N = 2
        new_mesh = tex_mesh.extend(N)

        self.assertEqual(len(tex_mesh) * N, len(new_mesh))

        tex_init = tex_mesh.textures
        new_tex = new_mesh.textures

        new_tex_num_verts = new_mesh.num_verts_per_mesh()
        for i in range(len(tex_mesh)):
            for n in range(N):
                tex_nv = new_tex_num_verts[i * N + n]
                self.assertClose(
                    # The original textures were initialized using
                    # verts uvs list
                    tex_init.verts_uvs_list()[i],
                    # In the new textures, the verts_uvs are initialized
                    # from padded. The verts per mesh are not used to
                    # convert from padded to list. See TexturesUV for an
                    # explanation.
                    new_tex.verts_uvs_list()[i * N + n][:tex_nv, ...],
                )
                self.assertClose(tex_init.faces_uvs_list()[i],
                                 new_tex.faces_uvs_list()[i * N + n])
                self.assertClose(tex_init.maps_padded()[i, ...],
                                 new_tex.maps_padded()[i * N + n])
                self.assertClose(
                    tex_init._num_faces_per_mesh[i],
                    new_tex._num_faces_per_mesh[i * N + n],
                )

        self.assertAllSeparate([
            tex_init.faces_uvs_padded(),
            new_tex.faces_uvs_padded(),
            tex_init.verts_uvs_padded(),
            new_tex.verts_uvs_padded(),
            tex_init.maps_padded(),
            new_tex.maps_padded(),
        ])

        with self.assertRaises(ValueError):
            tex_mesh.extend(N=-1)
Exemplo n.º 8
0
    def test_extend(self):
        B = 5
        mesh = TestMeshes.init_mesh(B, 30, 50)
        V = mesh._V
        num_faces = mesh.num_faces_per_mesh()
        num_verts = mesh.num_verts_per_mesh()
        faces_uvs_list = [
            torch.randint(size=(f, 3), low=0, high=V) for f in num_faces
        ]
        verts_uvs_list = [torch.rand(v, 2) for v in num_verts]
        tex_uv = TexturesUV(
            maps=torch.ones((B, 16, 16, 3)),
            faces_uvs=faces_uvs_list,
            verts_uvs=verts_uvs_list,
        )
        tex_mesh = Meshes(verts=mesh.verts_list(),
                          faces=mesh.faces_list(),
                          textures=tex_uv)
        N = 2
        new_mesh = tex_mesh.extend(N)

        self.assertEqual(len(tex_mesh) * N, len(new_mesh))

        tex_init = tex_mesh.textures
        new_tex = new_mesh.textures

        for i in range(len(tex_mesh)):
            for n in range(N):
                self.assertClose(tex_init.verts_uvs_list()[i],
                                 new_tex.verts_uvs_list()[i * N + n])
                self.assertClose(tex_init.faces_uvs_list()[i],
                                 new_tex.faces_uvs_list()[i * N + n])
                self.assertClose(tex_init.maps_padded()[i, ...],
                                 new_tex.maps_padded()[i * N + n])
                self.assertClose(
                    tex_init._num_faces_per_mesh[i],
                    new_tex._num_faces_per_mesh[i * N + n],
                )

        self.assertAllSeparate([
            tex_init.faces_uvs_padded(),
            new_tex.faces_uvs_padded(),
            tex_init.faces_uvs_packed(),
            new_tex.faces_uvs_packed(),
            tex_init.verts_uvs_padded(),
            new_tex.verts_uvs_padded(),
            tex_init.verts_uvs_packed(),
            new_tex.verts_uvs_packed(),
            tex_init.maps_padded(),
            new_tex.maps_padded(),
        ])

        with self.assertRaises(ValueError):
            tex_mesh.extend(N=-1)
Exemplo n.º 9
0
    def test_padded_to_packed(self):
        # Case where each face in the mesh has 3 unique uv vertex indices
        # - i.e. even if a vertex is shared between multiple faces it will
        # have a unique uv coordinate for each face.
        N = 2
        faces_uvs_list = [
            torch.tensor([[0, 1, 2], [3, 5, 4], [7, 6, 8]]),
            torch.tensor([[0, 1, 2], [3, 4, 5]]),
        ]  # (N, 3, 3)
        verts_uvs_list = [torch.ones(9, 2), torch.ones(6, 2)]

        num_faces_per_mesh = [f.shape[0] for f in faces_uvs_list]
        num_verts_per_mesh = [v.shape[0] for v in verts_uvs_list]
        tex = TexturesUV(
            maps=torch.ones((N, 16, 16, 3)),
            faces_uvs=faces_uvs_list,
            verts_uvs=verts_uvs_list,
        )

        # This is set inside Meshes when textures is passed as an input.
        # Here we set _num_faces_per_mesh and _num_verts_per_mesh explicity.
        tex1 = tex.clone()
        tex1._num_faces_per_mesh = num_faces_per_mesh
        tex1._num_verts_per_mesh = num_verts_per_mesh
        verts_list = tex1.verts_uvs_list()
        verts_padded = tex1.verts_uvs_padded()

        faces_list = tex1.faces_uvs_list()
        faces_padded = tex1.faces_uvs_padded()

        for f1, f2 in zip(faces_list, faces_uvs_list):
            self.assertTrue((f1 == f2).all().item())

        for f1, f2 in zip(verts_list, verts_uvs_list):
            self.assertTrue((f1 == f2).all().item())

        self.assertTrue(faces_padded.shape == (2, 3, 3))
        self.assertTrue(verts_padded.shape == (2, 9, 2))

        # Case where num_faces_per_mesh is not set and faces_verts_uvs
        # are initialized with a padded tensor.
        tex2 = TexturesUV(
            maps=torch.ones((N, 16, 16, 3)),
            verts_uvs=verts_padded,
            faces_uvs=faces_padded,
        )
        faces_list = tex2.faces_uvs_list()
        verts_list = tex2.verts_uvs_list()

        for i, (f1, f2) in enumerate(zip(faces_list, faces_uvs_list)):
            n = num_faces_per_mesh[i]
            self.assertTrue((f1[:n] == f2).all().item())

        for i, (f1, f2) in enumerate(zip(verts_list, verts_uvs_list)):
            n = num_verts_per_mesh[i]
            self.assertTrue((f1[:n] == f2).all().item())
Exemplo n.º 10
0
    def test_textures_uv_init_fail(self):
        # Maps has wrong shape
        with self.assertRaisesRegex(ValueError, "maps"):
            TexturesUV(
                maps=torch.ones((5, 16, 16, 3, 4)),
                faces_uvs=torch.rand(size=(5, 10, 3)),
                verts_uvs=torch.rand(size=(5, 15, 2)),
            )

        # faces_uvs has wrong shape
        with self.assertRaisesRegex(ValueError, "faces_uvs"):
            TexturesUV(
                maps=torch.ones((5, 16, 16, 3)),
                faces_uvs=torch.rand(size=(5, 10, 3, 3)),
                verts_uvs=torch.rand(size=(5, 15, 2)),
            )

        # verts_uvs has wrong shape
        with self.assertRaisesRegex(ValueError, "verts_uvs"):
            TexturesUV(
                maps=torch.ones((5, 16, 16, 3)),
                faces_uvs=torch.rand(size=(5, 10, 3)),
                verts_uvs=torch.rand(size=(5, 15, 2, 3)),
            )

        # verts has different batch dim to faces
        with self.assertRaisesRegex(ValueError, "verts_uvs"):
            TexturesUV(
                maps=torch.ones((5, 16, 16, 3)),
                faces_uvs=torch.rand(size=(5, 10, 3)),
                verts_uvs=torch.rand(size=(8, 15, 2)),
            )

        # maps has different batch dim to faces
        with self.assertRaisesRegex(ValueError, "maps"):
            TexturesUV(
                maps=torch.ones((8, 16, 16, 3)),
                faces_uvs=torch.rand(size=(5, 10, 3)),
                verts_uvs=torch.rand(size=(5, 15, 2)),
            )

        # verts on different device to faces
        with self.assertRaisesRegex(ValueError, "verts_uvs"):
            TexturesUV(
                maps=torch.ones((5, 16, 16, 3)),
                faces_uvs=torch.rand(size=(5, 10, 3)),
                verts_uvs=torch.rand(size=(5, 15, 2, 3), device="cuda"),
            )

        # maps on different device to faces
        with self.assertRaisesRegex(ValueError, "map"):
            TexturesUV(
                maps=torch.ones((5, 16, 16, 3), device="cuda"),
                faces_uvs=torch.rand(size=(5, 10, 3)),
                verts_uvs=torch.rand(size=(5, 15, 2)),
            )
Exemplo n.º 11
0
    def test_sample_textures_error(self):
        N = 1
        V = 20
        F = 10
        maps = torch.rand(size=(N, 1, 1, 3))
        verts_uvs = torch.randn(size=(N, V, 2))
        tex = TexturesUV(
            maps=maps,
            faces_uvs=torch.randint(size=(N, 15, 3), high=V),
            verts_uvs=verts_uvs,
        )
        verts = torch.rand(size=(5, V, 3))
        faces = torch.randint(size=(5, 10, 3), high=V)
        meshes = Meshes(verts=verts, faces=faces)

        # Wrong number of faces
        with self.assertRaisesRegex(ValueError, "do not match the dimensions"):
            Meshes(verts=verts, faces=faces, textures=tex)

        # Wrong batch dim for faces
        tex = TexturesUV(
            maps=maps,
            faces_uvs=torch.randint(size=(1, F, 3), high=V),
            verts_uvs=verts_uvs,
        )
        with self.assertRaisesRegex(ValueError, "do not match the dimensions"):
            Meshes(verts=verts, faces=faces, textures=tex)

        # Wrong batch dim for verts_uvs is not necessary to check as
        # there is already a check inside TexturesUV for a batch dim
        # mismatch with faces_uvs

        meshes = Meshes(verts=verts, faces=faces)
        meshes.textures = tex

        # Cannot use the texture attribute set on meshes for sampling
        # textures if the dimensions don't match
        with self.assertRaisesRegex(ValueError, "do not match the dimensions"):
            meshes.sample_textures(None)
Exemplo n.º 12
0
    def test_faces_verts_textures(self):
        device = torch.device("cuda:0")
        N, V, F, H, W = 2, 5, 12, 8, 8
        vert_uvs = torch.rand((N, V, 2), dtype=torch.float32, device=device)
        face_uvs = torch.randint(high=V,
                                 size=(N, F, 3),
                                 dtype=torch.int64,
                                 device=device)
        maps = torch.rand((N, H, W, 3), dtype=torch.float32, device=device)

        tex = TexturesUV(maps=maps, verts_uvs=vert_uvs, faces_uvs=face_uvs)

        # naive faces_verts_textures
        faces_verts_texs = []
        for n in range(N):
            temp = torch.zeros((F, 3, 3), device=device, dtype=torch.float32)
            for f in range(F):
                uv0 = vert_uvs[n, face_uvs[n, f, 0]]
                uv1 = vert_uvs[n, face_uvs[n, f, 1]]
                uv2 = vert_uvs[n, face_uvs[n, f, 2]]

                idx = torch.stack((uv0, uv1, uv2), dim=0).view(1, 1, 3,
                                                               2)  # 1x1x3x2
                idx = idx * 2.0 - 1.0
                imap = maps[n].view(1, H, W, 3).permute(0, 3, 1, 2)  # 1x3xHxW
                imap = torch.flip(imap, [2])

                texts = torch.nn.functional.grid_sample(
                    imap,
                    idx,
                    align_corners=tex.align_corners,
                    padding_mode=tex.padding_mode,
                )  # 1x3x1x3
                temp[f] = texts[0, :, 0, :].permute(1, 0)
            faces_verts_texs.append(temp)
        faces_verts_texs = torch.cat(faces_verts_texs, 0)

        self.assertClose(faces_verts_texs, tex.faces_verts_textures_packed())
Exemplo n.º 13
0
    def test_sample_textures_uv(self):
        barycentric_coords = torch.tensor([[0.5, 0.3, 0.2], [0.3, 0.6, 0.1]],
                                          dtype=torch.float32).view(
                                              1, 1, 1, 2, -1)
        dummy_verts = torch.zeros(4, 3)
        vert_uvs = torch.tensor([[1, 0], [0, 1], [1, 1], [0, 0]],
                                dtype=torch.float32)
        face_uvs = torch.tensor([[0, 1, 2], [1, 2, 3]], dtype=torch.int64)
        interpolated_uvs = torch.tensor(
            [[0.5 + 0.2, 0.3 + 0.2], [0.6, 0.3 + 0.6]], dtype=torch.float32)

        # Create a dummy texture map
        H = 2
        W = 2
        x = torch.linspace(0, 1, W).view(1, W).expand(H, W)
        y = torch.linspace(0, 1, H).view(H, 1).expand(H, W)
        tex_map = torch.stack([x, y], dim=2).view(1, H, W, 2)
        pix_to_face = torch.tensor([0, 1], dtype=torch.int64).view(1, 1, 1, 2)
        fragments = Fragments(
            pix_to_face=pix_to_face,
            bary_coords=barycentric_coords,
            zbuf=pix_to_face,
            dists=pix_to_face,
        )

        for align_corners in [True, False]:
            tex = TexturesUV(
                maps=tex_map,
                faces_uvs=[face_uvs],
                verts_uvs=[vert_uvs],
                align_corners=align_corners,
            )
            meshes = Meshes(verts=[dummy_verts],
                            faces=[face_uvs],
                            textures=tex)
            mesh_textures = meshes.textures
            texels = mesh_textures.sample_textures(fragments)

            # Expected output
            pixel_uvs = interpolated_uvs * 2.0 - 1.0
            pixel_uvs = pixel_uvs.view(2, 1, 1, 2)
            tex_map_ = torch.flip(tex_map, [1]).permute(0, 3, 1, 2)
            tex_map_ = torch.cat([tex_map_, tex_map_], dim=0)
            expected_out = F.grid_sample(tex_map_,
                                         pixel_uvs,
                                         align_corners=align_corners,
                                         padding_mode="border")
            self.assertTrue(
                torch.allclose(texels.squeeze(), expected_out.squeeze()))
Exemplo n.º 14
0
    def test_png_debug(self):
        maps = torch.rand(size=(1, 256, 128, 3)) * torch.tensor([0.8, 1, 0.8])
        verts_uvs = torch.rand(size=(1, 20, 2))
        faces_uvs = torch.zeros(size=(1, 0, 3), dtype=torch.int64)
        tex = TexturesUV(maps=maps, faces_uvs=faces_uvs, verts_uvs=verts_uvs)

        image = texturesuv_image_PIL(tex, radius=3)
        image_out = np.array(image)
        if DEBUG:
            image.save(DATA_DIR / "texturesuv_debug_.png")

        with Image.open(DATA_DIR / "texturesuv_debug.png") as image_ref_file:
            image_ref = np.array(image_ref_file)

        self.assertClose(image_out, image_ref)
Exemplo n.º 15
0
    def test_mesh_to(self):
        tex_cpu = TexturesUV(
            maps=torch.ones((5, 16, 16, 3)),
            faces_uvs=torch.randint(size=(5, 10, 3), high=15),
            verts_uvs=torch.rand(size=(5, 15, 2)),
        )
        verts = torch.rand(size=(5, 15, 3))
        faces = torch.randint(size=(5, 10, 3), high=15)
        mesh_cpu = Meshes(faces=faces, verts=verts, textures=tex_cpu)
        cpu = torch.device("cpu")
        device = torch.device("cuda:0")
        tex = mesh_cpu.to(device).textures
        self.assertEqual(tex._faces_uvs_padded.device, device)
        self.assertEqual(tex._verts_uvs_padded.device, device)
        self.assertEqual(tex._maps_padded.device, device)
        self.assertEqual(tex_cpu._verts_uvs_padded.device, cpu)

        self.assertEqual(tex_cpu.device, cpu)
        self.assertEqual(tex.device, device)