def main(args, config, sample_index):
    cuda = cnn_utils.check_cuda(config)
    model = cnn_utils.load_model_and_weights(args, config)
    if cuda:
        model = model.cuda()

    model.eval()

    # Create output directory
    base_dir = os.path.join(config['PATH']['output_dir'], 'warped')
    if not os.path.isdir(base_dir):
        pathlib.Path(base_dir).mkdir(parents=True, exist_ok=True)
    save_dir = get_sub_dir_for_saving(base_dir)

    start_time = time.time()
    file_path = os.path.join(config['PATH']['hdf5_dir'],
                             config['PATH']['hdf5_name'])
    with h5py.File(file_path, mode='r', libver='latest') as hdf5_file:
        depth_grp = hdf5_file['val']['disparity']
        SNUM = sample_index
        depth_images = torch.squeeze(
            torch.tensor(depth_grp['images'][SNUM], dtype=torch.float32))

        colour_grp = hdf5_file['val']['colour']
        colour_images = torch.tensor(colour_grp['images'][SNUM],
                                     dtype=torch.float32)

        sample = {
            'depth': depth_images,
            'colour': colour_images,
            'grid_size': depth_images.shape[0]
        }

        warped = data_transform.center_normalise(sample)
        im_input = warped['inputs'].unsqueeze_(0)

        if cuda:
            im_input = im_input.cuda()

        output = model(im_input)

        time_taken = time.time() - start_time
        print("Time taken was {:4f}s".format(time_taken))
        grid_size = 64

        psnr_accumulator = (0, 0, 0)
        ssim_accumulator = (0, 0, 0)

        print("Saving output to", save_dir)

        output = torch.squeeze(denormalise_lf(output))
        cpu_output = np.around(output.cpu().detach().numpy()).astype(np.uint8)

        if (not args.no_eval) or args.get_diff:
            ground_truth = np.around(
                denormalise_lf(colour_images).numpy()).astype(np.uint8)

        grid_len = int(math.sqrt(grid_size))
        for i in range(grid_size):
            row, col = i // grid_len, i % grid_len

            file_name = 'Colour{}{}.png'.format(row, col)
            save_location = os.path.join(save_dir, file_name)
            if i == 0:
                print("Saving images of size ", cpu_output[i].shape)
            image_warping.save_array_as_image(cpu_output[i], save_location)

            if args.get_diff:
                colour = ground_truth[i]
                diff = image_warping.get_diff_image(colour, cpu_output[i])
                #diff = get_diff_image_floatint(res, colour)
                file_name = 'Diff{}{}.png'.format(row, col)
                save_location = os.path.join(save_dir, file_name)
                image_warping.save_array_as_image(diff, save_location)

            if not args.no_eval:
                img = ground_truth[i]
                file_name = 'GT_Colour{}{}.png'.format(row, col)
                save_location = os.path.join(save_dir, file_name)
                image_warping.save_array_as_image(img, save_location)
                psnr = evaluate.my_psnr(cpu_output[i], img)
                ssim = evaluate.ssim(cpu_output[i], img)
                psnr_accumulator = welford.update(psnr_accumulator, psnr)
                ssim_accumulator = welford.update(ssim_accumulator, ssim)

        psnr_mean, psnr_var, _ = welford.finalize(psnr_accumulator)
        ssim_mean, ssim_var, _ = welford.finalize(ssim_accumulator)
        print("For cnn, psnr average {:5f}, stddev {:5f}".format(
            psnr_mean, math.sqrt(psnr_var)))
        print("For cnn, ssim average {:5f}, stddev {:5f}".format(
            ssim_mean, math.sqrt(ssim_var)))
