Spaces:
Running
on
Zero
Running
on
Zero
File size: 3,736 Bytes
7245cc5 961ea1f 7245cc5 961ea1f 7245cc5 961ea1f 7245cc5 f3bf944 7245cc5 961ea1f 7245cc5 bbfa81d f3bf944 6a2f159 f6c8dde 6a2f159 f6c8dde 7245cc5 961ea1f 7245cc5 6a2f159 961ea1f 7245cc5 6a2f159 7245cc5 6a2f159 7245cc5 6a2f159 7245cc5 f3bf944 7245cc5 6a2f159 a779c2b 6a1328e 6a2f159 7245cc5 6a2f159 7245cc5 6a2f159 7245cc5 63d4b61 7245cc5 6a2f159 f3bf944 7245cc5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
import os
import uuid
from pathlib import Path
import argparse
import spaces
import gradio as gr
from PIL import Image
from diffusers.utils import export_to_video
from inference import load_model, inference_on_image
# -----------------------
# 1. Load model
# -----------------------
args = argparse.Namespace()
args.blur2vid_hf_repo_path = "tedlasai/blur2vid"
args.pretrained_model_path = "THUDM/CogVideoX-2b"
args.model_config_path = "training/configs/outsidephotos.yaml"
args.video_width = 1280
args.video_height = 720
args.seed = None
pipe, model_config = load_model(args)
OUTPUT_DIR = Path("/tmp/generated_videos")
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
@spaces.GPU(timeout=300, duration=120)
def generate_video_from_image(image: Image.Image, interval_key: str, num_inference_steps: int) -> str:
"""
Wrapper for Gradio. Takes an image and returns a video path.
"""
if image is None:
raise gr.Error("Please upload an image first.")
print("Generating video")
import torch
print("CUDA:", torch.cuda.is_available())
print("Device:", torch.cuda.get_device_name(0))
print("bf16 supported:", torch.cuda.is_bf16_supported())
args.num_inference_steps = num_inference_steps
video_id = uuid.uuid4().hex
output_path = OUTPUT_DIR / f"{video_id}.mp4"
args.device = "cuda"
pipe.to(args.device)
processed_image, video = inference_on_image(pipe, image, interval_key, model_config, args)
export_to_video(video, output_path, fps=20)
if not os.path.exists(output_path):
raise gr.Error("Video generation failed: output file not found.")
return str(output_path)
with gr.Blocks(css="footer {visibility: hidden}") as demo:
gr.Markdown(
"""
# 🖼️ ➜ 🎬 Recover Motion from a Blurry Image
This demo accompanies the paper **“Generating the Past, Present, and Future from a Motion-Blurred Image”**
by Tedla *et al.*, ACM Transactions on Graphics (SIGGRAPH Asia 2025).
- 🌐 **Project page:** <https://blur2vid.github.io/>
- 💻 **Code:** <https://github.com/tedlasai/blur2vid/>
Upload a blurry image and the model will generate a short video showing the recovered motion based on your selection.
Note: The image will be resized to 1280×720. We recommend uploading landscape-oriented images.
"""
)
with gr.Row():
with gr.Column():
image_in = gr.Image(
type="pil",
label="Input image",
interactive=True,
)
with gr.Row():
tense_choice = gr.Radio(
label="Select the interval to be generated:",
choices=["present", "past, present and future"],
value="past, present and future",
interactive=True,
)
num_inference_steps = gr.Slider(
label="Number of inference steps",
minimum=4,
maximum=50,
step=1,
value=20,
info="More steps = better quality but slower. Too many steps may time out ZeroGPU.",
)
generate_btn = gr.Button("Generate video", variant="primary")
with gr.Column():
video_out = gr.Video(
label="Generated video",
format="mp4",
autoplay=True,
loop=True,
)
generate_btn.click(
fn=generate_video_from_image,
inputs=[image_in, tense_choice, num_inference_steps],
outputs=video_out,
api_name="predict",
)
if __name__ == "__main__":
demo.launch()
|