marian42 / mesh_to_sdf

Calculate signed distance fields for arbitrary meshes
https://pypi.org/project/mesh-to-sdf/
MIT License
991 stars 107 forks source link

Fitting into a cube ranging from (-0.5,-0.5,-0.5) to (0.5,0.5,0.5) Question ?? #2

Closed ParikaGoel closed 4 years ago

ParikaGoel commented 4 years ago

Hey Marian,

I am working on generating sdf voxelizations of shapenet dataset. I came across your library which is by far the best for my task. I used the mesh_to_voxels API to generate the sdfs which are quite good. But I am facing one problem and would be grateful if you could help me out.

The voxelizations produced right now give me a voxel grid ranging from (-1,-1,-1) to (1,1,1). I am trying to transform it into a cube ranging from (-0.5,-0.5,-0.5) to (0.5,0.5,0.5) since the shapenet dataset is also normalized into this range.

Below is the code of what I am doing:

mesh = trimesh.load("table.obj") sdf_grid = mesh_to_voxels(mesh, 32, pad=False) <- Generates sdf

Then I use the truncation distance to get the occupancy grid trunc_dist = 1/32 sdf_grid = torch.from_numpy(sdf_grid) mask = torch.gt(sdf_grid, -trunc_dist) & torch.lt(sdf_grid, trunc_dist) positions = np.where(mask.cpu().numpy()) <- This gives me the grid coordinates for occupancy grid

Then I am visualizing it by generating a ply file for the occupancy

image

This is the visualization of the occupancy grid generated from sdf and obj file of the model in meshlab. Looks like there is the scaling difference between shapenet model is normalized in the range of (-0.5,-0.5,-0.5) to (0.5,0.5,0.5), whereas the generated sdf is in the range of (-1,-1,-1) to (1,1,1).

Is there a way by which I can make the transformation ?

Thank you for your time.

marian42 commented 4 years ago

How do you "generate a ply file for the occupancy"?

The result of np.where will be integer indices of the input array, in this case they will be numbers from 0 to 32 (or whatever your resolution will be).

ParikaGoel commented 4 years ago

I have written below code to generate ply file from voxel positions:

def generate_ply(grid_positions, ply_filename, grid_size=None): cube_verts = np.array([[-1.0, -1.0, 1.0], [1.0, -1.0, 1.0], [1.0, 1.0, 1.0], [-1.0, 1.0, 1.0], [-1.0, -1.0, -1.0], [1.0, -1.0, -1.0], [1.0, 1.0, -1.0], [-1.0, 1.0, -1.0]]) # 8 points

cube_faces = np.array([[0, 1, 2], [2, 3, 0], [1, 5, 6], [6, 2, 1], [7, 6, 5], [5, 4, 7],
                       [4, 0, 3], [3, 7, 4], [4, 5, 1], [1, 0, 4], [3, 2, 6], [6, 7, 3]])  # 6 faces (12 triangles)

verts = []
faces = []
curr_vertex = 0

if grid_size is None:
    grid_size = 1

min_bound = np.array([-grid_size / 2, -grid_size / 2, -grid_size / 2])
voxel_scale = grid_size / 32

color = np.array([169, 0, 255])

for i, j, k in zip(*grid_positions):
    for cube_vert in cube_verts:
        vertex = (cube_vert * 0.45 + np.array([i, j, k])).astype(float)
        vertex *= voxel_scale
        vertex += min_bound
        vertex = np.append(vertex, color)
        vertex = list(vertex)
        verts.append(vertex)

    for cube_face in cube_faces:
        face = curr_vertex + cube_face
        faces.append(list(face))

    curr_vertex += len(cube_verts)

    file = open(ply_filename, "w")
    file.write('''ply
        format ascii 1.0
        element vertex %d
        property float x
        property float y
        property float z
        property uchar red
        property uchar green
        property uchar blue
        element face %d
        property list uchar int vertex_index
        end_header
        ''' % (len(verts), len(faces)))

    for vert in verts:
        file.write('%f %f %f %d %d %d\n' % tuple(vert))

    for face in faces:
        file.write('3 %d %d %d\n' % tuple(face))

    file.close()

I call above function as generate_ply(positions, "table.ply", grid_size=2)

marian42 commented 4 years ago

What happens if you change your voxel_scale = grid_size / 32 line to

voxel_scale = grid_size / 32 / 2

?

ParikaGoel commented 4 years ago

I got confused whether you meant dividing by 16 or 64, so I tried both

voxel_scale = grid_size / 16 produces below output image

voxel_scale = grid_size / 64 produces below output image

marian42 commented 4 years ago

It looks like on your second image the scale is pretty good, but the translation is off. So you should try to adjust your min_bound parameter.