kaolin.ops.conversions

API

kaolin.ops.conversions.pointclouds_to_voxelgrids(pointclouds, resolution, origin=None, scale=None, return_sparse=False)

Converts pointclouds to voxelgrids. It separates the 3D space into empty voxelgrid, and for each boxes, if there is a corresponding point, set that voxelgrid to be occupied.

Parameters
  • pointclouds (torch.Tensor) – Exact batched pointclouds with shape \((\text{batch_size}, \text{P}, \text{3})\).

  • resolution (int) – Resolution of output voxelgrids

  • origin (torch.tensor) – origin of the voxelgrid in the pointcloud coordinates. It has shape \((\text{batch_size}, 3)\). Default: origin = torch.min(pointcloud, dim=1)[0]

  • scale (torch.tensor) – the scale by which we divide the pointclouds’ coordinates. It has shape \((\text{batch_size})\). Default: scale = torch.max(torch.max(pointclouds, dim=1)[0] - origin, dim=1)[0]

  • return_sparse (bool) – Whether to return a sparse voxelgrids or not.

Returns

Exact batched voxelgrids with shape \((\text{batch_size}, \text{resolution}, \text{resolution}, \test{resolution})\). If return_sparse == True, a sparse FloatTensor is returned.

Return type

(torch.Tensor or torch.FloatTensor)

Example

>>> pointclouds = torch.tensor([[[0, 0, 0],
...                              [1, 1, 1],
...                              [2, 2, 2]]], dtype=torch.float)
>>> pointclouds_to_voxelgrids(pointclouds, 3)
tensor([[[[1., 0., 0.],
          [0., 0., 0.],
          [0., 0., 0.]],

         [[0., 0., 0.],
          [0., 1., 0.],
          [0., 0., 0.]],

         [[0., 0., 0.],
          [0., 0., 0.],
          [0., 0., 1.]]]])
kaolin.ops.conversions.sdf_to_voxelgrids(sdf, bbox_center=0.0, bbox_dim=1.0, init_res=32, upsampling_steps=0)

Converts SDFs to voxelgrids.

For each SDF returns a voxel grid with resolution \(init\_res * 2 ^ {upsampling\_steps} + 1\) (so the underlying voxel resolution is \(init\_res * 2 ^ {upsampling\_steps}\)) where each grid point holds a binary value determined by the sign of the SDF at the location of the grid point after normalizing the voxel grid to the bounding box defined by bbox_center and bbox_dim.

This solution is largely borrowed from “Multiresolution IsoSurface Extraction (MISE)” proposed in the CVPR 2019 paper “Occupancy Networks: Learning 3D Reconstruction in Function Space”: https://arxiv.org/abs/1906.02739. Instead of evaluating SDF values of all grid points at high resolution, this function incrementally builds an octree and only evaluate dense grid points around the surface.

Parameters
  • sdf (list[callable]) – a list of callable that takes in an Nx3 tensor of N 3D coordinates and outputs the N corresponding SDF values

  • bbox_center (float) – center of the surface’s bounding box.

  • bbox_dim (float) – largest dimension of the surface’s bounding box.

  • init_res (int) – the initial resolution of the voxel, should be large enough to properly define the surface.

  • upsampling_steps (int) – Number of times the initial resolution will be doubled.

Returns

Binary voxelgrids of shape \((batch\_size, init\_res * 2 ^ {upsampling\_steps} + 1)\)

Return type

(torch.Tensor)

Example

>>> def sphere(points):
...     return torch.sum(points ** 2, 1) ** 0.5 - 0.5
>>> sdf_to_voxelgrids([sphere], init_res=4)
tensor([[[[0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 1., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.]],

         [[0., 0., 0., 0., 0.],
          [0., 1., 1., 1., 0.],
          [0., 1., 1., 1., 0.],
          [0., 1., 1., 1., 0.],
          [0., 0., 0., 0., 0.]],

         [[0., 0., 1., 0., 0.],
          [0., 1., 1., 1., 0.],
          [1., 1., 1., 1., 1.],
          [0., 1., 1., 1., 0.],
          [0., 0., 1., 0., 0.]],

         [[0., 0., 0., 0., 0.],
          [0., 1., 1., 1., 0.],
          [0., 1., 1., 1., 0.],
          [0., 1., 1., 1., 0.],
          [0., 0., 0., 0., 0.]],

         [[0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 1., 0., 0.],
          [0., 0., 0., 0., 0.],
          [0., 0., 0., 0., 0.]]]])
kaolin.ops.conversions.trianglemeshes_to_voxelgrids(vertices, faces, resolution, origin=None, scale=None, return_sparse=False)

Converts meshes to surface voxelgrids of a given resolution. It first upsamples triangle mesh’s vertices to given resolution, then it performs a box test. If a voxel contains a triangle vertex, set that voxel to 1. Vertex will be offset and scaled as following: \(\text{normalized_vertices} = (\text{vertices} - \text{origin}) / \text{scale}\) the voxelgrids will only be generated in the range [0, 1] of normalized_vertices.

