mirror of
https://github.com/facebookresearch/pytorch3d.git
synced 2025-08-02 20:02:49 +08:00
Tutorials textures updates and fix bug in extending meshes with uv textures
Summary: Found a bug in extending textures with vertex uv coordinates. This was due to the padded -> list conversion of vertex uv coordinates i.e. The number of vertices in the mesh and in verts_uvs can differ e.g. if a vertex is shared between 3 faces, it can have up to 3 different uv coordinates. Therefore we cannot convert directly from padded to list using _num_verts_per_mesh Reviewed By: bottler Differential Revision: D23233595 fbshipit-source-id: 0c66d15baae697ead0bdc384f74c27d4c6539fc9
This commit is contained in:
parent
d330765847
commit
90f6a005b0
File diff suppressed because it is too large
Load Diff
@ -87,7 +87,7 @@
|
|||||||
"from pytorch3d.io import load_objs_as_meshes, load_obj\n",
|
"from pytorch3d.io import load_objs_as_meshes, load_obj\n",
|
||||||
"\n",
|
"\n",
|
||||||
"# Data structures and functions for rendering\n",
|
"# Data structures and functions for rendering\n",
|
||||||
"from pytorch3d.structures import Meshes, Textures\n",
|
"from pytorch3d.structures import Meshes\n",
|
||||||
"from pytorch3d.renderer import (\n",
|
"from pytorch3d.renderer import (\n",
|
||||||
" look_at_view_transform,\n",
|
" look_at_view_transform,\n",
|
||||||
" FoVPerspectiveCameras, \n",
|
" FoVPerspectiveCameras, \n",
|
||||||
@ -97,7 +97,8 @@
|
|||||||
" RasterizationSettings, \n",
|
" RasterizationSettings, \n",
|
||||||
" MeshRenderer, \n",
|
" MeshRenderer, \n",
|
||||||
" MeshRasterizer, \n",
|
" MeshRasterizer, \n",
|
||||||
" SoftPhongShader\n",
|
" SoftPhongShader,\n",
|
||||||
|
" TexturesUV\n",
|
||||||
")\n",
|
")\n",
|
||||||
"\n",
|
"\n",
|
||||||
"# add path for demo utils functions \n",
|
"# add path for demo utils functions \n",
|
||||||
@ -170,7 +171,7 @@
|
|||||||
"\n",
|
"\n",
|
||||||
"**Meshes** is a unique datastructure provided in PyTorch3D for working with batches of meshes of different sizes. \n",
|
"**Meshes** is a unique datastructure provided in PyTorch3D for working with batches of meshes of different sizes. \n",
|
||||||
"\n",
|
"\n",
|
||||||
"**Textures** is an auxillary datastructure for storing texture information about meshes. \n",
|
"**TexturesUV** is an auxillary datastructure for storing vertex uv and texture maps for meshes. \n",
|
||||||
"\n",
|
"\n",
|
||||||
"**Meshes** has several class methods which are used throughout the rendering pipeline."
|
"**Meshes** has several class methods which are used throughout the rendering pipeline."
|
||||||
]
|
]
|
||||||
@ -537,7 +538,7 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"# We can pass arbirary keyword arguments to the rasterizer/shader via the renderer\n",
|
"# We can pass arbirary keyword arguments to the rasterizer/shader via the renderer\n",
|
||||||
"# so the renderer does not need to be reinitialized if any of the settings change.\n",
|
"# so the renderer does not need to be reinitialized if any of the settings change.\n",
|
||||||
"images = renderer(meshes, cameras=cameras, lights=lights)"
|
"images = renderer(mesh, cameras=cameras, lights=lights)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -582,9 +583,9 @@
|
|||||||
"backup_notebook_id": "569222367081034"
|
"backup_notebook_id": "569222367081034"
|
||||||
},
|
},
|
||||||
"kernelspec": {
|
"kernelspec": {
|
||||||
"display_name": "pytorch3d (local)",
|
"display_name": "intro_to_cv",
|
||||||
"language": "python",
|
"language": "python",
|
||||||
"name": "pytorch3d_local"
|
"name": "bento_kernel_intro_to_cv"
|
||||||
},
|
},
|
||||||
"language_info": {
|
"language_info": {
|
||||||
"codemirror_mode": {
|
"codemirror_mode": {
|
||||||
|
@ -599,11 +599,6 @@ class TexturesUV(TexturesBase):
|
|||||||
if not all(v.device == self.device for v in verts_uvs):
|
if not all(v.device == self.device for v in verts_uvs):
|
||||||
raise ValueError("verts_uvs and faces_uvs must be on the same device")
|
raise ValueError("verts_uvs and faces_uvs must be on the same device")
|
||||||
|
|
||||||
# These values may be overridden when textures is
|
|
||||||
# passed into the Meshes constructor. For more details
|
|
||||||
# refer to the __init__ of Meshes.
|
|
||||||
self._num_verts_per_mesh = [len(v) for v in verts_uvs]
|
|
||||||
|
|
||||||
elif torch.is_tensor(verts_uvs):
|
elif torch.is_tensor(verts_uvs):
|
||||||
if (
|
if (
|
||||||
verts_uvs.ndim != 3
|
verts_uvs.ndim != 3
|
||||||
@ -621,7 +616,6 @@ class TexturesUV(TexturesBase):
|
|||||||
# These values may be overridden when textures is
|
# These values may be overridden when textures is
|
||||||
# passed into the Meshes constructor.
|
# passed into the Meshes constructor.
|
||||||
max_V = verts_uvs.shape[1]
|
max_V = verts_uvs.shape[1]
|
||||||
self._num_verts_per_mesh = [max_V] * self._N
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("Expected verts_uvs to be a tensor or list")
|
raise ValueError("Expected verts_uvs to be a tensor or list")
|
||||||
|
|
||||||
@ -758,9 +752,11 @@ class TexturesUV(TexturesBase):
|
|||||||
torch.empty((0, 2), dtype=torch.float32, device=self.device)
|
torch.empty((0, 2), dtype=torch.float32, device=self.device)
|
||||||
] * self._N
|
] * self._N
|
||||||
else:
|
else:
|
||||||
self._verts_uvs_list = padded_to_list(
|
# The number of vertices in the mesh and in verts_uvs can differ
|
||||||
self._verts_uvs_padded, split_size=self._num_verts_per_mesh
|
# e.g. if a vertex is shared between 3 faces, it can
|
||||||
)
|
# have up to 3 different uv coordinates. Therefore we cannot
|
||||||
|
# convert directly from padded to list using _num_verts_per_mesh
|
||||||
|
self._verts_uvs_list = list(self._verts_uvs_padded.unbind(0))
|
||||||
return self._verts_uvs_list
|
return self._verts_uvs_list
|
||||||
|
|
||||||
# Currently only the padded maps are used.
|
# Currently only the padded maps are used.
|
||||||
@ -783,7 +779,6 @@ class TexturesUV(TexturesBase):
|
|||||||
"verts_uvs_padded",
|
"verts_uvs_padded",
|
||||||
"faces_uvs_padded",
|
"faces_uvs_padded",
|
||||||
"_num_faces_per_mesh",
|
"_num_faces_per_mesh",
|
||||||
"_num_verts_per_mesh",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
new_tex = TexturesUV(
|
new_tex = TexturesUV(
|
||||||
@ -791,8 +786,8 @@ class TexturesUV(TexturesBase):
|
|||||||
faces_uvs=new_props["faces_uvs_padded"],
|
faces_uvs=new_props["faces_uvs_padded"],
|
||||||
verts_uvs=new_props["verts_uvs_padded"],
|
verts_uvs=new_props["verts_uvs_padded"],
|
||||||
)
|
)
|
||||||
|
|
||||||
new_tex._num_faces_per_mesh = new_props["_num_faces_per_mesh"]
|
new_tex._num_faces_per_mesh = new_props["_num_faces_per_mesh"]
|
||||||
new_tex._num_verts_per_mesh = new_props["_num_verts_per_mesh"]
|
|
||||||
return new_tex
|
return new_tex
|
||||||
|
|
||||||
def sample_textures(self, fragments, **kwargs) -> torch.Tensor:
|
def sample_textures(self, fragments, **kwargs) -> torch.Tensor:
|
||||||
@ -860,6 +855,7 @@ class TexturesUV(TexturesBase):
|
|||||||
# right-bottom pixel of input.
|
# right-bottom pixel of input.
|
||||||
|
|
||||||
pixel_uvs = pixel_uvs * 2.0 - 1.0
|
pixel_uvs = pixel_uvs * 2.0 - 1.0
|
||||||
|
|
||||||
texture_maps = torch.flip(texture_maps, [2]) # flip y axis of the texture map
|
texture_maps = torch.flip(texture_maps, [2]) # flip y axis of the texture map
|
||||||
if texture_maps.device != pixel_uvs.device:
|
if texture_maps.device != pixel_uvs.device:
|
||||||
texture_maps = texture_maps.to(pixel_uvs.device)
|
texture_maps = texture_maps.to(pixel_uvs.device)
|
||||||
|
@ -588,10 +588,19 @@ class TestTexturesUV(TestCaseMixin, unittest.TestCase):
|
|||||||
tex_init = tex_mesh.textures
|
tex_init = tex_mesh.textures
|
||||||
new_tex = new_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 i in range(len(tex_mesh)):
|
||||||
for n in range(N):
|
for n in range(N):
|
||||||
|
tex_nv = new_tex_num_verts[i * N + n]
|
||||||
self.assertClose(
|
self.assertClose(
|
||||||
tex_init.verts_uvs_list()[i], new_tex.verts_uvs_list()[i * N + n]
|
# 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(
|
self.assertClose(
|
||||||
tex_init.faces_uvs_list()[i], new_tex.faces_uvs_list()[i * N + n]
|
tex_init.faces_uvs_list()[i], new_tex.faces_uvs_list()[i * N + n]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user