def process(self):
    """Perform the model warping and output an image grid"""
    if self.getPropertyByIdentifier("off").value:
        print("Image warping is currently turned off")
        return 1

    start_time = time.time()

    if self.getPropertyByIdentifier("display_input").value:
        im_data = []
        for name in INPORT_LIST:
            im_data.append(self.getInport(name).getData())
        out_image = Image(OUT_SIZE, DTYPE)
        out = resize(
            im_data[0].colorLayers[0].data.transpose(1, 0, 2),
            OUT_SIZE_LIST)

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            inter_out = img_as_ubyte(out)
        out_image.colorLayers[0].data = inter_out
        self.getOutport("outport").setData(out_image)
        return 1

    if model is None:
        print("No model for synthesis")
        return -1

    cam = inviwopy.app.network.EntryExitPoints.camera
    im_data = []
    for name in INPORT_LIST:
        im_data.append(self.getInport(name).getData())
    for im in im_data: 
        if not (im_data[0].dimensions == im.dimensions):
            print("Operation is incompatible with images of different size")
            print("Size 1: ", im_data[0].dimensions)
            print("Size 2: ", im.dimensions)
            return -1
     
    out_image = Image(OUT_SIZE, DTYPE)
    sample_image = Image(SAMPLE_SIZE, DTYPE)
    im_colour = []
    for idx, name in enumerate(INPORT_LIST):
        im_colour.append(im_data[idx].colorLayers[0].data[:, :, :3].transpose(1, 0, 2))
    
    im_depth = []
    near = cam.nearPlane
    far = cam.farPlane
    baseline = 0.5
    focal_length = cam.projectionMatrix[0][0]
    fov = cam.fov.value
    
    for idx, name in enumerate(INPORT_LIST):
        im_depth.append(
            conversions.depth_to_pixel_disp(
                im_data[idx].depth.data.transpose(1, 0),
                near=near, far=far, baseline=baseline,
                focal_length=focal_length,
                fov=fov,
                image_pixel_size=float(im_data[0].dimensions[0]))
        )
    
    sample = {
        'depth': torch.tensor(im_depth[0], dtype=torch.float32).unsqueeze_(0), 
        'colour': torch.tensor(im_colour[0], dtype=torch.float32).unsqueeze_(0),
        'grid_size': GRID_SIZE}

    warped = data_transform.transform_inviwo_to_warped(sample)
    desired_shape = warped['shape']
    im_input = warped['inputs'].unsqueeze_(0)
    
    if cuda:
        im_input = im_input.cuda()

    model.eval()
    output = model(im_input)
    output += im_input
    output = torch.clamp(output, 0.0, 1.0)
    
    end_time = time.time() - start_time
    print("Grid light field rendered in {:4f}".format(end_time))
    out_unstack = data_transform.undo_remap(
        output[0], desired_shape, dtype=torch.float32)
    out_colour = cnn_utils.transform_lf_to_torch(
        out_unstack
    )

    output_grid = vutils.make_grid(
                    out_colour, nrow=8, range=(0, 1), normalize=False,
                    padding=2, pad_value=1.0)

    output_grid = resize(
        output_grid.cpu().detach().numpy().transpose(1, 2, 0),
        OUT_SIZE_LIST)

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        inter_out = img_as_ubyte(output_grid)

    #inter_out = denormalise_lf(output_grid)
    #inter_out = inter_out.cpu().detach().numpy().astype(np.uint8).transpose(1, 2, 0)
    # Add an alpha channel here
    shape = tuple(OUT_SIZE_LIST) + (4,)
    final_out = np.full(shape, 255, np.uint8)
    final_out[:, :, :3] = inter_out
    
    shape = tuple(SAMPLE_SIZE_LIST) + (4,)
    sample_out = np.full(shape, 255, np.uint8)
    sample_out[:, :, :3] = np.around(
        data_transform.denormalise_lf(
            out_unstack).cpu().detach().numpy()
    ).astype(np.uint8)[self.getPropertyByIdentifier("sample_num").value]

    # Inviwo expects a uint8 here
    out_image.colorLayers[0].data = final_out
    sample_image.colorLayers[0].data = sample_out
    self.getOutport("outport").setData(out_image)
    self.getOutport("sample").setData(sample_image)

    end_time = time.time() - start_time
    print("Overall render time was {:4f}".format(end_time))
