def get_inversions_on_batch(inputs, net, avg_image, opts):
    result_batch, result_latents = run_on_batch(inputs, net, opts, avg_image)
    # we'll take the final inversion as the inversion to edit
    y_hat = [result_batch[idx][-1] for idx in range(len(result_batch))]
    latents = [
        torch.from_numpy(result_latents[idx][-1]).cuda()
        for idx in range(len(result_batch))
    ]
    return y_hat, torch.stack(latents)
示例#2
0
    def run_default_encoding(self, input, encoding_type, num_iterations,
                             display_intermediate_results):
        # load model
        print(f'Loading {encoding_type} model...')
        ckpt = self.checkpoints[encoding_type]
        opts = ckpt['opts']
        opts['checkpoint_path'] = self.model_paths[encoding_type]
        opts = Namespace(**opts)
        net = e4e(opts) if encoding_type == "horses" else pSp(opts)
        net.eval()
        net.cuda()
        print('Done!')

        # define some arguments
        opts.n_iters_per_batch = num_iterations
        opts.resize_outputs = False

        # define transforms
        image_transforms = self.cars_transforms if encoding_type == "cars" else self.default_transforms

        # if working on faces load and align the image
        if encoding_type == "faces":
            print('Aligning image...')
            input_image = self.run_alignment(str(input))
            print('Done!')
        # otherwise simply load the image
        else:
            input_image = Image.open(str(input)).convert("RGB")

        # preprocess image
        transformed_image = image_transforms(input_image)

        # run inference
        print("Running inference...")
        with torch.no_grad():
            start = time.time()
            avg_image = self.get_avg_image(net, encoding_type)
            result_batch, result_latents = run_on_batch(
                transformed_image.unsqueeze(0).cuda(), net, opts, avg_image)
            total_time = time.time() - start
        print(f"Finished inference in {total_time} seconds!")

        # post-processing
        print("Preparing result...")
        resize_amount = (512, 384) if encoding_type == "cars_encode" else (
            opts.output_size, opts.output_size)
        res = self.get_final_output(result_batch, resize_amount,
                                    display_intermediate_results, opts)

        # display output
        out_path = Path(tempfile.mkdtemp()) / "output.png"
        imageio.imwrite(str(out_path), res)
        return out_path
def run():
    test_opts = TestOptions().parse()

    out_path_coupled = os.path.join(test_opts.exp_dir, 'inference_coupled')
    os.makedirs(out_path_coupled, exist_ok=True)

    # update test options with options used during training
    ckpt = torch.load(test_opts.checkpoint_path, map_location='cpu')
    opts = ckpt['opts']
    opts.update(vars(test_opts))
    opts = Namespace(**opts)

    net = pSp(opts)
    net.eval()
    net.cuda()

    print('Loading dataset for {}'.format(opts.dataset_type))
    dataset_args = data_configs.DATASETS[opts.dataset_type]
    transforms_dict = dataset_args['transforms'](opts).get_transforms()
    dataset = InferenceDataset(root=opts.data_path,
                               transform=transforms_dict['transform_inference'],
                               opts=opts)
    dataloader = DataLoader(dataset,
                            batch_size=opts.test_batch_size,
                            shuffle=False,
                            num_workers=int(opts.test_workers),
                            drop_last=False)

    if opts.n_images is None:
        opts.n_images = len(dataset)

    # get the image corresponding to the latent average
    avg_image = net(net.latent_avg.unsqueeze(0),
                    input_code=True,
                    randomize_noise=False,
                    return_latents=False,
                    average_code=True)[0]
    avg_image = avg_image.to('cuda').float().detach()
    if opts.dataset_type == "cars_encode":
        avg_image = avg_image[:, 32:224, :]
    tensor2im(avg_image).save(os.path.join(opts.exp_dir, 'avg_image.jpg'))

    if opts.dataset_type == "cars_encode":
        resize_amount = (256, 192) if opts.resize_outputs else (512, 384)
    else:
        resize_amount = (256, 256) if opts.resize_outputs else (opts.output_size, opts.output_size)

    global_i = 0
    global_time = []
    for input_batch in tqdm(dataloader):
        if global_i >= opts.n_images:
            break

        with torch.no_grad():
            input_cuda = input_batch.cuda().float()
            tic = time.time()
            result_batch, result_latents = run_on_batch(input_cuda, net, opts, avg_image)
            toc = time.time()
            global_time.append(toc - tic)

        for i in range(input_batch.shape[0]):
            results = [tensor2im(result_batch[i][iter_idx]) for iter_idx in range(opts.n_iters_per_batch)]
            im_path = dataset.paths[global_i]

            # save step-by-step results side-by-side
            input_im = tensor2im(input_batch[i])
            res = np.array(results[0].resize(resize_amount))
            for idx, result in enumerate(results[1:]):
                res = np.concatenate([res, np.array(result.resize(resize_amount))], axis=1)
            res = np.concatenate([res, input_im.resize(resize_amount)], axis=1)

            Image.fromarray(res).save(os.path.join(out_path_coupled, os.path.basename(im_path)))

            global_i += 1

    stats_path = os.path.join(opts.exp_dir, 'stats.txt')
    result_str = 'Runtime {:.4f}+-{:.4f}'.format(np.mean(global_time), np.std(global_time))
    print(result_str)

    with open(stats_path, 'w') as f:
        f.write(result_str)
