def export_mesh(label_id, ds, bb_starts, bb_stops, resolution, out_path):
    if bb_starts is None:
        bb = np.s_[:]
    else:
        start, stop = bb_starts[label_id], bb_stops[label_id]
        bb = tuple(
            slice(int(sta),
                  int(sto) + 1) for sta, sto in zip(start, stop))

    seg = ds[bb]
    mask = seg == label_id
    n_foreground = mask.sum()
    # assert we have some meaningful number of foreground pixels
    assert n_foreground > 100

    res_nm = [1000. * re for re in resolution]
    verts, faces, normals = marching_cubes(mask, resolution=res_nm)
    # go from zyx axis convention to xyz
    verts = verts[:, ::-1]
    normals = normals[:, ::-1]

    # offset the vertex coordinates
    if bb_starts is not None:
        offset = np.array([sta * re for sta, re in zip(start, res_nm)])[::-1]
        verts += offset

    # save to obj
    write_obj(out_path, verts, faces, normals)
Exemple #2
0
def _compute_meshes_id_block(blocking, block_id, ds_in, output_path, sizes,
                             bb_min, bb_max, resolution, size_threshold,
                             smoothing_iterations, output_format):

    fu.log("start processing block %i" % block_id)
    block = blocking.getBlock(block_id)
    id_begin, id_end = block.begin[0], block.end[0]
    # we don't compute the skeleton for id 0, which is reserved for the ignore label
    id_begin = 1 if id_begin == 0 else id_begin

    # compute_meshes ids in range and serialize skeletons
    for seg_id in range(id_begin, id_end):
        if size_threshold is not None:
            if sizes[seg_id] < size_threshold:
                continue
        bb = tuple(
            slice(mi, ma) for mi, ma in zip(bb_min[seg_id], bb_max[seg_id]))
        obj = ds_in[bb] == seg_id

        # try to compute_meshes the object, skip if any exception is thrown
        verts, faces, normals = marching_cubes(
            obj,
            smoothing_iterations=smoothing_iterations,
            resolution=resolution)
        offsets = [b.start * res for b, res in zip(bb, resolution)]
        verts += np.array(offsets)

        if output_format == 'npy':
            out_path = os.path.join(output_path, '%i.npz' % seg_id)
            meshio.write_numpy(out_path, verts, faces, normals)
        else:
            out_path = os.path.join(output_path, '%.obj' % seg_id)
            meshio.write_obj(out_path, verts, faces, normals)

    fu.log_block_success(block_id)
Exemple #3
0
 def test_marching_cubes(self):
     from elf.mesh import marching_cubes
     shape = (64, ) * 3
     seg = (np.random.rand(*shape) > 0.6).astype("uint32")
     verts, faces, normals = marching_cubes(seg)
     self.assertGreater(len(verts), 0)
     self.assertGreater(len(faces), 0)
     self.assertGreater(len(normals), 0)
Exemple #4
0
 def test_marching_cubes_smoothing(self):
     from elf.mesh import marching_cubes
     shape = (32, ) * 3
     seg = (np.random.rand(*shape) > 0.6).astype("uint32")
     for smoothing_iterations in (1, 2, 3):
         verts, faces, normals = marching_cubes(
             seg, smoothing_iterations=smoothing_iterations)
         self.assertGreater(len(verts), 0)
         self.assertGreater(len(faces), 0)
         self.assertGreater(len(normals), 0)
Exemple #5
0
    def test_ply(self):
        from elf.mesh.io import read_ply, write_ply
        shape = (64, ) * 3
        seg = (np.random.rand(*shape) > 0.6).astype("uint32")
        verts, faces, _ = marching_cubes(seg)

        write_ply(self.tmp_path, verts, faces)
        deverts, defaces = read_ply(self.tmp_path)

        self.assertTrue(np.allclose(verts, deverts))
        self.assertTrue(np.allclose(faces, defaces))