def do_one_demo(args, config, hdf5_file, model, sample_num, cuda):
    depth_grp = hdf5_file['val']['disparity']
    # Create output directory

    if not args.no_save:
        base_dir = os.path.join(config['PATH']['output_dir'], 'warped')
        if not os.path.isdir(base_dir):
            pathlib.Path(base_dir).mkdir(parents=True, exist_ok=True)
        save_dir = get_sub_dir_for_saving(base_dir)

    model.eval()
    SNUM = sample_num
    start_time = time.time()
    print("Working on image", SNUM)
    depth_images = torch.squeeze(
        torch.tensor(depth_grp['images'][SNUM], dtype=torch.float32))

    colour_grp = hdf5_file['val']['colour']
    colour_images = torch.tensor(colour_grp['images'][SNUM],
                                 dtype=torch.float32)

    sample = {
        'depth': depth_images,
        'colour': colour_images,
        'grid_size': depth_images.shape[0]
    }

    warped = data_transform.transform_to_warped(sample)
    warped = data_transform.stack(warped, 65)
    im_input = warped['inputs'].unsqueeze_(0)

    if cuda:
        im_input = im_input.cuda()

    output = model(im_input)
    im_input = im_input[:, :-3]
    output += im_input
    output = torch.clamp(output, 0.0, 1.0)

    time_taken = time.time() - start_time
    print("Time taken was {:.0f}s".format(time_taken))
    grid_size = 64

    psnr_accumulator = (0, 0, 0)
    ssim_accumulator = (0, 0, 0)

    if not args.no_save:
        print("Saving output to", save_dir)
        no_cnn_dir = os.path.join(save_dir, "no_cnn")
        cnn_dir = os.path.join(save_dir, "cnn")
        os.mkdir(cnn_dir)
        os.mkdir(no_cnn_dir)

    output = torch.squeeze(denormalise_lf(output))
    output = data_transform.torch_unstack(output)
    im_input = im_input.cpu().detach()
    cpu_output = np.around(output.cpu().detach().numpy()).astype(np.uint8)

    if (not args.no_eval) or args.get_diff:
        ground_truth = np.around(denormalise_lf(colour_images).numpy()).astype(
            np.uint8)
    grid_len = int(math.sqrt(grid_size))
    for i in range(grid_size):
        row, col = i // grid_len, i % grid_len

        if not args.no_save:
            file_name = 'Colour{}{}.png'.format(row, col)
            save_location = os.path.join(cnn_dir, file_name)
            if i == 0:
                print("Saving images of size ", cpu_output[i].shape)
            image_warping.save_array_as_image(cpu_output[i], save_location)

        if args.get_diff and not args.no_save:
            colour = ground_truth[i]
            diff = image_warping.get_diff_image(colour, cpu_output[i])
            #diff = get_diff_image_floatint(res, colour)
            file_name = 'Diff{}{}.png'.format(row, col)
            save_location = os.path.join(cnn_dir, file_name)
            image_warping.save_array_as_image(diff, save_location)

        if not args.no_eval:
            img = ground_truth[i]

            if not args.no_save:
                file_name = 'GT_Colour{}{}.png'.format(row, col)
                save_location = os.path.join(save_dir, file_name)
                image_warping.save_array_as_image(img, save_location)
            psnr = evaluate.my_psnr(cpu_output[i], img)
            ssim = evaluate.ssim(cpu_output[i], img)
            psnr_accumulator = welford.update(psnr_accumulator, psnr)
            ssim_accumulator = welford.update(ssim_accumulator, ssim)

    psnr_mean, psnr_var, _ = welford.finalize(psnr_accumulator)
    ssim_mean, ssim_var, _ = welford.finalize(ssim_accumulator)
    print("For cnn, psnr average {:5f}, stddev {:5f}".format(
        psnr_mean, math.sqrt(psnr_var)))
    print("For cnn, ssim average {:5f}, stddev {:5f}".format(
        ssim_mean, math.sqrt(ssim_var)))
    psnr1 = psnr_mean
    ssim1 = ssim_mean

    psnr_accumulator = (0, 0, 0)
    ssim_accumulator = (0, 0, 0)

    psnr2, ssim2 = 0, 0
    if args.no_cnn:
        squeeze_input = torch.squeeze(denormalise_lf(im_input))
        squeeze_input = data_transform.torch_unstack(squeeze_input)
        cpu_input = np.around(squeeze_input.numpy()).astype(np.uint8)
        for i in range(grid_size):
            row, col = i // grid_len, i % grid_len

            if not args.no_save:
                file_name = 'Colour{}{}.png'.format(row, col)
                save_location = os.path.join(no_cnn_dir, file_name)
                if i == 0:
                    print("Saving images of size ", cpu_input[i].shape)
                image_warping.save_array_as_image(cpu_input[i], save_location)

            if args.get_diff and not args.no_save:
                colour = ground_truth[i]
                diff = image_warping.get_diff_image(colour, cpu_output[i])
                #diff = get_diff_image_floatint(res, colour)
                file_name = 'Diff{}{}.png'.format(row, col)
                save_location = os.path.join(no_cnn_dir, file_name)
                image_warping.save_array_as_image(diff, save_location)

            if not args.no_eval:
                img = ground_truth[i]
                psnr = evaluate.my_psnr(cpu_input[i], img)
                ssim = evaluate.ssim(cpu_input[i], img)
                psnr_accumulator = welford.update(psnr_accumulator, psnr)
                ssim_accumulator = welford.update(ssim_accumulator, ssim)

        psnr_mean, psnr_var, _ = welford.finalize(psnr_accumulator)
        ssim_mean, ssim_var, _ = welford.finalize(ssim_accumulator)
        print("For no cnn, psnr average {:5f}, stddev {:5f}".format(
            psnr_mean, math.sqrt(psnr_var)))
        print("For no cnn, ssim average {:5f}, stddev {:5f}".format(
            ssim_mean, math.sqrt(ssim_var)))
        psnr2, ssim2 = psnr_mean, ssim_mean

    return psnr1, ssim1, psnr2, ssim2