CoolFace
Apppublic

facebook/StyleNeRF

sourceHugging Faceupdated 4y agoView on Hugging Face
34likes
generate.py203 linesDownload Raw Back to root
1# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved2 3# Copyright (c) 2021, NVIDIA CORPORATION.  All rights reserved.4#5# NVIDIA CORPORATION and its licensors retain all intellectual property6# and proprietary rights in and to this software, related documentation7# and any modifications thereto.  Any use, reproduction, disclosure or8# distribution of this software and related documentation without an express9# license agreement from NVIDIA CORPORATION is strictly prohibited.10 11"""Generate images using pretrained network pickle."""12 13import os14import re15import time16import glob17from typing import List, Optional18 19import click20import dnnlib21import numpy as np22import PIL.Image23import torch24import imageio25import legacy26from renderer import Renderer27 28#----------------------------------------------------------------------------29 30def num_range(s: str) -> List[int]:31    '''Accept either a comma separated list of numbers 'a,b,c' or a range 'a-c' and return as a list of ints.'''32 33    range_re = re.compile(r'^(\d+)-(\d+)$')34    m = range_re.match(s)35    if m:36        return list(range(int(m.group(1)), int(m.group(2))+1))37    vals = s.split(',')38    return [int(x) for x in vals]39 40#----------------------------------------------------------------------------41os.environ['PYOPENGL_PLATFORM'] = 'egl'42 43@click.command()44@click.pass_context45@click.option('--network', 'network_pkl', help='Network pickle filename', required=True)46@click.option('--seeds', type=num_range, help='List of random seeds')47@click.option('--trunc', 'truncation_psi', type=float, help='Truncation psi', default=1, show_default=True)48@click.option('--class', 'class_idx', type=int, help='Class label (unconditional if not specified)')49@click.option('--noise-mode', help='Noise mode', type=click.Choice(['const', 'random', 'none']), default='const', show_default=True)50@click.option('--projected-w', help='Projection result file', type=str, metavar='FILE')51@click.option('--outdir', help='Where to save the output images', type=str, required=True, metavar='DIR')52@click.option('--render-program', default=None, show_default=True)53@click.option('--render-option', default=None, type=str, help="e.g. up_256, camera, depth")54@click.option('--n_steps', default=8, type=int, help="number of steps for each seed")55@click.option('--no-video', default=False)56@click.option('--relative_range_u_scale', default=1.0, type=float, help="relative scale on top of the original range u")57def generate_images(58    ctx: click.Context,59    network_pkl: str,60    seeds: Optional[List[int]],61    truncation_psi: float,62    noise_mode: str,63    outdir: str,64    class_idx: Optional[int],65    projected_w: Optional[str],66    render_program=None,67    render_option=None,68    n_steps=8,69    no_video=False,70    relative_range_u_scale=1.071):72 73    74    device = torch.device('cuda')75    if os.path.isdir(network_pkl):76        network_pkl = sorted(glob.glob(network_pkl + '/*.pkl'))[-1]77    print('Loading networks from "%s"...' % network_pkl)78    79    with dnnlib.util.open_url(network_pkl) as f:80        network = legacy.load_network_pkl(f)81        G = network['G_ema'].to(device) # type: ignore82        D = network['D'].to(device)83    # from fairseq import pdb;pdb.set_trace()84    os.makedirs(outdir, exist_ok=True)85 86    # Labels.87    label = torch.zeros([1, G.c_dim], device=device)88    if G.c_dim != 0:89        if class_idx is None:90            ctx.fail('Must specify class label with --class when using a conditional network')91        label[:, class_idx] = 192    else:93        if class_idx is not None:94            print ('warn: --class=lbl ignored when running on an unconditional network')95 96    # avoid persistent classes... 97    from training.networks import Generator98    # from training.stylenerf import Discriminator99    from torch_utils import misc100    with torch.no_grad():101        G2 = Generator(*G.init_args, **G.init_kwargs).to(device)102        misc.copy_params_and_buffers(G, G2, require_all=False)103        # D2 = Discriminator(*D.init_args, **D.init_kwargs).to(device)104        # misc.copy_params_and_buffers(D, D2, require_all=False)105    G2 = Renderer(G2, D, program=render_program)106    107    # Generate images.108    all_imgs = []109 110    def stack_imgs(imgs):111        img = torch.stack(imgs, dim=2)112        return img.reshape(img.size(0) * img.size(1), img.size(2) * img.size(3), 3)113 114    def proc_img(img): 115        return (img.permute(0, 2, 3, 1) * 127.5 + 128).clamp(0, 255).to(torch.uint8).cpu()116 117    if projected_w is not None:118        ws = np.load(projected_w)119        ws = torch.tensor(ws, device=device) # pylint: disable=not-callable120        img = G2(styles=ws, truncation_psi=truncation_psi, noise_mode=noise_mode, render_option=render_option)121        assert isinstance(img, List)122        imgs = [proc_img(i) for i in img]123        all_imgs += [imgs]124    125    else:126        for seed_idx, seed in enumerate(seeds):127            print('Generating image for seed %d (%d/%d) ...' % (seed, seed_idx, len(seeds)))128            G2.set_random_seed(seed)129            z = torch.from_numpy(np.random.RandomState(seed).randn(2, G.z_dim)).to(device)130            relative_range_u = [0.5 - 0.5 * relative_range_u_scale, 0.5 + 0.5 * relative_range_u_scale]131            outputs = G2(132                z=z,133                c=label,134                truncation_psi=truncation_psi,135                noise_mode=noise_mode,136                render_option=render_option,137                n_steps=n_steps,138                relative_range_u=relative_range_u,139                return_cameras=True)140            if isinstance(outputs, tuple):141                img, cameras = outputs142            else:143                img = outputs144 145            if isinstance(img, List):146                imgs = [proc_img(i) for i in img]147                if not no_video:148                    all_imgs += [imgs]149           150                curr_out_dir = os.path.join(outdir, 'seed_{:0>6d}'.format(seed))151                os.makedirs(curr_out_dir, exist_ok=True)152 153                if (render_option is not None) and ("gen_ibrnet_metadata" in render_option):154                    intrinsics = []155                    poses = []156                    _, H, W, _ = imgs[0].shape157                    for i, camera in enumerate(cameras):158                        intri, pose, _, _ = camera159                        focal = (H - 1) * 0.5 / intri[0, 0, 0].item()160                        intri = np.diag([focal, focal, 1.0, 1.0]).astype(np.float32)161                        intri[0, 2], intri[1, 2] = (W - 1) * 0.5, (H - 1) * 0.5162 163                        pose = pose.squeeze().detach().cpu().numpy() @ np.diag([1, -1, -1, 1]).astype(np.float32)164                        intrinsics.append(intri)165                        poses.append(pose)166 167                    intrinsics = np.stack(intrinsics, axis=0)168                    poses = np.stack(poses, axis=0)169 170                    np.savez(os.path.join(curr_out_dir, 'cameras.npz'), intrinsics=intrinsics, poses=poses)171                    with open(os.path.join(curr_out_dir, 'meta.conf'), 'w') as f:172                        f.write('depth_range = {}\ntest_hold_out = {}\nheight = {}\nwidth = {}'.173                                format(G2.generator.synthesis.depth_range, 2, H, W))174 175                img_dir = os.path.join(curr_out_dir, 'images_raw')176                os.makedirs(img_dir, exist_ok=True)177                for step, img in enumerate(imgs):178                    PIL.Image.fromarray(img[0].detach().cpu().numpy(), 'RGB').save(f'{img_dir}/{step:03d}.png')179 180            else:181                img = proc_img(img)[0]182                PIL.Image.fromarray(img.numpy(), 'RGB').save(f'{outdir}/seed_{seed:0>6d}.png')183 184    if len(all_imgs) > 0 and (not no_video):185         # write to video186        timestamp = time.strftime('%Y%m%d.%H%M%S',time.localtime(time.time()))187        seeds = ','.join([str(s) for s in seeds]) if seeds is not None else 'projected'188        network_pkl = network_pkl.split('/')[-1].split('.')[0]189        all_imgs = [stack_imgs([a[k] for a in all_imgs]).numpy() for k in range(len(all_imgs[0]))]190        imageio.mimwrite(f'{outdir}/{network_pkl}_{timestamp}_{seeds}.mp4', all_imgs, fps=30, quality=8)191        outdir = f'{outdir}/{network_pkl}_{timestamp}_{seeds}'192        os.makedirs(outdir, exist_ok=True)193        for step, img in enumerate(all_imgs):194            PIL.Image.fromarray(img, 'RGB').save(f'{outdir}/{step:04d}.png')195 196 197#----------------------------------------------------------------------------198 199if __name__ == "__main__":200    generate_images() # pylint: disable=no-value-for-parameter201 202#----------------------------------------------------------------------------203