Download app.py from 3ZadeSSG/PVSNet: direct link, hf CLI and curl.
- Browser
- Download file 8.41 kB
-
https://huggingface.co/spaces/3ZadeSSG/PVSNet/resolve/main/app.py
- Command line
-
hf download hf://spaces/3ZadeSSG/PVSNet/app.py
-
curl -L -o app.py https://huggingface.co/spaces/3ZadeSSG/PVSNet/resolve/main/app.py
8.41 kB
| import gradio as gr | |
| import torch | |
| import numpy as np | |
| import cv2 | |
| import tempfile | |
| from PIL import Image | |
| import torchvision.transforms as transforms | |
| import os | |
| from huggingface_hub import hf_hub_download | |
| import huggingface_hub | |
| from models.pvsnet_model import PVSNet | |
| import helperFunctions as helper | |
| import parameters as params | |
| DEVICE = params.DEVICE | |
| def getPositionVector(x, y, z, pose_dims=3): | |
| if pose_dims == 3: | |
| vector = torch.zeros((1, 3), dtype=torch.float) | |
| vector[0][0] = (float(format(x, '.7f')) - (-0.1)) / (0.1 - (-0.1)) | |
| vector[0][1] = (float(format(y, '.7f')) - (-0.1)) / (0.1 - (-0.1)) | |
| vector[0][2] = (float(format(z, '.7f')) - (-0.1)) / (0.1 - (-0.1)) | |
| return vector | |
| else: | |
| t_min, t_max = -0.1, 0.1 | |
| r_min, r_max = -3, 3 | |
| vector = torch.zeros((1, 6), dtype=torch.float) | |
| vector[0, 0] = (x - t_min) / (t_max - t_min) | |
| vector[0, 1] = (y - t_min) / (t_max - t_min) | |
| vector[0, 2] = (z - t_min) / (t_max - t_min) | |
| vector[0, 3] = (0 - r_min) / (r_max - r_min) | |
| vector[0, 4] = (0 - r_min) / (r_max - r_min) | |
| vector[0, 5] = (0 - r_min) / (r_max - r_min) | |
| return vector | |
| def generateCircularTrajectory(radius, num_frames): | |
| angles = np.linspace(0, 2 * np.pi, num_frames, endpoint=False) | |
| return [[radius * np.cos(angle), radius * np.sin(angle), 0] for angle in angles] | |
| def generateSwingTrajectory(radius, num_frames): | |
| angles = np.linspace(0, 2 * np.pi, num_frames, endpoint=False) | |
| return [[radius * np.cos(angle), 0, radius * np.sin(angle)] for angle in angles] | |
| def create_video_from_memory(frames, fps=30): | |
| if not frames: | |
| return None | |
| height, width, _ = frames[0].shape | |
| fourcc = cv2.VideoWriter_fourcc(*'mp4v') | |
| temp_video = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") | |
| out = cv2.VideoWriter(temp_video.name, fourcc, fps, (width, height)) | |
| for frame in frames: | |
| out.write(frame) | |
| out.release() | |
| return temp_video.name | |
| def process_image(img, video_type, radius, num_frames, num_loops, dataset, resolution, architecture): | |
| if img is None: | |
| return None | |
| width, height = map(int, resolution.split('x')) | |
| min_dim = min(img.width, img.height) | |
| left = (img.width - min_dim) / 2 | |
| top = (img.height - min_dim) / 2 | |
| right = (img.width + min_dim) / 2 | |
| bottom = (img.height + min_dim) / 2 | |
| img = img.crop((left, top, right, bottom)) | |
| is_lite = (architecture == "Lite") | |
| pose_dims = 3 if dataset == "Blender" else 6 | |
| dataset_prefix = dataset.lower() | |
| arch_infix = "pvsnet_lite" if is_lite else "pvsnet" | |
| checkpoint_name = f"checkpoint_{dataset_prefix}_{arch_infix}_{resolution}.pth" | |
| try: | |
| checkpoint_path = hf_hub_download( | |
| repo_id="3ZadeSSG/PVSNet", | |
| filename=checkpoint_name | |
| ) | |
| except huggingface_hub.utils.EntryNotFoundError: | |
| raise gr.Error(f"Checkpoint {checkpoint_name} not found in Hugging Face Hub! Please select a valid combination.") | |
| except Exception as e: | |
| raise gr.Error(f"Error downloading checkpoint {checkpoint_name}: {e}") | |
| model = PVSNet(total_image_input=params.params_number_input, pose_dims=pose_dims, height=height, width=width, is_lite=is_lite) | |
| try: | |
| model = helper.load_Checkpoint(checkpoint_path, model, load_cpu=True) | |
| except Exception as e: | |
| print(f"Error loading checkpoint {checkpoint_path}: {e}") | |
| raise gr.Error(f"Error loading checkpoint {checkpoint_path}: {e}") | |
| model.to(DEVICE) | |
| model.eval() | |
| transform = transforms.Compose([ | |
| transforms.Resize((height, width)), | |
| transforms.ToTensor() | |
| ]) | |
| img_input = img.convert('RGB') | |
| img_input = transform(img_input).unsqueeze(0).to(DEVICE) | |
| if video_type == "Circle": | |
| raw_traj = generateCircularTrajectory(radius, num_frames) | |
| trajectory = [(p[0], p[1], 0) for p in raw_traj] | |
| elif video_type == "Swing": | |
| raw_traj = generateSwingTrajectory(radius, num_frames) | |
| trajectory = raw_traj | |
| else: | |
| raw_traj = generateCircularTrajectory(radius, num_frames) | |
| trajectory = [(p[0], p[1], 0) for p in raw_traj] | |
| view_frames = [] | |
| for x, y, z in trajectory: | |
| pos = getPositionVector(x, y, z, pose_dims=pose_dims).unsqueeze(0).to(DEVICE) | |
| with torch.no_grad(): | |
| predicted_img = model(img_input, pos) | |
| p_img = predicted_img[0].detach().cpu().permute(1, 2, 0).numpy() | |
| p_img = np.clip(p_img, 0, 1) | |
| p_img = (p_img * 255).astype(np.uint8) | |
| p_img_bgr = cv2.cvtColor(p_img, cv2.COLOR_RGB2BGR) | |
| view_frames.append(p_img_bgr) | |
| view_frames = view_frames * int(num_loops) | |
| fps = 60 | |
| view_video_path = create_video_from_memory(view_frames, fps=fps) | |
| return view_video_path | |
| with gr.Blocks(title="PVSNet", theme="default") as demo: | |
| gr.Markdown( | |
| """ | |
| ## PVSNet: Real-Time Position-Aware View Synthesis from Single-View Input | |
| * Upload an image and get a mini video showing capability of novel view synthesis. | |
| **Note:** Huggingface demo is running on CPU so inference speeds will be slow. Inference might take around 2-5 mins depending on resolution and model. We recomment runnning it on 256x256 and with Lite model. | |
| ### Head to our [Project Page](https://realistic3d-miun.github.io/PVSNet/) for more details about the models | |
| """) | |
| with gr.Row(): | |
| with gr.Column(): | |
| img_input = gr.Image(type="pil", label="Input Image", height=256) | |
| with gr.Group(): | |
| dataset_type = gr.Dropdown(["Blender", "COCO"], label="Dataset Model", value="COCO") | |
| resolution_type = gr.Dropdown(["256x256", "512x512"], label="Resolution", value="256x256") | |
| architecture_type = gr.Dropdown(["Regular", "Lite"], label="Architecture", value="Lite") | |
| video_type = gr.Dropdown(["Circle", "Swing"], label="Trajectory Type", value="Swing") | |
| with gr.Accordion("Advanced Settings", open=False): | |
| radius = gr.Slider(0.01, 0.1, value=0.06, label="Motion Radius") | |
| num_frames = gr.Slider(10, 120, value=60, step=1, label="Frames per Loop") | |
| num_loops = gr.Slider(1, 6, value=3, step=1, label="Number of Loops") | |
| submit_btn = gr.Button("Generate", variant="primary") | |
| with gr.Column(): | |
| video_output = gr.Video(label="Generated View Video", height=256) | |
| submit_btn.click( | |
| fn=process_image, | |
| inputs=[img_input, video_type, radius, num_frames, num_loops, dataset_type, resolution_type, architecture_type], | |
| outputs=[video_output] | |
| ) | |
| gr.Markdown("### Example Images: Click to Load") | |
| import glob | |
| blender_imgs = sorted(glob.glob("./sample_images/blender/*")) | |
| coco_imgs = sorted(glob.glob("./sample_images/coco/*")) | |
| rw_imgs = sorted(glob.glob("./sample_images/real_world/*")) | |
| def create_grid(imgs, title, cols=4): | |
| gr.Markdown(title) | |
| image_components = [] | |
| for i in range(0, len(imgs), cols): | |
| with gr.Row(): | |
| for img_path in imgs[i:i+cols]: | |
| comp = gr.Image(img_path, label=os.path.basename(img_path), height=150, interactive=False, show_label=True) | |
| image_components.append((comp, img_path)) | |
| return image_components | |
| with gr.Column(): | |
| b_comps = create_grid(blender_imgs, "#### Blender Models (Loads Blender Lite 256x256 by Default)") | |
| c_comps = create_grid(coco_imgs, "#### COCO Models (Loads COCO 256x256 Lite by Default)") | |
| r_comps = create_grid(rw_imgs, "#### Real World Models (Loads COCO 256x256 Lite by Default)") | |
| for comp, path in b_comps: | |
| comp.select(fn=lambda p=path: (Image.open(p), "Blender", "256x256", "Lite"), outputs=[img_input, dataset_type, resolution_type, architecture_type]) | |
| for comp, path in c_comps: | |
| comp.select(fn=lambda p=path: (Image.open(p), "COCO", "256x256", "Lite"), outputs=[img_input, dataset_type, resolution_type, architecture_type]) | |
| for comp, path in r_comps: | |
| comp.select(fn=lambda p=path: (Image.open(p), "COCO", "256x256", "Lite"), outputs=[img_input, dataset_type, resolution_type, architecture_type]) | |
| if __name__ == "__main__": | |
| demo.launch() | |