示例#4
0
def process(input_path, output_path, verbose, preloaded_params):
    time_before = time.time()

    image_path = input_path
    net = preloaded_params[0]
    opts = preloaded_params[1]

    # VISUALIZE INPUT
    # image_path = EXPERIMENT_DATA_ARGS[experiment_type]["image_path"]
    original_image = Image.open(image_path).convert("RGB")

    # ALIGN IMAGE
    # def run_alignment(image_path):
    #     import dlib
    #     from scripts.align_faces_parallel import align_face
    #     if not os.path.exists("shape_predictor_68_face_landmarks.dat"):
    #         print('Downloading files for aligning face image...')
    #         os.system('wget http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2')
    #         os.system('bzip2 -dk shape_predictor_68_face_landmarks.dat.bz2')
    #         print('Done.')
    #     predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
    #     aligned_image = align_face(filepath=image_path, predictor=predictor)
    #     print("Aligned image has shape: {}".format(aligned_image.size))
    #     return aligned_image

    # if experiment_type in ['ffhq_encode', 'toonify']:
    #     input_image = run_alignment(image_path)
    # else:
    #     input_image = original_image
    input_image = original_image

    # PERFORM INFERENCE
    img_transforms = transforms.Compose([
        transforms.Resize((256, 256)),
        transforms.ToTensor(),
        transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
    ])

    transformed_image = img_transforms(input_image)

    with torch.no_grad():
        avg_image = get_avg_image(net)
        tic = time.time()
        result_batch, result_latents = run_on_batch(
            transformed_image.unsqueeze(0).cuda(), net, opts, avg_image)
        toc = time.time()
        if verbose:
            print('Inference took {:.4f} seconds.'.format(toc - tic))

    # KEEP LAST W-VECTOR
    w_last = result_latents[0][NUM_STEPS - 1]

    # make sure output folder exists, otherwise saving won’t work
    if not os.path.exists(output_path):
        os.makedirs(output_path)
    np.save(f'{output_path}/w_vector.npy', w_last, allow_pickle=True)

    time_after = time.time()
    if verbose:
        print('Time to load img and get its w-vector took {:.4f} seconds.'.
              format(time_after - time_before))

    # Emit DONE signal
    Path(f'{output_path}/w_vector.done').touch()
