def render_blender(view_type='nearest', scenes=['ficus'], num_src_views=3, ckpt='base-3src-dense.tar', source_split='train', target_split='val', select_index=None, is_fixed=False, is_source_target_overlap=False):
    (psnr_all, ssim_all, LPIPS_vgg_all) = ([], [], [])
    for (i_scene, scene) in enumerate(scenes):
        (psnr, ssim, LPIPS_vgg) = ([], [], [])
        cmd = f'--datadir /mnt/hdd/mvsnerf_data/nerf_synthetic/{scene}           --dataset_name blender_src --white_bkgd         --net_type v0 --ckpt ./ckpts/{ckpt} --num_src_views {num_src_views}'
        save_dir = f'/mnt/hdd/youngsun/mvsnerf_timing/results/{ckpt[:(- 4)]}/blender-{num_src_views}-'
        if is_fixed:
            save_dir += 'fixed-'
        save_dir += f'{view_type}-'
        save_dir += f'{source_split}-{target_split}/{scene}'
        args = config_parser(cmd.split())
        args.use_viewdirs = True
        args.N_samples = 128
        args.feat_dim = (8 + (4 * num_src_views))
        if (0 == i_scene):
            (render_kwargs_train, render_kwargs_test, start, grad_vars) = create_nerf_mvs(args, use_mvs=True, dir_embedder=False, pts_embedder=True)
            filter_keys(render_kwargs_train)
            MVSNet = render_kwargs_train['network_mvs']
            render_kwargs_train.pop('network_mvs')
        datadir = args.datadir
        datatype = 'train'
        pad = 16
        args.chunk = 5120
        print('============> rendering dataset <===================')
        dataset_source = dataset_dict[args.dataset_name](args, split=source_split)
        dataset_target = dataset_dict[args.dataset_name](args, split=target_split, select_index=select_index)
        target_idx = dataset_target.img_idx
        save_as_image = True
        os.makedirs(save_dir, exist_ok=True)
        MVSNet.train()
        MVSNet = MVSNet.cuda()
        with torch.no_grad():
            try:
                tqdm._instances.clear()
            except Exception:
                pass
            for (i, batch) in enumerate(tqdm(dataset_target)):
                torch.cuda.empty_cache()
                (rays, img) = decode_batch(batch)
                rays = rays.squeeze().to(device)
                img = img.squeeze().cpu().numpy()
                if is_fixed:
                    if (i == 0):
                        if (select_index is not None):
                            pair_idx = get_pair_idx(source_dataset=dataset_source, target_position=dataset_target.poses[[(len(select_index) // 2)], :3, 3], N_views=args.num_src_views, view_type=view_type)
                        else:
                            pair_idx = get_pair_idx(source_dataset=dataset_source, target_position=dataset_target.poses[[50], :3, 3], N_views=args.num_src_views, view_type=view_type)
                    (imgs_source, proj_mats, near_far_source, pose_source) = dataset_source.read_source_views(pair_idx=pair_idx, device=device)
                else:
                    (imgs_source, proj_mats, near_far_source, pose_source) = get_source_imgs(source_dataset=dataset_source, target_position=dataset_target.poses[[i], :3, 3], N_views=args.num_src_views, device=device, view_type=view_type)
                (volume_feature, _, _) = MVSNet(imgs_source, proj_mats, near_far_source, pad=pad)
                imgs_source = unpreprocess(imgs_source)
                N_rays_all = rays.shape[0]
                (rgb_rays, depth_rays_preds) = ([], [])
                for chunk_idx in range(((N_rays_all // args.chunk) + int(((N_rays_all % args.chunk) > 0)))):
                    (xyz_coarse_sampled, rays_o, rays_d, z_vals) = ray_marcher(rays[(chunk_idx * args.chunk):((chunk_idx + 1) * args.chunk)], N_samples=args.N_samples)
                    (H, W) = img.shape[:2]
                    inv_scale = torch.tensor([(W - 1), (H - 1)]).to(device)
                    (w2c_ref, intrinsic_ref) = (pose_source['w2cs'][0], pose_source['intrinsics'][0].clone())
                    intrinsic_ref[:2] *= (args.imgScale_test / args.imgScale_train)
                    xyz_NDC = get_ndc_coordinate(w2c_ref, intrinsic_ref, xyz_coarse_sampled, inv_scale, near=near_far_source[0], far=near_far_source[1], pad=(pad * args.imgScale_test))
                    (rgb, disp, acc, depth_pred, alpha, extras) = rendering(args, pose_source, xyz_coarse_sampled, xyz_NDC, z_vals, rays_o, rays_d, volume_feature, imgs_source, **render_kwargs_train)
                    (rgb, depth_pred) = (torch.clamp(rgb.cpu(), 0, 1.0).numpy(), depth_pred.cpu().numpy())
                    rgb_rays.append(rgb)
                    depth_rays_preds.append(depth_pred)
                depth_rays_preds = np.concatenate(depth_rays_preds).reshape(H, W)
                (depth_rays_preds, _) = visualize_depth_numpy(depth_rays_preds, near_far_source)
                rgb_rays = np.concatenate(rgb_rays).reshape(H, W, 3)
                img_vis = np.concatenate(((img * 255), (rgb_rays * 255), depth_rays_preds), axis=1)
                img_vis = np.concatenate((torch.cat(torch.split((imgs_source * 255), ([1] * num_src_views), dim=1), (- 1)).squeeze().permute(1, 2, 0).cpu().numpy(), img_vis), axis=1)
                if save_as_image:
                    imageio.imwrite(f'{save_dir}/{scene}_{target_idx[i]:03d}.png', img_vis.astype('uint8'))
                else:
                    rgbs.append(img_vis.astype('uint8'))
                (H_crop, W_crop) = (np.array(rgb_rays.shape[:2]) // 10)
                img = img[H_crop:(- H_crop), W_crop:(- W_crop)]
                rgb_rays = rgb_rays[H_crop:(- H_crop), W_crop:(- W_crop)]
                psnr.append(mse2psnr(np.mean(((rgb_rays - img) ** 2))))
                ssim.append(structural_similarity(rgb_rays, img, multichannel=True))
                img_tensor = ((torch.from_numpy(rgb_rays)[None].permute(0, 3, 1, 2).float() * 2) - 1.0)
                img_gt_tensor = ((torch.from_numpy(img)[None].permute(0, 3, 1, 2).float() * 2) - 1.0)
                LPIPS_vgg.append(loss_fn_vgg(img_tensor, img_gt_tensor).item())
            print(f'=====> scene: {scene} mean psnr {np.mean(psnr)} ssim: {np.mean(ssim)} lpips: {np.mean(LPIPS_vgg)}')
            psnr_all.append(psnr)
            ssim_all.append(ssim)
            LPIPS_vgg_all.append(LPIPS_vgg)
        if (not save_as_image):
            imageio.mimwrite(f'{save_dir}/{scene}_spiral.mp4', np.stack(rgbs), fps=20, quality=10)
    print(f'=====> all mean psnr {np.mean(psnr_all)} ssim: {np.mean(ssim_all)} lpips: {np.mean(LPIPS_vgg_all)}')
def render_blender(view_type='nearest', scenes=['ficus'], num_src_views=3, ckpt='base-3src-dense.tar', source_split='train', target_split='val', select_index=None, is_fixed=False, is_source_target_overlap=False):
    (psnr_all, ssim_all, LPIPS_vgg_all) = ([], [], [])
    for (i_scene, scene) in enumerate(scenes):
        (psnr, ssim, LPIPS_vgg) = ([], [], [])
        cmd = f'--datadir /mnt/hdd/mvsnerf_data/nerf_synthetic/{scene}           --dataset_name blender_src --white_bkgd         --net_type v0 --ckpt ./ckpts/{ckpt} --num_src_views {num_src_views}'
        save_dir = f'/mnt/hdd/youngsun/mvsnerf_timing/results/{ckpt[:(- 4)]}/blender-{num_src_views}-'
        if is_fixed:
            save_dir += 'fixed-'
        save_dir += f'{view_type}-'
        save_dir += f'{source_split}-{target_split}/{scene}'
        args = config_parser(cmd.split())
        args.use_viewdirs = True
        args.N_samples = 128
        args.feat_dim = (8 + (4 * num_src_views))
        if (0 == i_scene):
            (render_kwargs_train, render_kwargs_test, start, grad_vars) = create_nerf_mvs(args, use_mvs=True, dir_embedder=False, pts_embedder=True)
            filter_keys(render_kwargs_train)
            MVSNet = render_kwargs_train['network_mvs']
            render_kwargs_train.pop('network_mvs')
        datadir = args.datadir
        datatype = 'train'
        pad = 16
        args.chunk = 5120
        print('============> rendering dataset <===================')
        dataset_source = dataset_dict[args.dataset_name](args, split=source_split)
        dataset_target = dataset_dict[args.dataset_name](args, split=target_split, select_index=select_index)
        target_idx = dataset_target.img_idx
        save_as_image = True
        os.makedirs(save_dir, exist_ok=True)
        MVSNet.train()
        MVSNet = MVSNet.cuda()
        with torch.no_grad():
            try:
                tqdm._instances.clear()
            except Exception:
                pass
            for (i, batch) in enumerate(tqdm(dataset_target)):
                torch.cuda.empty_cache()
                (rays, img) = decode_batch(batch)
                rays = rays.squeeze().to(device)
                img = img.squeeze().cpu().numpy()
                if is_fixed:
                    if (i == 0):
                        if (select_index is not None):
                            pair_idx = get_pair_idx(source_dataset=dataset_source, target_position=dataset_target.poses[[(len(select_index) // 2)], :3, 3], N_views=args.num_src_views, view_type=view_type)
                        else:
                            pair_idx = get_pair_idx(source_dataset=dataset_source, target_position=dataset_target.poses[[50], :3, 3], N_views=args.num_src_views, view_type=view_type)
                    (imgs_source, proj_mats, near_far_source, pose_source) = dataset_source.read_source_views(pair_idx=pair_idx, device=device)
                else:
                    (imgs_source, proj_mats, near_far_source, pose_source) = get_source_imgs(source_dataset=dataset_source, target_position=dataset_target.poses[[i], :3, 3], N_views=args.num_src_views, device=device, view_type=view_type)
                (volume_feature, _, _) = MVSNet(imgs_source, proj_mats, near_far_source, pad=pad)
                imgs_source = unpreprocess(imgs_source)
                N_rays_all = rays.shape[0]
                (rgb_rays, depth_rays_preds) = ([], [])
                for chunk_idx in range(((N_rays_all // args.chunk) + int(((N_rays_all % args.chunk) > 0)))):
                    (xyz_coarse_sampled, rays_o, rays_d, z_vals) = ray_marcher(rays[(chunk_idx * args.chunk):((chunk_idx + 1) * args.chunk)], N_samples=args.N_samples)
                    (H, W) = img.shape[:2]
                    inv_scale = torch.tensor([(W - 1), (H - 1)]).to(device)
                    (w2c_ref, intrinsic_ref) = (pose_source['w2cs'][0], pose_source['intrinsics'][0].clone())
                    intrinsic_ref[:2] *= (args.imgScale_test / args.imgScale_train)
                    xyz_NDC = get_ndc_coordinate(w2c_ref, intrinsic_ref, xyz_coarse_sampled, inv_scale, near=near_far_source[0], far=near_far_source[1], pad=(pad * args.imgScale_test))
                    (rgb, disp, acc, depth_pred, alpha, extras) = rendering(args, pose_source, xyz_coarse_sampled, xyz_NDC, z_vals, rays_o, rays_d, volume_feature, imgs_source, **render_kwargs_train)
                    (rgb, depth_pred) = (torch.clamp(rgb.cpu(), 0, 1.0).numpy(), depth_pred.cpu().numpy())
                    rgb_rays.append(rgb)
                    depth_rays_preds.append(depth_pred)
                depth_rays_preds = np.concatenate(depth_rays_preds).reshape(H, W)
                (depth_rays_preds, _) = visualize_depth_numpy(depth_rays_preds, near_far_source)
                rgb_rays = np.concatenate(rgb_rays).reshape(H, W, 3)
                img_vis = np.concatenate(((img * 255), (rgb_rays * 255), depth_rays_preds), axis=1)
                img_vis = np.concatenate((torch.cat(torch.split((imgs_source * 255), ([1] * num_src_views), dim=1), (- 1)).squeeze().permute(1, 2, 0).cpu().numpy(), img_vis), axis=1)
                if save_as_image:
                    imageio.imwrite(f'{save_dir}/{scene}_{target_idx[i]:03d}.png', img_vis.astype('uint8'))
                else:
                    rgbs.append(img_vis.astype('uint8'))
                (H_crop, W_crop) = (np.array(rgb_rays.shape[:2]) // 10)
                img = img[H_crop:(- H_crop), W_crop:(- W_crop)]
                rgb_rays = rgb_rays[H_crop:(- H_crop), W_crop:(- W_crop)]
                psnr.append(mse2psnr(np.mean(((rgb_rays - img) ** 2))))
                ssim.append(structural_similarity(rgb_rays, img, multichannel=True))
                img_tensor = ((torch.from_numpy(rgb_rays)[None].permute(0, 3, 1, 2).float() * 2) - 1.0)
                img_gt_tensor = ((torch.from_numpy(img)[None].permute(0, 3, 1, 2).float() * 2) - 1.0)
                LPIPS_vgg.append(loss_fn_vgg(img_tensor, img_gt_tensor).item())
            print(f'=====> scene: {scene} mean psnr {np.mean(psnr)} ssim: {np.mean(ssim)} lpips: {np.mean(LPIPS_vgg)}')
            psnr_all.append(psnr)
            ssim_all.append(ssim)
            LPIPS_vgg_all.append(LPIPS_vgg)
        if (not save_as_image):
            imageio.mimwrite(f'{save_dir}/{scene}_spiral.mp4', np.stack(rgbs), fps=20, quality=10)
    print(f'=====> all mean psnr {np.mean(psnr_all)} ssim: {np.mean(ssim_all)} lpips: {np.mean(LPIPS_vgg_all)}')