mirror of
https://github.com/facebookresearch/pytorch3d.git
synced 2025-08-02 20:02:49 +08:00
join_meshes_as_batch
Summary: rename join_meshes to join_meshes_as_batch. Reviewed By: nikhilaravi Differential Revision: D20671293 fbshipit-source-id: e84d6a67d6c1ec28fb5e52d4607db8e92561a4cd
This commit is contained in:
parent
27eb791e2f
commit
b64fe51360
@ -12,7 +12,7 @@ import numpy as np
|
|||||||
import torch
|
import torch
|
||||||
from fvcore.common.file_io import PathManager
|
from fvcore.common.file_io import PathManager
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from pytorch3d.structures import Meshes, Textures, join_meshes
|
from pytorch3d.structures import Meshes, Textures, join_meshes_as_batch
|
||||||
|
|
||||||
|
|
||||||
def _make_tensor(data, cols: int, dtype: torch.dtype) -> torch.Tensor:
|
def _make_tensor(data, cols: int, dtype: torch.dtype) -> torch.Tensor:
|
||||||
@ -249,7 +249,7 @@ def load_objs_as_meshes(files: list, device=None, load_textures: bool = True):
|
|||||||
mesh_list.append(mesh)
|
mesh_list.append(mesh)
|
||||||
if len(mesh_list) == 1:
|
if len(mesh_list) == 1:
|
||||||
return mesh_list[0]
|
return mesh_list[0]
|
||||||
return join_meshes(mesh_list)
|
return join_meshes_as_batch(mesh_list)
|
||||||
|
|
||||||
|
|
||||||
def _parse_face(
|
def _parse_face(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved.
|
# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved.
|
||||||
|
|
||||||
from .meshes import Meshes, join_meshes
|
from .meshes import Meshes, join_meshes_as_batch
|
||||||
from .pointclouds import Pointclouds
|
from .pointclouds import Pointclouds
|
||||||
from .textures import Textures
|
from .textures import Textures
|
||||||
from .utils import list_to_packed, list_to_padded, packed_to_list, padded_to_list
|
from .utils import list_to_packed, list_to_padded, packed_to_list, padded_to_list
|
||||||
|
@ -1346,7 +1346,7 @@ class Meshes(object):
|
|||||||
return Meshes(verts=new_verts_list, faces=new_faces_list, textures=tex)
|
return Meshes(verts=new_verts_list, faces=new_faces_list, textures=tex)
|
||||||
|
|
||||||
|
|
||||||
def join_meshes(meshes: List[Meshes], include_textures: bool = True):
|
def join_meshes_as_batch(meshes: List[Meshes], include_textures: bool = True):
|
||||||
"""
|
"""
|
||||||
Merge multiple Meshes objects, i.e. concatenate the meshes objects. They
|
Merge multiple Meshes objects, i.e. concatenate the meshes objects. They
|
||||||
must all be on the same device. If include_textures is true, they must all
|
must all be on the same device. If include_textures is true, they must all
|
||||||
@ -1363,8 +1363,8 @@ def join_meshes(meshes: List[Meshes], include_textures: bool = True):
|
|||||||
"""
|
"""
|
||||||
if isinstance(meshes, Meshes):
|
if isinstance(meshes, Meshes):
|
||||||
# Meshes objects can be iterated and produce single Meshes. We avoid
|
# Meshes objects can be iterated and produce single Meshes. We avoid
|
||||||
# letting join_meshes(mesh1, mesh2) silently do the wrong thing.
|
# letting join_meshes_as_batch(mesh1, mesh2) silently do the wrong thing.
|
||||||
raise ValueError("Wrong first argument to join_meshes.")
|
raise ValueError("Wrong first argument to join_meshes_as_batch.")
|
||||||
verts = [v for mesh in meshes for v in mesh.verts_list()]
|
verts = [v for mesh in meshes for v in mesh.verts_list()]
|
||||||
faces = [f for mesh in meshes for f in mesh.faces_list()]
|
faces = [f for mesh in meshes for f in mesh.faces_list()]
|
||||||
if len(meshes) == 0 or not include_textures:
|
if len(meshes) == 0 or not include_textures:
|
||||||
@ -1372,49 +1372,49 @@ def join_meshes(meshes: List[Meshes], include_textures: bool = True):
|
|||||||
|
|
||||||
if meshes[0].textures is None:
|
if meshes[0].textures is None:
|
||||||
if any(mesh.textures is not None for mesh in meshes):
|
if any(mesh.textures is not None for mesh in meshes):
|
||||||
raise ValueError("Inconsistent textures in join_meshes.")
|
raise ValueError("Inconsistent textures in join_meshes_as_batch.")
|
||||||
return Meshes(verts=verts, faces=faces)
|
return Meshes(verts=verts, faces=faces)
|
||||||
|
|
||||||
if any(mesh.textures is None for mesh in meshes):
|
if any(mesh.textures is None for mesh in meshes):
|
||||||
raise ValueError("Inconsistent textures in join_meshes.")
|
raise ValueError("Inconsistent textures in join_meshes_as_batch.")
|
||||||
|
|
||||||
# Now we know there are multiple meshes and they have textures to merge.
|
# Now we know there are multiple meshes and they have textures to merge.
|
||||||
first = meshes[0].textures
|
first = meshes[0].textures
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if first.maps_padded() is not None:
|
if first.maps_padded() is not None:
|
||||||
if any(mesh.textures.maps_padded() is None for mesh in meshes):
|
if any(mesh.textures.maps_padded() is None for mesh in meshes):
|
||||||
raise ValueError("Inconsistent maps_padded in join_meshes.")
|
raise ValueError("Inconsistent maps_padded in join_meshes_as_batch.")
|
||||||
maps = [m for mesh in meshes for m in mesh.textures.maps_padded()]
|
maps = [m for mesh in meshes for m in mesh.textures.maps_padded()]
|
||||||
kwargs["maps"] = maps
|
kwargs["maps"] = maps
|
||||||
elif any(mesh.textures.maps_padded() is not None for mesh in meshes):
|
elif any(mesh.textures.maps_padded() is not None for mesh in meshes):
|
||||||
raise ValueError("Inconsistent maps_padded in join_meshes.")
|
raise ValueError("Inconsistent maps_padded in join_meshes_as_batch.")
|
||||||
|
|
||||||
if first.verts_uvs_padded() is not None:
|
if first.verts_uvs_padded() is not None:
|
||||||
if any(mesh.textures.verts_uvs_padded() is None for mesh in meshes):
|
if any(mesh.textures.verts_uvs_padded() is None for mesh in meshes):
|
||||||
raise ValueError("Inconsistent verts_uvs_padded in join_meshes.")
|
raise ValueError("Inconsistent verts_uvs_padded in join_meshes_as_batch.")
|
||||||
uvs = [uv for mesh in meshes for uv in mesh.textures.verts_uvs_list()]
|
uvs = [uv for mesh in meshes for uv in mesh.textures.verts_uvs_list()]
|
||||||
V = max(uv.shape[0] for uv in uvs)
|
V = max(uv.shape[0] for uv in uvs)
|
||||||
kwargs["verts_uvs"] = struct_utils.list_to_padded(uvs, (V, 2), -1)
|
kwargs["verts_uvs"] = struct_utils.list_to_padded(uvs, (V, 2), -1)
|
||||||
elif any(mesh.textures.verts_uvs_padded() is not None for mesh in meshes):
|
elif any(mesh.textures.verts_uvs_padded() is not None for mesh in meshes):
|
||||||
raise ValueError("Inconsistent verts_uvs_padded in join_meshes.")
|
raise ValueError("Inconsistent verts_uvs_padded in join_meshes_as_batch.")
|
||||||
|
|
||||||
if first.faces_uvs_padded() is not None:
|
if first.faces_uvs_padded() is not None:
|
||||||
if any(mesh.textures.faces_uvs_padded() is None for mesh in meshes):
|
if any(mesh.textures.faces_uvs_padded() is None for mesh in meshes):
|
||||||
raise ValueError("Inconsistent faces_uvs_padded in join_meshes.")
|
raise ValueError("Inconsistent faces_uvs_padded in join_meshes_as_batch.")
|
||||||
uvs = [uv for mesh in meshes for uv in mesh.textures.faces_uvs_list()]
|
uvs = [uv for mesh in meshes for uv in mesh.textures.faces_uvs_list()]
|
||||||
F = max(uv.shape[0] for uv in uvs)
|
F = max(uv.shape[0] for uv in uvs)
|
||||||
kwargs["faces_uvs"] = struct_utils.list_to_padded(uvs, (F, 3), -1)
|
kwargs["faces_uvs"] = struct_utils.list_to_padded(uvs, (F, 3), -1)
|
||||||
elif any(mesh.textures.faces_uvs_padded() is not None for mesh in meshes):
|
elif any(mesh.textures.faces_uvs_padded() is not None for mesh in meshes):
|
||||||
raise ValueError("Inconsistent faces_uvs_padded in join_meshes.")
|
raise ValueError("Inconsistent faces_uvs_padded in join_meshes_as_batch.")
|
||||||
|
|
||||||
if first.verts_rgb_padded() is not None:
|
if first.verts_rgb_padded() is not None:
|
||||||
if any(mesh.textures.verts_rgb_padded() is None for mesh in meshes):
|
if any(mesh.textures.verts_rgb_padded() is None for mesh in meshes):
|
||||||
raise ValueError("Inconsistent verts_rgb_padded in join_meshes.")
|
raise ValueError("Inconsistent verts_rgb_padded in join_meshes_as_batch.")
|
||||||
rgb = [i for mesh in meshes for i in mesh.textures.verts_rgb_list()]
|
rgb = [i for mesh in meshes for i in mesh.textures.verts_rgb_list()]
|
||||||
V = max(i.shape[0] for i in rgb)
|
V = max(i.shape[0] for i in rgb)
|
||||||
kwargs["verts_rgb"] = struct_utils.list_to_padded(rgb, (V, 3))
|
kwargs["verts_rgb"] = struct_utils.list_to_padded(rgb, (V, 3))
|
||||||
elif any(mesh.textures.verts_rgb_padded() is not None for mesh in meshes):
|
elif any(mesh.textures.verts_rgb_padded() is not None for mesh in meshes):
|
||||||
raise ValueError("Inconsistent verts_rgb_padded in join_meshes.")
|
raise ValueError("Inconsistent verts_rgb_padded in join_meshes_as_batch.")
|
||||||
|
|
||||||
tex = Textures(**kwargs)
|
tex = Textures(**kwargs)
|
||||||
return Meshes(verts=verts, faces=faces, textures=tex)
|
return Meshes(verts=verts, faces=faces, textures=tex)
|
||||||
|
@ -8,7 +8,7 @@ from pathlib import Path
|
|||||||
import torch
|
import torch
|
||||||
from common_testing import TestCaseMixin
|
from common_testing import TestCaseMixin
|
||||||
from pytorch3d.io import load_obj, load_objs_as_meshes, save_obj
|
from pytorch3d.io import load_obj, load_objs_as_meshes, save_obj
|
||||||
from pytorch3d.structures import Meshes, Textures, join_meshes
|
from pytorch3d.structures import Meshes, Textures, join_meshes_as_batch
|
||||||
from pytorch3d.utils import torus
|
from pytorch3d.utils import torus
|
||||||
|
|
||||||
|
|
||||||
@ -523,10 +523,10 @@ class TestMeshObjIO(TestCaseMixin, unittest.TestCase):
|
|||||||
self.assertTrue(aux.material_colors is None)
|
self.assertTrue(aux.material_colors is None)
|
||||||
self.assertTrue(aux.texture_images is None)
|
self.assertTrue(aux.texture_images is None)
|
||||||
|
|
||||||
def test_join_meshes(self):
|
def test_join_meshes_as_batch(self):
|
||||||
"""
|
"""
|
||||||
Test that join_meshes and load_objs_as_meshes are consistent with single
|
Test that join_meshes_as_batch and load_objs_as_meshes are consistent
|
||||||
meshes.
|
with single meshes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def check_triple(mesh, mesh3):
|
def check_triple(mesh, mesh3):
|
||||||
@ -575,7 +575,7 @@ class TestMeshObjIO(TestCaseMixin, unittest.TestCase):
|
|||||||
)
|
)
|
||||||
tex = Textures(verts_rgb=vert_tex[None, :])
|
tex = Textures(verts_rgb=vert_tex[None, :])
|
||||||
mesh_rgb = Meshes(verts=[verts], faces=[faces], textures=tex)
|
mesh_rgb = Meshes(verts=[verts], faces=[faces], textures=tex)
|
||||||
mesh_rgb3 = join_meshes([mesh_rgb, mesh_rgb, mesh_rgb])
|
mesh_rgb3 = join_meshes_as_batch([mesh_rgb, mesh_rgb, mesh_rgb])
|
||||||
check_triple(mesh_rgb, mesh_rgb3)
|
check_triple(mesh_rgb, mesh_rgb3)
|
||||||
|
|
||||||
teapot_obj = DATA_DIR / "teapot.obj"
|
teapot_obj = DATA_DIR / "teapot.obj"
|
||||||
@ -588,7 +588,7 @@ class TestMeshObjIO(TestCaseMixin, unittest.TestCase):
|
|||||||
self.assertClose(mix_mesh.verts_list()[1], teapot_verts)
|
self.assertClose(mix_mesh.verts_list()[1], teapot_verts)
|
||||||
self.assertClose(mix_mesh.faces_list()[1], teapot_faces)
|
self.assertClose(mix_mesh.faces_list()[1], teapot_faces)
|
||||||
|
|
||||||
cow3_tea = join_meshes([mesh3, mesh_teapot], include_textures=False)
|
cow3_tea = join_meshes_as_batch([mesh3, mesh_teapot], include_textures=False)
|
||||||
self.assertEqual(len(cow3_tea), 4)
|
self.assertEqual(len(cow3_tea), 4)
|
||||||
check_triple(mesh_notex, cow3_tea[:3])
|
check_triple(mesh_notex, cow3_tea[:3])
|
||||||
self.assertClose(cow3_tea.verts_list()[3], mesh_teapot.verts_list()[0])
|
self.assertClose(cow3_tea.verts_list()[3], mesh_teapot.verts_list()[0])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user