示例#5
0
def project(image_path: str, output_path: str, network: str,
            NUM_OUTPUT_IMAGES: int):
    experiment_type = 'ffhq_encode'  #['ffhq_encode', 'cars_encode', 'church_encode', 'horse_encode', 'afhq_wild_encode', 'toonify']

    CODE_DIR = 'restyle-encoder'

    def get_download_model_command(file_id, file_name):
        """ Get wget download command for downloading the desired model and save to directory ../pretrained_models. """
        current_directory = os.getcwd()
        save_path = os.path.join(os.path.dirname(current_directory), CODE_DIR,
                                 "pretrained_models")
        if not os.path.exists(save_path):
            os.makedirs(save_path)
        url = r"""wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id={FILE_ID}' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id={FILE_ID}" -O {SAVE_PATH}/{FILE_NAME} && rm -rf /tmp/cookies.txt""".format(
            FILE_ID=file_id, FILE_NAME=file_name, SAVE_PATH=save_path)
        return url

    MODEL_PATHS = {
        "ffhq_encode": {
            "id": "1sw6I2lRIB0MpuJkpc8F5BJiSZrc0hjfE",
            "name": "restyle_psp_ffhq_encode.pt"
        },
        # "church_encode": {"id": "1bcxx7mw-1z7dzbJI_z7oGpWG1oQAvMaD", "name": "restyle_psp_church_encode.pt"},
        # "horse_encode": {"id": "19_sUpTYtJmhSAolKLm3VgI-ptYqd-hgY", "name": "restyle_e4e_horse_encode.pt"},
        # "afhq_wild_encode": {"id": "1GyFXVTNDUw3IIGHmGS71ChhJ1Rmslhk7", "name": "restyle_psp_afhq_wild_encode.pt"},
        # "toonify": {"id": "1GtudVDig59d4HJ_8bGEniz5huaTSGO_0", "name": "restyle_psp_toonify.pt"}
    }

    path = MODEL_PATHS[experiment_type]
    download_command = get_download_model_command(file_id=path["id"],
                                                  file_name=path["name"])

    EXPERIMENT_DATA_ARGS = {
        "ffhq_encode": {
            "model_path":
            network,  #"pretrained_models/restyle_psp_ffhq_encode.pt",
            # "image_path": "notebooks/images/face_img.jpg",
            "transform":
            transforms.Compose([
                transforms.Resize((256, 256)),
                transforms.ToTensor(),
                transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
            ])
        },
        # "church_encode": {
        #     "model_path": "pretrained_models/restyle_psp_church_encode.pt",
        #     "image_path": "notebooks/images/church_img.jpg",
        #     "transform": transforms.Compose([
        #         transforms.Resize((256, 256)),
        #         transforms.ToTensor(),
        #         transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])
        # },
        # "horse_encode": {
        #     "model_path": "pretrained_models/restyle_e4e_horse_encode.pt",
        #     "image_path": "notebooks/images/horse_img.jpg",
        #     "transform": transforms.Compose([
        #         transforms.Resize((256, 256)),
        #         transforms.ToTensor(),
        #         transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])
        # },
        # "afhq_wild_encode": {
        #     "model_path": "pretrained_models/restyle_psp_afhq_wild_encode.pt",
        #     "image_path": "notebooks/images/afhq_wild_img.jpg",
        #     "transform": transforms.Compose([
        #         transforms.Resize((256, 256)),
        #         transforms.ToTensor(),
        #         transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])
        # },
        # "toonify": {
        #     "model_path": "pretrained_models/restyle_psp_toonify.pt",
        #     "image_path": "notebooks/images/toonify_img.jpg",
        #     "transform": transforms.Compose([
        #         transforms.Resize((256, 256)),
        #         transforms.ToTensor(),
        #         transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])
        # },
    }

    EXPERIMENT_ARGS = EXPERIMENT_DATA_ARGS[experiment_type]

    if not os.path.exists(EXPERIMENT_ARGS['model_path']) or os.path.getsize(
            EXPERIMENT_ARGS['model_path']) < 1000000:
        print(f'Downloading ReStyle model for {experiment_type}...')
        os.system(f"wget {download_command}")
        # if google drive receives too many requests, we'll reach the quota limit and be unable to download the model
        if os.path.getsize(EXPERIMENT_ARGS['model_path']) < 1000000:
            raise ValueError(
                "Pretrained model was unable to be downloaded correctly!")
        else:
            print('Done.')
    else:
        print(f'ReStyle model for {experiment_type} already exists!')

    # MOVE INFERENCE FUNCTIONS AND PRE-DECLARATIONS OUTSIDE OF INFINITE LOOP
    def get_avg_image(net):
        avg_image = net(net.latent_avg.unsqueeze(0),
                        input_code=True,
                        randomize_noise=False,
                        return_latents=False,
                        average_code=True)[0]
        avg_image = avg_image.to('cuda').float().detach()
        if experiment_type == "cars_encode":
            avg_image = avg_image[:, 32:224, :]
        return avg_image

    from utils.inference_utils import run_on_batch

    # MOVE FUNCTION TO DISPLAY RESULTS OUTSIDE OF LOOP
    def get_coupled_results(result_batch, transformed_image):
        """
      Visualize output images from left to right (the input image is on the right)
      """
        result_tensors = result_batch[0]  # there's one image in our batch
        result_images = [
            tensor2im(result_tensors[iter_idx])
            for iter_idx in range(opts.n_iters_per_batch)
        ]
        input_im = tensor2im(transformed_image)
        res = np.array(result_images[0].resize(resize_amount))
        for idx, result in enumerate(result_images[1:]):
            res = np.concatenate(
                [res, np.array(result.resize(resize_amount))], axis=1)
        res = np.concatenate([res, input_im.resize(resize_amount)], axis=1)
        res = Image.fromarray(res)
        return res, result_images


