pytorch3d icon indicating copy to clipboard operation
pytorch3d copied to clipboard

Support other face / vertex attributes in save_{obj,ply} function

Open monniert opened this issue 2 years ago • 5 comments

🚀 Feature

Support other texture representations (at least the TexturesVertex one) in save_obj function

https://github.com/facebookresearch/pytorch3d/blob/1872e0249c8c2c4eef7088996284a16cab52ca25/pytorch3d/io/obj_io.py#L652

Motivation

Saving a mesh without loosing the texture information, e.g. as done in fit_textured_mesh.ipynb

Pitch

For the TexturesVertex case it should be simple, the beginning of the _save function can for example be replaced by:

def _save(
    f,
    verts,
    faces,
    decimal_places: Optional[int] = None,
    *,
    verts_rgb: Optional[torch.Tensor] = None,
    verts_uvs: Optional[torch.Tensor] = None,
    faces_uvs: Optional[torch.Tensor] = None,
    save_texture: bool = False,
) -> None:

    if len(faces) and (faces.dim() != 2 or faces.size(1) != 3):
        message = "'faces' should either be empty or of shape (num_faces, 3)."
        raise ValueError(message)

    if not (len(verts) or len(faces)):
        warnings.warn("Empty 'verts' and 'faces' arguments provided")
        return

    if verts_rgb is not None and (verts_rgb.dim() != 2 or verts_rgb.size(1) != 3):
        message = "'verts_rgb' should either be empty or of shape (num_verts, 3)."
        raise ValueError(message)

    verts, faces = verts.cpu(), faces.cpu()

    lines = ""

    if len(verts):
        if decimal_places is None:
            float_str = "%f"
        else:
            float_str = "%" + ".%df" % decimal_places

        V, D = verts.shape
        for i in range(V):
            vert = [float_str % verts[i, j] for j in range(D)]
            if verts_rgb is not None:
                vert += [float_str % verts_rgb[i, j] for j in range(3)]
            lines += "v %s\n" % " ".join(vert)

modulo some verifications that verts_rgb has values in [0, 1]

monniert avatar Jul 27 '21 15:07 monniert

Thanks for the suggestion. I believe the OBJ format does not support per-vertex colors though.

patricklabatut avatar Jul 29 '21 15:07 patricklabatut

If you need to save such information, try using instead the PLY format: while the exposed save_ply() does not support saving colors, the internal _save_ply() should. Feel free to submit a PR to close this gap.

patricklabatut avatar Jul 29 '21 15:07 patricklabatut

my bad I thought it was rather standard to append rgb colors to the vertex position as it is fully supported by MeshLab (see for example this discussion

I will keep using my local function then and see what can be done in the PLY format

monniert avatar Jul 29 '21 15:07 monniert

Oh I see, I guess this non-standard extension could potentially be added to save_obj() then.

patricklabatut avatar Jul 29 '21 15:07 patricklabatut

great that would be cool, thanks for the detailed answers :)

monniert avatar Jul 29 '21 16:07 monniert