Parameters
  • vertices (torch.tensor) – batched vertices of shape (B, V, 3) of mesh to convert.

  • faces (torch.tensor) – unbatched faces of shape (F, 3) of mesh to convert.

  • resolution (int) – desired resolution of generated voxelgrid.

  • origin (torch.tensor) – origin of the voxelgrid in the mesh coordinates. It has shape \((\text{batch_size}, 3)\). Default: origin = torch.min(vertices, dim=1)[0]

  • scale (torch.tensor) – the scale by which we divide the vertex position. It has shape \((\text{batch_size})\). Default: scale = torch.max(torch.max(vertices, dim=1)[0] - origin, dim=1)[0]

Returns

Binary batched voxelgrids of shape (B, resolution, resolution, resolution). If return_sparse == True, sparse tensor is returned.

Return type

(torch.Tensor or torch.FloatTensor)

Example

>>> vertices = torch.tensor([[[0, 0, 0],
...                           [1, 0, 0],
...                           [0, 0, 1]]], dtype=torch.float)
>>> faces = torch.tensor([[0, 1, 2]], dtype=torch.long)
>>> origin = torch.zeros((1, 3))
>>> scale = torch.ones((1))
>>> trianglemeshes_to_voxelgrids(vertices, faces, 3, origin, scale)
tensor([[[[1., 1., 1.],
          [0., 0., 0.],
          [0., 0., 0.]],

         [[1., 1., 0.],
          [0., 0., 0.],
          [0., 0., 0.]],

         [[1., 0., 0.],
          [0., 0., 0.],
          [0., 0., 0.]]]])
kaolin.ops.conversions.voxelgrids_to_cubic_meshes(voxelgrids, is_trimesh=True)

Convert voxelgrids to meshes by replacing each occupied voxel with a cuboid mesh (unit cube). Each cube has 8 vertices and 6 (for quadmesh) or 12 faces (for triangular mesh). Internal faces are ignored. If is_trimesh==True, this function performs the same operation as “Cubify” defined in the ICCV 2019 paper “Mesh R-CNN”: https://arxiv.org/abs/1906.02739. :param voxelgrids: binary voxel array with shape (B, X, Y, Z). :type voxelgrids: torch.Tensor :param is_trimesh: the outputs are triangular meshes if True. Otherwise quadmeshes are returned. :type is_trimesh: bool

Returns

tuple containing the list of vertices and the list of faces for each mesh.

Return type

(list[torch.Tensor], list[torch.LongTensor])

Example

>>> voxelgrids = torch.ones((1, 1, 1, 1))
>>> verts, faces = voxelgrids_to_cubic_meshes(voxelgrids)
>>> verts[0]
tensor([[0., 0., 0.],
        [0., 0., 1.],
        [0., 1., 0.],
        [0., 1., 1.],
        [1., 0., 0.],
        [1., 0., 1.],
        [1., 1., 0.],
        [1., 1., 1.]])
>>> faces[0]
tensor([[0, 1, 2],
        [5, 4, 7],
        [0, 4, 1],
        [6, 2, 7],
        [0, 2, 4],
        [3, 1, 7],
        [3, 2, 1],
        [6, 7, 4],
        [5, 1, 4],
        [3, 7, 2],
        [6, 4, 2],
        [5, 7, 1]])
kaolin.ops.conversions.voxelgrids_to_trianglemeshes(voxelgrids, iso_value=0.5)

Converts voxelgrids to triangle meshes using marching cube algorithm. Please refer to: Lorensen, William E.; Cline, Harvey E. in Marching cubes, A high resolution 3D surface construction algorithm

Parameters
  • voxelgrids (torch.Tensor) – Exact batched voxel array with shape \((\text{batch_size}, \text{dim}, \text{dim}, \text{dim})\).

  • iso_value (float) – Value in the range [0, 1] used to determine whether a voxel is inside the surface or not. Isovalue is also used to interpolate newly created triangle vertices. Defaults to 0.5

Returns

List of vertices and faces tensors of the converted triangle mesh, corresponds to each voxelgrid.

Return type

(List of torch.FloatTensor, List of torch.LongTensor)

Example

>>> voxelgrid = torch.tensor([[[[1, 0],
...                             [0, 0]],
...                            [[0, 0],
...                             [0, 0]]]], device='cuda', dtype=torch.uint8)
>>> vertices, faces = voxelgrids_to_trianglemeshes(voxelgrid)
>>> vertices[0]
tensor([[1.0000, 1.0000, 0.5000],
        [1.0000, 0.5000, 1.0000],
        [0.5000, 1.0000, 1.0000],
        [1.0000, 1.0000, 1.5000],
        [1.0000, 1.5000, 1.0000],
        [1.5000, 1.0000, 1.0000]], device='cuda:0')
>>> faces[0]
tensor([[0, 1, 2],
        [3, 2, 1],
        [4, 0, 2],
        [4, 2, 3],
        [0, 5, 1],
        [5, 3, 1],
        [4, 5, 0],
        [5, 4, 3]], device='cuda:0')