##### ADD INFINITE LOOP ################################################################

    time_before = time.time()

    # LOAD PRETRAINED MODEL
    model_path = EXPERIMENT_ARGS['model_path']
    ckpt = torch.load(model_path, map_location='cpu')

    opts = ckpt['opts']

    # resize_amount = (256, 256) if opts.resize_outputs else (opts.output_size, opts.output_size)

    # number of output images
    opts['n_iters_per_batch'] = NUM_OUTPUT_IMAGES
    opts['resize_outputs'] = False  # generate outputs at full resolution

    # update the training options
    opts['checkpoint_path'] = model_path

    opts = Namespace(**opts)
    if experiment_type == 'horse_encode':
        net = e4e(opts)
    else:
        net = pSp(opts)

    net.eval()
    net.cuda()
    print('Model successfully loaded!')

    time_after_loading = time.time()
    print('Time to load model took {:.4f} seconds.'.format(time_after_loading -
                                                           time_before))

    # VISUALIZE INPUT
    # image_path = EXPERIMENT_DATA_ARGS[experiment_type]["image_path"]
    original_image = Image.open(image_path).convert("RGB")

    # if experiment_type == 'cars_encode':
    #     original_image = original_image.resize((192, 256))
    # else:
    #     original_image = original_image.resize((256, 256))

    # ALIGN IMAGE
    # def run_alignment(image_path):
    #     import dlib
    #     from scripts.align_faces_parallel import align_face
    #     if not os.path.exists("shape_predictor_68_face_landmarks.dat"):
    #         print('Downloading files for aligning face image...')
    #         os.system('wget http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2')
    #         os.system('bzip2 -dk shape_predictor_68_face_landmarks.dat.bz2')
    #         print('Done.')
    #     predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
    #     aligned_image = align_face(filepath=image_path, predictor=predictor)
    #     print("Aligned image has shape: {}".format(aligned_image.size))
    #     return aligned_image

    # if experiment_type in ['ffhq_encode', 'toonify']:
    #     input_image = run_alignment(image_path)
    # else:
    #     input_image = original_image
    input_image = original_image

    # PERFORM INFERENCE
    img_transforms = EXPERIMENT_ARGS['transform']
    transformed_image = img_transforms(input_image)

    with torch.no_grad():
        avg_image = get_avg_image(net)
        tic = time.time()
        result_batch, result_latents = run_on_batch(
            transformed_image.unsqueeze(0).cuda(), net, opts, avg_image)
        toc = time.time()
        print('Inference took {:.4f} seconds.'.format(toc - tic))

    # VISUALIZE RESULT

    # get results & save
    res, result_images = get_coupled_results(result_batch, transformed_image)

    time_after = time.time()
    print(
        'Time to load model, perform projection, and save out the results took {:.4f} seconds.'
        .format(time_after - time_before))

    return res, result_images