| import json, os, sys, time, numpy as np, trimesh |
| from multiprocessing import Pool |
| sys.path.insert(0, '/root') |
| from caption_filter import is_single_object |
|
|
| root = '/root/lowpoly' |
| OUT = '/root/data' |
| os.makedirs(OUT, exist_ok=True) |
|
|
| paths = {} |
| for dirpath, _, names in os.walk(root): |
| for n in names: |
| if n.endswith('.obj'): |
| paths[n[:-4]] = os.path.join(dirpath, n) |
| print('obj files on disk:', len(paths), flush=True) |
|
|
| caps = json.load(open('/root/captions.json')) |
| uids = sorted(u for u in caps if u in paths) |
| print('captioned meshes:', len(uids), flush=True) |
|
|
| def vox(u): |
| try: |
| m = trimesh.load(paths[u], force='mesh') |
| v = m.vertices - m.vertices.mean(0) |
| s = np.abs(v).max() |
| m.vertices = v / (s if s > 0 else 1) |
| g = m.voxelized(pitch=2.0/31).matrix.astype(np.uint8) |
| pad = np.zeros((32,32,32), np.uint8) |
| sh = [min(32,d) for d in g.shape] |
| pad[:sh[0],:sh[1],:sh[2]] = g[:sh[0],:sh[1],:sh[2]] |
| if pad.sum() == 0: |
| return u, None |
| return u, np.packbits(pad.reshape(-1)) |
| except Exception: |
| return u, None |
|
|
| t0 = time.time() |
| ok_uids, rows, failed = [], [], 0 |
| with Pool(32) as p: |
| for i, (u, packed) in enumerate(p.imap(vox, uids, chunksize=64)): |
| if packed is None: |
| failed += 1 |
| else: |
| ok_uids.append(u); rows.append(packed) |
| if (i+1) % 5000 == 0: |
| print(f' voxelized {i+1}/{len(uids)} failed {failed} {time.time()-t0:.0f}s', flush=True) |
|
|
| vox_arr = np.stack(rows) |
| np.save(f'{OUT}/voxels_packed.npy', vox_arr) |
| captions = [caps[u] for u in ok_uids] |
| keep = [bool(is_single_object(c)) for c in captions] |
| json.dump({'uids': ok_uids, 'captions': captions, 'keep': keep}, |
| open(f'{OUT}/meta.json', 'w')) |
|
|
| occ = np.unpackbits(vox_arr, axis=1).mean(1) * 100 |
| print(f'\ndone in {time.time()-t0:.0f}s') |
| print(f'meshes voxelized {len(ok_uids)}, failed/empty {failed}') |
| print(f'array {vox_arr.shape} {vox_arr.nbytes/2**20:.0f} MiB packed') |
| print(f'filter survivors {sum(keep)} = {sum(keep)/len(keep)*100:.1f}%') |
| print(f'surface occupancy mean {occ.mean():.2f}% median {np.median(occ):.2f}%') |
| print('BUILDDONE', flush=True) |
|
|