예제 #1
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('input', type=str, nargs='+', default=None, help='Input npz(s)')
    parser.add_argument('--noquant', action='store_true',
            help='Disable quantization')
    parser.add_argument('--bits', type=int, default=16,
            help='Quantization bits (order)')
    parser.add_argument('--out_dir', type=str, default='min_alt',
            help='Where to write compressed npz')
    parser.add_argument('--overwrite', action='store_true',
            help='Overwrite existing compressed npz')
    parser.add_argument('--weighted', action='store_true',
            help='Use weighted median cut (seems quite useless)')
    parser.add_argument('--sigma_thresh', type=float, default=2.0,
            help='Kill voxels under this sigma')
    parser.add_argument('--retain', type=int, default=0,
            help='Do not compress first x SH coeffs, needed for some scenes to keep ok quality')

    args = parser.parse_args()

    _C = _get_c_extension()
    os.makedirs(args.out_dir, exist_ok=True)

    if args.noquant:
        print('Quantization disabled, only applying deflate')
    else:
        print('Quantization enabled')

    for fname in args.input:
        fname_c = osp.join(args.out_dir, osp.basename(fname))
        print('Compressing', fname, 'to', fname_c)
        if not args.overwrite and osp.exists(fname_c):
            print(' > skip')
            continue

        z = np.load(fname)

        if not args.noquant:
            if 'quant_colors' in z.files:
                print(' > skip since source already compressed')
                continue
        z = dict(z)
        del z['parent_depth']
        del z['geom_resize_fact']
        del z['n_free']
        del z['n_internal']
        del z['depth_limit']

        if not args.noquant:
            data = torch.from_numpy(z['data'])
            sigma = data[..., -1].reshape(-1)
            snz = sigma > args.sigma_thresh
            sigma[~snz] = 0.0

            data = data[..., :-1]
            N = data.size(1)
            basis_dim = data.size(-1) // 3

            data = data.reshape(-1, 3, basis_dim).float()[snz].unbind(-1)
            if args.retain:
                retained = data[:args.retain]
                data = data[args.retain:]
            else:
                retained = None

            all_quant_colors = []
            all_quant_maps = []

            if args.weighted:
                weights = 1.0 - np.exp(-0.01 * sigma.float(float32))
            else:
                weights = torch.empty((0,))

            for i, d in tqdm(enumerate(data), total=len(data)):
                colors, color_id_map = _C.quantize_median_cut(d.contiguous(),
                                                              weights,
                                                              args.bits)
                color_id_map_full = np.zeros((snz.shape[0],), dtype=np.uint16)
                color_id_map_full[snz] = color_id_map

                all_quant_colors.append(colors.numpy().astype(np.float16))
                all_quant_maps.append(color_id_map_full.reshape(-1, N, N, N).astype(np.uint16))
            quant_map = np.stack(all_quant_maps, axis=0)
            quant_colors = np.stack(all_quant_colors, axis=0)
            del all_quant_maps
            del all_quant_colors
            z['quant_colors'] = quant_colors
            z['quant_map'] = quant_map
            z['sigma'] = sigma.reshape(-1, N, N, N)
            if args.retain:
                all_retained = []
                for i in range(args.retain):
                    retained_wz = np.zeros((snz.shape[0], 3), dtype=np.float16)
                    retained_wz[snz] = retained[i]
                    all_retained.append(retained_wz.reshape(-1, N, N, N, 3))
                all_retained = np.stack(all_retained, axis=0)
                del retained
                z['data_retained'] = all_retained
            del z['data']
        np.savez_compressed(fname_c, **z)
        print(' > Size', osp.getsize(fname) // (1024 * 1024), 'MB ->',
                osp.getsize(fname_c)  // (1024 * 1024), 'MB')
예제 #2
0
"""
Volume rendering utilities
"""

import torch
import numpy as np
from torch import nn, autograd
from collections import namedtuple
from warnings import warn

from svox.helpers import _get_c_extension, LocalIndex, DataFormat

NDCConfig = namedtuple('NDCConfig', ["width", "height", "focal"])
Rays = namedtuple('Rays', ["origins", "dirs", "viewdirs"])

_C = _get_c_extension()

def _rays_spec_from_rays(rays):
    spec = _C.RaysSpec()
    spec.origins = rays.origins
    spec.dirs = rays.dirs
    spec.vdirs = rays.viewdirs
    return spec

def _make_camera_spec(c2w, width, height, fx, fy):
    spec = _C.CameraSpec()
    spec.c2w = c2w
    spec.width = width
    spec.height = height
    spec.fx = fx
    spec.fy = fy