From 37aa6cf9ce299db529ea4c78f7985b2b4355ec01 Mon Sep 17 00:00:00 2001 From: Fill Date: Mon, 5 Jan 2026 22:09:14 -0800 Subject: [PATCH] Initial release - FL DiffVSR video super-resolution nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 4x video upscaling with temporal coherence using Stream-DiffVSR - Model Loader node with precision/device options and xformers support - Upscaler node with chunked processing for memory efficiency - Automatic model download from HuggingFace - Text-guided upscaling support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .gitignore | 75 +++ README.md | 82 +++ __init__.py | 30 + assets/readme.png | Bin 0 -> 316987 bytes core/__init__.py | 1 + core/model_manager.py | 114 ++++ core/pipeline_wrapper.py | 310 ++++++++++ nodes/__init__.py | 1 + nodes/model_loader.py | 83 +++ nodes/upscaler.py | 159 +++++ pyproject.toml | 26 + requirements.txt | 25 + stream_diffvsr/__init__.py | 1 + stream_diffvsr/pipeline/__init__.py | 3 + .../pipeline/stream_diffvsr_pipeline.py | 582 ++++++++++++++++++ stream_diffvsr/scheduler/__init__.py | 3 + stream_diffvsr/scheduler/ddim_scheduler.py | 298 +++++++++ .../temporal_autoencoder/__init__.py | 3 + .../temporal_autoencoder/autoencoder_tiny.py | 278 +++++++++ .../temporal_autoencoder/models/__init__.py | 1 + .../models/unets/__init__.py | 3 + .../models/unets/unet_2d_blocks.py | 98 +++ stream_diffvsr/temporal_autoencoder/vae.py | 138 +++++ stream_diffvsr/util/__init__.py | 3 + stream_diffvsr/util/flow_utils.py | 100 +++ 25 files changed, 2417 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 __init__.py create mode 100644 assets/readme.png create mode 100644 core/__init__.py create mode 100644 core/model_manager.py create mode 100644 core/pipeline_wrapper.py create mode 100644 nodes/__init__.py create mode 100644 nodes/model_loader.py create mode 100644 nodes/upscaler.py create mode 100644 pyproject.toml create mode 100644 requirements.txt create mode 100644 stream_diffvsr/__init__.py create mode 100644 stream_diffvsr/pipeline/__init__.py create mode 100644 stream_diffvsr/pipeline/stream_diffvsr_pipeline.py create mode 100644 stream_diffvsr/scheduler/__init__.py create mode 100644 stream_diffvsr/scheduler/ddim_scheduler.py create mode 100644 stream_diffvsr/temporal_autoencoder/__init__.py create mode 100644 stream_diffvsr/temporal_autoencoder/autoencoder_tiny.py create mode 100644 stream_diffvsr/temporal_autoencoder/models/__init__.py create mode 100644 stream_diffvsr/temporal_autoencoder/models/unets/__init__.py create mode 100644 stream_diffvsr/temporal_autoencoder/models/unets/unet_2d_blocks.py create mode 100644 stream_diffvsr/temporal_autoencoder/vae.py create mode 100644 stream_diffvsr/util/__init__.py create mode 100644 stream_diffvsr/util/flow_utils.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1372a1d --- /dev/null +++ b/.gitignore @@ -0,0 +1,75 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual environments +venv/ +ENV/ +env/ +.venv/ + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ +.project +.pydevproject +.settings/ + +# OS +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Logs +*.log +logs/ + +# Model files (downloaded separately) +*.safetensors +*.bin +*.ckpt +*.pt +*.pth + +# Temporary files +*.tmp +*.temp +.cache/ + +# Jupyter +.ipynb_checkpoints/ +*.ipynb + +# Testing +.pytest_cache/ +.coverage +htmlcov/ + +# Distribution +*.tar.gz +*.zip diff --git a/README.md b/README.md new file mode 100644 index 0000000..1f73862 --- /dev/null +++ b/README.md @@ -0,0 +1,82 @@ +# FL DiffVSR + +Diffusion-based video super-resolution nodes for ComfyUI powered by Stream-DiffVSR. Upscale videos 4x with temporal coherence for smooth, artifact-free results. + +[![Stream-DiffVSR](https://img.shields.io/badge/Stream--DiffVSR-Original%20Paper-blue?style=for-the-badge&logo=arxiv&logoColor=white)](https://arxiv.org/abs/2512.23709) +[![Patreon](https://img.shields.io/badge/Patreon-Support%20Me-F96854?style=for-the-badge&logo=patreon&logoColor=white)](https://www.patreon.com/Machinedelusions) + +![Workflow Preview](assets/readme.png) + +## Features + +- **4x Video Upscaling** - Upscale video frames to 4x resolution with high fidelity +- **Temporal Coherence** - Maintains consistency across frames for flicker-free results +- **Diffusion-Based** - Leverages diffusion models for superior detail reconstruction +- **Text Guidance** - Optional prompt support for guided upscaling +- **Memory Efficient** - Chunked processing and xformers support for lower VRAM usage +- **Automatic Downloads** - Models download automatically from HuggingFace on first use + +## Nodes + +| Node | Description | +|------|-------------| +| **FL DiffVSR Load Model** | Downloads and loads Stream-DiffVSR model from HuggingFace | +| **FL DiffVSR Upscale** | Upscales video frames with temporal coherence | + +## Installation + +### ComfyUI Manager +Search for "FL DiffVSR" and install. + +### Manual +```bash +cd ComfyUI/custom_nodes +git clone https://github.com/filliptm/ComfyUI-FL-DiffVSR.git +cd ComfyUI-FL-DiffVSR +pip install -r requirements.txt +``` + +## Quick Start + +1. Add **FL DiffVSR Load Model** node and configure precision/device settings +2. Connect to **FL DiffVSR Upscale** node +3. Feed your video frames as an IMAGE batch +4. Adjust inference steps (4 recommended for speed/quality balance) +5. Generate upscaled frames + +## Parameters + +### Model Loader +| Parameter | Options | Description | +|-----------|---------|-------------| +| precision | auto, fp32, fp16, bf16 | Model precision (auto selects fp16 for GPU) | +| device | auto, cuda, cpu | Target device for inference | +| enable_xformers | true/false | Enable memory-efficient attention | + +### Upscaler +| Parameter | Default | Description | +|-----------|---------|-------------| +| inference_steps | 4 | Denoising steps (higher = better quality, slower) | +| guidance_scale | 0.0 | CFG scale (0 = no guidance) | +| chunk_size | 8 | Frames per batch (lower = less VRAM) | +| prompt | "" | Optional text guidance | +| negative_prompt | "" | Optional negative prompt | +| seed | -1 | Random seed (-1 for random) | + +## Requirements + +- Python 3.10+ +- 8GB VRAM minimum (16GB+ recommended for larger videos) +- NVIDIA GPU recommended (CPU supported but slow) + +## Model + +The Stream-DiffVSR model downloads automatically to `ComfyUI/models/stream_diffvsr/` on first use (~2GB). + +| Model | Source | Size | +|-------|--------|------| +| Stream-DiffVSR | Jamichsu/Stream-DiffVSR | ~2GB | + +## License + +Apache 2.0 diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e4d14c4 --- /dev/null +++ b/__init__.py @@ -0,0 +1,30 @@ +""" +FL DiffVSR - ComfyUI Node Pack for Stream-DiffVSR Video Super-Resolution + +A standalone ComfyUI node pack for 4x video upscaling with temporal coherence +using diffusion-based super-resolution. + +Based on Stream-DiffVSR: https://arxiv.org/abs/2512.23709 +Model: Jamichsu/Stream-DiffVSR (HuggingFace) +""" + +from .nodes.model_loader import FL_DiffVSR_LoadModel +from .nodes.upscaler import FL_DiffVSR_Upscale + + +NODE_CLASS_MAPPINGS = { + "FL_DiffVSR_LoadModel": FL_DiffVSR_LoadModel, + "FL_DiffVSR_Upscale": FL_DiffVSR_Upscale, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "FL_DiffVSR_LoadModel": "FL DiffVSR Load Model", + "FL_DiffVSR_Upscale": "FL DiffVSR Upscale", +} + +__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"] + +print("\n" + "=" * 50) +print("FL DiffVSR - Video Super-Resolution Node Pack") +print("4x Upscaling with Temporal Coherence") +print("=" * 50 + "\n") diff --git a/assets/readme.png b/assets/readme.png new file mode 100644 index 0000000000000000000000000000000000000000..3971e272cb4f6188bed5a686e3539f44f344e76b GIT binary patch literal 316987 zcmeFa2V9fOwl1*C)?0RibfA%rB~B)Io>pS}0_&b{ZH`@iS^;SVLg+V^8C4zCwHHBgj?I*vf|)4 z>lbRsX{7g=FV5uIlVdkltbX~R`(+--#S=GHyyP!AeRkyo9?RX2TB{T9+wpU?)*En_ zZ+^5!eN_7XCYr@@bz^?6qx#)1?`6`eC_1KX8lkdb-H(OyrTATz{gAKa}qO`jt$m^XK-qSW{~_O9)9 zHdRyD(p$>$HT25Ud=8Gp5QXT=yPsLK-U|~DUpFNxSr^i$A*mDIM?Vt(K#{NPAjkf+ zJBqzp9Qqx5bRplYPi$&ddldUX)oUw>cH{ANf)@EF z>P3&QP+4Jd^%4KnjCbF5HIuUEecQ6@3pdL6r+tOoDSMm$#c0c3B|j}6Mzpk=$&27L zKAU}ePilF!7N38zZB4dR*=DNJ6!(VshH~TAse44S_v%F9mC77EuiZ$vB66T+t8ba) zqUOxB?|}d9&pcU4+vd%WUpf&{tY*X&E>{}yfELFyx4hO622kZ1a+<0LOM>Lga73f5yIB(WqUu(l=H~VW0_HvPnC{uZwOExV~TX>g`X@1++GbKIA_6=xDy$xG(MN(@6o2Xs)^s z*oOmCUGbA4^~c>#DwJvIf*{&*%D~eU2 zkGT4U4nenm)jP4N+t%a5x`-8aiX!}9S9l)dShu!k_s+fdwjJiSj$cD85YSp9`{By@ zl~o@cv)10?h%Pyr#WlKy^Egy-vyQjZ*CRJL6+T?e_b4pUtmo|ZUa|W4*>&4r?D2Rc zW8u}h=g_)UQz!2~J-c`Fx#M4+Xq|d=_Q{Sv|B9Z+EpV6dA&rhTue|$>2{%q z61`VEH>h!$-G_g0?QwDALTy4nqV$l~>EB;b67*HuoVSAK$a=l?`yM!c-29RIqp=&r zg}0m6@6@iu?G3!${*q<4dYyZDdQbPN^-5ZBPRV4)pAsEb*CN+3_vB5(CXeRN!(qeHE

@a~tN8hGU26JLNXn1l|Z# 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 str: + """Get the path to the stream_diffvsr models directory.""" + models_base = folder_paths.models_dir + models_dir = os.path.join(models_base, self.MODEL_FOLDER_NAME) + os.makedirs(models_dir, exist_ok=True) + return models_dir + + def get_model_path(self) -> str: + """Get the path where models are/will be stored.""" + return self.models_dir + + def check_models_exist(self) -> bool: + """Check if all required model files exist.""" + required_dirs = [ + "unet", + "controlnet", + "vae", + "text_encoder", + "tokenizer", + "scheduler", + ] + + for dir_name in required_dirs: + dir_path = os.path.join(self.models_dir, dir_name) + if not os.path.exists(dir_path): + return False + + # Check for at least one file in each directory + if not any(os.scandir(dir_path)): + return False + + return True + + def download_models(self, force: bool = False) -> str: + """ + Download all model components from HuggingFace. + + Args: + force: If True, download even if models already exist + + Returns: + Path to the downloaded models + """ + if self.check_models_exist() and not force: + print(f"Stream-DiffVSR models already exist at {self.models_dir}") + return self.models_dir + + try: + from huggingface_hub import snapshot_download + + print(f"Downloading Stream-DiffVSR models from {self.HF_REPO_ID}...") + print(f"Target directory: {self.models_dir}") + + local_dir = snapshot_download( + repo_id=self.HF_REPO_ID, + local_dir=self.models_dir, + local_dir_use_symlinks=False, + ignore_patterns=[ + "*.md", + "*.txt", + ".git*", + "*.py", + "*.yml", + "*.yaml", + ], + ) + + print(f"Models downloaded successfully to: {local_dir}") + return local_dir + + except ImportError: + raise ImportError( + "huggingface_hub is required to download models. " + "Please install it with: pip install huggingface_hub" + ) + except Exception as e: + raise RuntimeError(f"Failed to download Stream-DiffVSR models: {e}") + + def get_component_path(self, component: str) -> str: + """Get the path to a specific model component.""" + return os.path.join(self.models_dir, component) + + +# Singleton instance +_model_manager: Optional[ModelManager] = None + + +def get_model_manager() -> ModelManager: + """Get the singleton ModelManager instance.""" + global _model_manager + if _model_manager is None: + _model_manager = ModelManager() + return _model_manager diff --git a/core/pipeline_wrapper.py b/core/pipeline_wrapper.py new file mode 100644 index 0000000..512b18c --- /dev/null +++ b/core/pipeline_wrapper.py @@ -0,0 +1,310 @@ +""" +Pipeline Wrapper for FL DiffVSR +Wraps the Stream-DiffVSR pipeline for ComfyUI integration. +""" + +import torch +import torch.nn.functional as F +from PIL import Image +import numpy as np +from typing import Optional, List, Union + +from torchvision.models.optical_flow import raft_large, Raft_Large_Weights + + +class StreamDiffVSRWrapper: + """ + Wrapper around StreamDiffVSRPipeline for ComfyUI integration. + Handles model loading, optical flow, and frame-by-frame processing. + """ + + def __init__( + self, + model_path: str, + device: torch.device, + dtype: torch.dtype, + enable_xformers: bool = True, + ): + self.model_path = model_path + self.device = device + self.dtype = dtype + + # Load pipeline components + self._load_pipeline(enable_xformers) + + # Load optical flow model (RAFT) + self._load_flow_model() + + # Temporal state + self.prev_frame_rgb = None + self.frame_count = 0 + + def _load_pipeline(self, enable_xformers: bool): + """Load the Stream-DiffVSR pipeline.""" + from diffusers import UNet2DConditionModel, ControlNetModel + from transformers import CLIPTextModel, CLIPTokenizer + + # Import local modules + from ..stream_diffvsr.temporal_autoencoder.autoencoder_tiny import TemporalAutoencoderTiny + from ..stream_diffvsr.pipeline.stream_diffvsr_pipeline import StreamDiffVSRPipeline + from ..stream_diffvsr.scheduler.ddim_scheduler import DDIMScheduler + + print("Loading Stream-DiffVSR pipeline components...") + + # Load UNet + print(" Loading UNet...") + self.unet = UNet2DConditionModel.from_pretrained( + self.model_path, subfolder="unet", torch_dtype=self.dtype + ).to(self.device) + + # Load ControlNet + print(" Loading ControlNet...") + self.controlnet = ControlNetModel.from_pretrained( + self.model_path, subfolder="controlnet", torch_dtype=self.dtype + ).to(self.device) + + # Load Temporal VAE + print(" Loading Temporal VAE...") + self.vae = TemporalAutoencoderTiny.from_pretrained( + self.model_path, subfolder="vae", torch_dtype=self.dtype + ).to(self.device) + + # Load text encoder and tokenizer + print(" Loading Text Encoder...") + self.text_encoder = CLIPTextModel.from_pretrained( + self.model_path, subfolder="text_encoder", torch_dtype=self.dtype + ).to(self.device) + + # Load tokenizer - the Stream-DiffVSR model's tokenizer is incomplete (missing merges.txt) + # So we load from openai/clip-vit-large-patch14 which is the base CLIP model + print(" Loading Tokenizer...") + try: + self.tokenizer = CLIPTokenizer.from_pretrained( + self.model_path, subfolder="tokenizer" + ) + except (TypeError, OSError) as e: + print(f" Local tokenizer incomplete, loading from openai/clip-vit-large-patch14...") + self.tokenizer = CLIPTokenizer.from_pretrained( + "openai/clip-vit-large-patch14" + ) + + # Load scheduler + print(" Loading Scheduler...") + self.scheduler = DDIMScheduler.from_pretrained( + self.model_path, subfolder="scheduler" + ) + + # Create pipeline + self.pipeline = StreamDiffVSRPipeline( + vae=self.vae, + text_encoder=self.text_encoder, + tokenizer=self.tokenizer, + unet=self.unet, + controlnet=self.controlnet, + scheduler=self.scheduler, + safety_checker=None, + feature_extractor=None, + requires_safety_checker=False, + ) + + # Enable memory optimizations + if enable_xformers: + try: + self.pipeline.enable_xformers_memory_efficient_attention() + print(" xformers memory efficient attention enabled") + except Exception as e: + print(f" Could not enable xformers: {e}") + + print("Stream-DiffVSR pipeline loaded successfully!") + + def _load_flow_model(self): + """Load RAFT optical flow model.""" + print("Loading RAFT optical flow model...") + self.flow_model = raft_large(weights=Raft_Large_Weights.DEFAULT) + self.flow_model = self.flow_model.to(self.device).eval() + self.flow_model.requires_grad_(False) + print("RAFT model loaded successfully!") + + def reset_temporal_state(self): + """Reset temporal state for new video sequence.""" + self.prev_frame_rgb = None + self.frame_count = 0 + self.vae.reset_temporal_condition() + + def process_frames_chunked( + self, + images: List[Image.Image], + chunk_size: int = 8, + prompt: str = "", + negative_prompt: str = "", + num_inference_steps: int = 4, + guidance_scale: float = 0.0, + generator: Optional[torch.Generator] = None, + progress_callback: Optional[callable] = None, + ) -> List[Image.Image]: + """ + Process frames in memory-efficient chunks. + + Args: + images: List of PIL Images to upscale + chunk_size: Number of frames per chunk (lower = less VRAM) + prompt: Text prompt for guidance + negative_prompt: Negative text prompt + num_inference_steps: Number of denoising steps + guidance_scale: CFG scale + generator: Random generator for reproducibility + progress_callback: Optional callback for progress updates + + Returns: + List of upscaled PIL Images + """ + all_results = [] + prev_frame_rgb = None + prev_upscaled_for_flow = None + total_frames = len(images) + + # Calculate number of chunks + num_chunks = (total_frames + chunk_size - 1) // chunk_size + + print(f" Processing {total_frames} frames in {num_chunks} chunk(s) of up to {chunk_size} frames each") + + for chunk_idx in range(num_chunks): + start_idx = chunk_idx * chunk_size + end_idx = min(start_idx + chunk_size, total_frames) + chunk_images = images[start_idx:end_idx] + + print(f" Processing chunk {chunk_idx + 1}/{num_chunks} (frames {start_idx}-{end_idx - 1})") + + # Reset temporal state but pass previous frame context + self.vae.reset_temporal_condition() + + # Process chunk with previous frame state for continuity + output, prev_frame_rgb, prev_upscaled_for_flow = self.pipeline( + prompt=prompt, + images=chunk_images, + num_inference_steps=num_inference_steps, + guidance_scale=guidance_scale, + negative_prompt=negative_prompt if negative_prompt else None, + generator=generator, + of_model=self.flow_model, + of_rescale_factor=1, + output_type="pil", + callback=progress_callback, + callback_steps=1, + # Pass previous frame state for chunk continuity + prev_frame_rgb=prev_frame_rgb, + prev_upscaled_for_flow=prev_upscaled_for_flow, + # Pass frame offset for progress callback + frame_offset=start_idx, + ) + + # Extract results from this chunk + for img_list in output.images: + if isinstance(img_list, list): + all_results.extend(img_list) + else: + all_results.append(img_list) + + # Clear VRAM between chunks + torch.cuda.empty_cache() + + return all_results + + def process_frames( + self, + images: List[Image.Image], + prompt: str = "", + negative_prompt: str = "", + num_inference_steps: int = 4, + guidance_scale: float = 0.0, + generator: Optional[torch.Generator] = None, + progress_callback: Optional[callable] = None, + chunk_size: int = 0, + ) -> List[Image.Image]: + """ + Process a list of frames through the pipeline. + + Args: + images: List of PIL Images to upscale + prompt: Text prompt for guidance + negative_prompt: Negative text prompt + num_inference_steps: Number of denoising steps + guidance_scale: CFG scale + generator: Random generator for reproducibility + progress_callback: Optional callback for progress updates + chunk_size: Number of frames per chunk (0 = process all at once) + + Returns: + List of upscaled PIL Images + """ + # Use chunked processing if chunk_size > 0 and we have more frames than chunk_size + if chunk_size > 0 and len(images) > chunk_size: + return self.process_frames_chunked( + images=images, + chunk_size=chunk_size, + prompt=prompt, + negative_prompt=negative_prompt, + num_inference_steps=num_inference_steps, + guidance_scale=guidance_scale, + generator=generator, + progress_callback=progress_callback, + ) + + # Reset temporal state for new sequence + self.reset_temporal_state() + + # Run pipeline (original behavior for small batches or chunk_size=0) + output, _, _ = self.pipeline( + prompt=prompt, + images=images, + num_inference_steps=num_inference_steps, + guidance_scale=guidance_scale, + negative_prompt=negative_prompt if negative_prompt else None, + generator=generator, + of_model=self.flow_model, + of_rescale_factor=1, + output_type="pil", + callback=progress_callback, + callback_steps=1, + prev_frame_rgb=None, + prev_upscaled_for_flow=None, + frame_offset=0, + ) + + # Extract results + results = [] + for img_list in output.images: + if isinstance(img_list, list): + results.extend(img_list) + else: + results.append(img_list) + + return results + + def to(self, device: torch.device): + """Move all models to specified device.""" + self.device = device + self.unet = self.unet.to(device) + self.controlnet = self.controlnet.to(device) + self.vae = self.vae.to(device) + self.text_encoder = self.text_encoder.to(device) + self.flow_model = self.flow_model.to(device) + return self + + +def tensor_to_pil(tensor: torch.Tensor) -> Image.Image: + """ + Convert a ComfyUI tensor [H, W, C] (0-1 range) to PIL Image. + """ + arr = tensor.cpu().numpy() + arr = (arr * 255).clip(0, 255).astype(np.uint8) + return Image.fromarray(arr, mode='RGB') + + +def pil_to_tensor(pil_image: Image.Image) -> torch.Tensor: + """ + Convert PIL Image to ComfyUI tensor [1, H, W, C] (0-1 range). + """ + arr = np.array(pil_image).astype(np.float32) / 255.0 + tensor = torch.from_numpy(arr) + return tensor.unsqueeze(0) # [H, W, C] -> [1, H, W, C] diff --git a/nodes/__init__.py b/nodes/__init__.py new file mode 100644 index 0000000..1fc4c8d --- /dev/null +++ b/nodes/__init__.py @@ -0,0 +1 @@ +# FL DiffVSR Nodes diff --git a/nodes/model_loader.py b/nodes/model_loader.py new file mode 100644 index 0000000..241ad50 --- /dev/null +++ b/nodes/model_loader.py @@ -0,0 +1,83 @@ +""" +FL DiffVSR Model Loader Node +Downloads and loads Stream-DiffVSR model from HuggingFace. +""" + +import torch + +from ..core.model_manager import get_model_manager +from ..core.pipeline_wrapper import StreamDiffVSRWrapper + + +class FL_DiffVSR_LoadModel: + """ + Load Stream-DiffVSR model from HuggingFace. + Downloads model components to ComfyUI/models/stream_diffvsr/ on first use. + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "precision": (["auto", "fp32", "fp16", "bf16"], {"default": "auto"}), + "device": (["auto", "cuda", "cpu"], {"default": "auto"}), + }, + "optional": { + "enable_xformers": ("BOOLEAN", {"default": True}), + } + } + + RETURN_TYPES = ("FL_DIFFVSR_MODEL",) + RETURN_NAMES = ("model",) + FUNCTION = "load_model" + CATEGORY = "FL DiffVSR" + + def load_model(self, precision: str, device: str, enable_xformers: bool = True): + """Load the Stream-DiffVSR pipeline.""" + + # Get model manager + model_manager = get_model_manager() + + # Download models if needed + if not model_manager.check_models_exist(): + print("Stream-DiffVSR models not found. Downloading from HuggingFace...") + model_manager.download_models() + + model_path = model_manager.get_model_path() + + # Determine device + if device == "auto": + if torch.cuda.is_available(): + target_device = torch.device("cuda") + else: + target_device = torch.device("cpu") + else: + target_device = torch.device(device) + + # Determine dtype + if precision == "auto": + if target_device.type == "cuda": + dtype = torch.float16 + else: + dtype = torch.float32 + elif precision == "fp16": + dtype = torch.float16 + elif precision == "bf16": + dtype = torch.bfloat16 + else: + dtype = torch.float32 + + # Only enable xformers on CUDA + use_xformers = enable_xformers and target_device.type == "cuda" + + # Load pipeline wrapper + wrapper = StreamDiffVSRWrapper( + model_path=model_path, + device=target_device, + dtype=dtype, + enable_xformers=use_xformers, + ) + + print(f"Stream-DiffVSR model loaded on {target_device} with {dtype}") + + return (wrapper,) diff --git a/nodes/upscaler.py b/nodes/upscaler.py new file mode 100644 index 0000000..a594625 --- /dev/null +++ b/nodes/upscaler.py @@ -0,0 +1,159 @@ +""" +FL DiffVSR Upscaler Node +Upscales video frames using Stream-DiffVSR with temporal coherence. +""" + +import torch +from PIL import Image +import numpy as np + +import comfy.utils + +from ..core.pipeline_wrapper import StreamDiffVSRWrapper, tensor_to_pil, pil_to_tensor + + +class FL_DiffVSR_Upscale: + """ + Upscale video frames using Stream-DiffVSR. + Processes frames sequentially with temporal coherence. + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "model": ("FL_DIFFVSR_MODEL",), + "images": ("IMAGE",), + "inference_steps": ("INT", { + "default": 4, + "min": 1, + "max": 50, + "step": 1, + "tooltip": "Number of denoising steps (4 recommended for speed/quality balance)" + }), + "guidance_scale": ("FLOAT", { + "default": 0.0, + "min": 0.0, + "max": 20.0, + "step": 0.5, + "tooltip": "Classifier-free guidance scale (0 = no guidance)" + }), + "chunk_size": ("INT", { + "default": 8, + "min": 1, + "max": 64, + "step": 1, + "tooltip": "Number of frames to process at once (lower = less VRAM, 0 = process all at once)" + }), + }, + "optional": { + "prompt": ("STRING", { + "default": "", + "multiline": False, + "tooltip": "Optional text prompt for guidance" + }), + "negative_prompt": ("STRING", { + "default": "", + "multiline": False, + "tooltip": "Optional negative prompt" + }), + "seed": ("INT", { + "default": -1, + "min": -1, + "max": 0xffffffffffffffff, + "tooltip": "-1 for random seed" + }), + } + } + + RETURN_TYPES = ("IMAGE",) + RETURN_NAMES = ("upscaled_images",) + FUNCTION = "upscale" + CATEGORY = "FL DiffVSR" + + def upscale( + self, + model: StreamDiffVSRWrapper, + images: torch.Tensor, + inference_steps: int, + guidance_scale: float, + chunk_size: int = 8, + prompt: str = "", + negative_prompt: str = "", + seed: int = -1, + ): + """ + Upscale images using Stream-DiffVSR pipeline. + + Args: + model: StreamDiffVSRWrapper instance + images: Tensor of shape [B, H, W, C] in ComfyUI format (0-1 range) + inference_steps: Number of denoising steps + guidance_scale: CFG scale + chunk_size: Number of frames per chunk (lower = less VRAM) + prompt: Text prompt for guidance + negative_prompt: Negative prompt + seed: Random seed (-1 for random) + + Returns: + Upscaled images tensor [B, H*4, W*4, C] + """ + num_frames = images.shape[0] + total_steps = num_frames * inference_steps + print(f"FL DiffVSR: Processing {num_frames} frames with {inference_steps} steps ({total_steps} total steps)...") + if chunk_size > 0: + print(f"FL DiffVSR: Using chunk_size={chunk_size} for VRAM-efficient processing") + + # Set seed if specified + generator = None + if seed != -1: + generator = torch.Generator(device=model.device).manual_seed(seed) + + # Convert ComfyUI tensors to PIL images + pil_images = [] + for i in range(num_frames): + frame = images[i] # [H, W, C] + pil_img = tensor_to_pil(frame) + pil_images.append(pil_img) + + # Setup ComfyUI progress bar + pbar = comfy.utils.ProgressBar(total_steps) + current_progress = [0] # Use list to allow modification in closure + + def progress_callback(frame_idx, step_idx, total_frames, total_steps_per_frame, latents): + # Calculate overall progress + overall_step = frame_idx * total_steps_per_frame + step_idx + 1 + steps_to_update = overall_step - current_progress[0] + if steps_to_update > 0: + pbar.update(steps_to_update) + current_progress[0] = overall_step + + # Process through pipeline with chunking support + upscaled_pil = model.process_frames( + images=pil_images, + prompt=prompt, + negative_prompt=negative_prompt, + num_inference_steps=inference_steps, + guidance_scale=guidance_scale, + generator=generator, + progress_callback=progress_callback, + chunk_size=chunk_size, + ) + + # Ensure progress bar completes + remaining = total_steps - current_progress[0] + if remaining > 0: + pbar.update(remaining) + + # Convert back to ComfyUI tensors + upscaled_tensors = [] + for pil_img in upscaled_pil: + tensor = pil_to_tensor(pil_img) # [1, H, W, C] + upscaled_tensors.append(tensor) + + # Concatenate all frames [B, H*4, W*4, C] + output = torch.cat(upscaled_tensors, dim=0) + + print(f"FL DiffVSR: Upscaling complete. Output shape: {list(output.shape)}") + + return (output,) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8d89187 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,26 @@ +[project] +name = "comfyui-fl-diffvsr" +description = "FL DiffVSR - Diffusion-based video super-resolution nodes for ComfyUI. Features 4x upscaling with temporal coherence using Stream-DiffVSR for smooth, artifact-free video enhancement. Supports text-guided upscaling, chunked processing for memory efficiency, and automatic model downloading from HuggingFace." +version = "1.0.0" +license = "Apache-2.0" +dependencies = [ + "torch>=2.0.0", + "torchvision>=0.15.0", + "diffusers>=0.21.0", + "transformers>=4.30.0", + "safetensors>=0.3.0", + "huggingface_hub>=0.16.0", + "accelerate>=0.20.0", + "Pillow>=9.0.0", + "numpy>=1.20.0", + "xformers>=0.0.20", + "einops>=0.6.0" +] + +[project.urls] +Repository = "https://github.com/filliptm/ComfyUI-FL-DiffVSR" + +[tool.comfy] +PublisherId = "machinedelusions" +DisplayName = "FL DiffVSR" +Icon = "" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..521d794 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,25 @@ +# FL DiffVSR Requirements +# Core dependencies for Stream-DiffVSR video super-resolution + +# Core ML frameworks +torch>=2.0.0 +torchvision>=0.15.0 + +# Diffusers and transformers +diffusers>=0.21.0 +transformers>=4.30.0 + +# Model loading +safetensors>=0.3.0 +huggingface_hub>=0.16.0 +accelerate>=0.20.0 + +# Image processing +Pillow>=9.0.0 +numpy>=1.20.0 + +# Optional: Memory efficient attention (recommended) +xformers>=0.0.20 + +# Tensor operations +einops>=0.6.0 diff --git a/stream_diffvsr/__init__.py b/stream_diffvsr/__init__.py new file mode 100644 index 0000000..a188440 --- /dev/null +++ b/stream_diffvsr/__init__.py @@ -0,0 +1 @@ +# Stream-DiffVSR adapted source diff --git a/stream_diffvsr/pipeline/__init__.py b/stream_diffvsr/pipeline/__init__.py new file mode 100644 index 0000000..7280e4f --- /dev/null +++ b/stream_diffvsr/pipeline/__init__.py @@ -0,0 +1,3 @@ +from .stream_diffvsr_pipeline import StreamDiffVSRPipeline + +__all__ = ["StreamDiffVSRPipeline"] diff --git a/stream_diffvsr/pipeline/stream_diffvsr_pipeline.py b/stream_diffvsr/pipeline/stream_diffvsr_pipeline.py new file mode 100644 index 0000000..6bdf487 --- /dev/null +++ b/stream_diffvsr/pipeline/stream_diffvsr_pipeline.py @@ -0,0 +1,582 @@ +# Copyright 2023 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import inspect +from typing import Any, Callable, Dict, List, Optional, Tuple, Union + +import numpy as np +import PIL.Image +import torch +import torch.nn.functional as F +import torchvision.transforms as T +from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer + +from diffusers.image_processor import PipelineImageInput, VaeImageProcessor +from diffusers.loaders import FromSingleFileMixin, LoraLoaderMixin, TextualInversionLoaderMixin +from diffusers.models import AutoencoderKL, ControlNetModel, UNet2DConditionModel +from diffusers.schedulers import KarrasDiffusionSchedulers +from diffusers.utils import ( + deprecate, + is_accelerate_available, + is_accelerate_version, + logging, +) +from diffusers.utils.torch_utils import randn_tensor, is_compiled_module +from diffusers.pipelines import DiffusionPipeline +from diffusers.pipelines.controlnet import MultiControlNetModel +from diffusers.pipelines.stable_diffusion import StableDiffusionPipelineOutput, StableDiffusionSafetyChecker + +from ..util import flow_utils as of +from ..temporal_autoencoder.autoencoder_tiny import TemporalAutoencoderTiny +from ..scheduler.ddim_scheduler import DDIMScheduler + + +logger = logging.get_logger(__name__) + + +class StreamDiffVSRPipeline( + DiffusionPipeline, TextualInversionLoaderMixin, LoraLoaderMixin, FromSingleFileMixin +): + """ + Stream-DiffVSR Pipeline for video super-resolution. + + Args: + vae: Temporal VAE model for encoding/decoding + text_encoder: CLIP text encoder + tokenizer: CLIP tokenizer + unet: UNet2DConditionModel for denoising + controlnet: ControlNet for temporal conditioning + scheduler: DDIM scheduler + safety_checker: Optional safety checker + feature_extractor: Optional feature extractor + """ + _optional_components = ["safety_checker", "feature_extractor"] + + def __init__( + self, + vae: Union[AutoencoderKL, TemporalAutoencoderTiny], + text_encoder: CLIPTextModel, + tokenizer: CLIPTokenizer, + unet: UNet2DConditionModel, + controlnet: Union[ControlNetModel, List[ControlNetModel], Tuple[ControlNetModel], MultiControlNetModel], + scheduler: Union[KarrasDiffusionSchedulers, DDIMScheduler], + safety_checker: StableDiffusionSafetyChecker, + feature_extractor: CLIPImageProcessor, + requires_safety_checker: bool = True, + ): + super().__init__() + + if safety_checker is None and requires_safety_checker: + logger.warning( + f"You have disabled the safety checker for {self.__class__} by passing `safety_checker=None`." + ) + + if safety_checker is not None and feature_extractor is None: + raise ValueError( + "Make sure to define a feature extractor when loading {self.__class__} if you want to use the safety checker." + ) + + if isinstance(controlnet, (list, tuple)): + controlnet = MultiControlNetModel(controlnet) + + self.register_modules( + vae=vae, + text_encoder=text_encoder, + tokenizer=tokenizer, + unet=unet, + controlnet=controlnet, + scheduler=scheduler, + safety_checker=safety_checker, + feature_extractor=feature_extractor, + ) + self.vae_scale_factor = 2 ** (len(self.vae.config.block_out_channels) - 1) + self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor, do_convert_rgb=True) + self.control_image_processor = VaeImageProcessor( + vae_scale_factor=self.vae_scale_factor, do_convert_rgb=True, do_normalize=True + ) + self.register_to_config(requires_safety_checker=requires_safety_checker) + + def enable_vae_slicing(self): + self.vae.enable_slicing() + + def disable_vae_slicing(self): + self.vae.disable_slicing() + + def enable_vae_tiling(self): + self.vae.enable_tiling() + + def disable_vae_tiling(self): + self.vae.disable_tiling() + + def enable_model_cpu_offload(self, gpu_id=0): + if is_accelerate_available() and is_accelerate_version(">=", "0.17.0.dev0"): + from accelerate import cpu_offload_with_hook + else: + raise ImportError("`enable_model_cpu_offload` requires `accelerate v0.17.0` or higher.") + + device = torch.device(f"cuda:{gpu_id}") + + hook = None + for cpu_offloaded_model in [self.text_encoder, self.unet, self.vae]: + _, hook = cpu_offload_with_hook(cpu_offloaded_model, device, prev_module_hook=hook) + + if self.safety_checker is not None: + _, hook = cpu_offload_with_hook(self.safety_checker, device, prev_module_hook=hook) + + cpu_offload_with_hook(self.controlnet, device) + self.final_offload_hook = hook + + def encode_prompt( + self, + prompt, + device, + num_images_per_prompt, + do_classifier_free_guidance, + negative_prompt=None, + prompt_embeds: Optional[torch.FloatTensor] = None, + negative_prompt_embeds: Optional[torch.FloatTensor] = None, + lora_scale: Optional[float] = None, + ): + if lora_scale is not None and isinstance(self, LoraLoaderMixin): + self._lora_scale = lora_scale + + if prompt is not None and isinstance(prompt, str): + batch_size = 1 + elif prompt is not None and isinstance(prompt, list): + batch_size = len(prompt) + else: + batch_size = prompt_embeds.shape[0] + + if prompt_embeds is None: + if isinstance(self, TextualInversionLoaderMixin): + prompt = self.maybe_convert_prompt(prompt, self.tokenizer) + + text_inputs = self.tokenizer( + prompt, + padding="max_length", + max_length=self.tokenizer.model_max_length, + truncation=True, + return_tensors="pt", + ) + text_input_ids = text_inputs.input_ids + + if hasattr(self.text_encoder.config, "use_attention_mask") and self.text_encoder.config.use_attention_mask: + attention_mask = text_inputs.attention_mask.to(device) + else: + attention_mask = None + + prompt_embeds = self.text_encoder( + text_input_ids.to(device), + attention_mask=attention_mask, + ) + prompt_embeds = prompt_embeds[0] + + if self.text_encoder is not None: + prompt_embeds_dtype = self.text_encoder.dtype + elif self.unet is not None: + prompt_embeds_dtype = self.unet.dtype + else: + prompt_embeds_dtype = prompt_embeds.dtype + + prompt_embeds = prompt_embeds.to(dtype=prompt_embeds_dtype, device=device) + + bs_embed, seq_len, _ = prompt_embeds.shape + prompt_embeds = prompt_embeds.repeat(1, num_images_per_prompt, 1) + prompt_embeds = prompt_embeds.view(bs_embed * num_images_per_prompt, seq_len, -1) + + if do_classifier_free_guidance and negative_prompt_embeds is None: + uncond_tokens: List[str] + if negative_prompt is None: + uncond_tokens = [""] * batch_size + elif isinstance(negative_prompt, str): + uncond_tokens = [negative_prompt] + else: + uncond_tokens = negative_prompt + + if isinstance(self, TextualInversionLoaderMixin): + uncond_tokens = self.maybe_convert_prompt(uncond_tokens, self.tokenizer) + + max_length = prompt_embeds.shape[1] + uncond_input = self.tokenizer( + uncond_tokens, + padding="max_length", + max_length=max_length, + truncation=True, + return_tensors="pt", + ) + + if hasattr(self.text_encoder.config, "use_attention_mask") and self.text_encoder.config.use_attention_mask: + attention_mask = uncond_input.attention_mask.to(device) + else: + attention_mask = None + + negative_prompt_embeds = self.text_encoder( + uncond_input.input_ids.to(device), + attention_mask=attention_mask, + ) + negative_prompt_embeds = negative_prompt_embeds[0] + + if do_classifier_free_guidance: + seq_len = negative_prompt_embeds.shape[1] + negative_prompt_embeds = negative_prompt_embeds.to(dtype=prompt_embeds_dtype, device=device) + negative_prompt_embeds = negative_prompt_embeds.repeat(1, num_images_per_prompt, 1) + negative_prompt_embeds = negative_prompt_embeds.view(batch_size * num_images_per_prompt, seq_len, -1) + + return prompt_embeds, negative_prompt_embeds + + def prepare_extra_step_kwargs(self, generator, eta): + accepts_eta = "eta" in set(inspect.signature(self.scheduler.step).parameters.keys()) + extra_step_kwargs = {} + if accepts_eta: + extra_step_kwargs["eta"] = eta + + accepts_generator = "generator" in set(inspect.signature(self.scheduler.step).parameters.keys()) + if accepts_generator: + extra_step_kwargs["generator"] = generator + return extra_step_kwargs + + def prepare_latents(self, batch_size, num_channels_latents, height, width, dtype, device, generator, latents=None): + shape = (batch_size, num_channels_latents, height // self.vae_scale_factor, width // self.vae_scale_factor) + if isinstance(generator, list) and len(generator) != batch_size: + raise ValueError( + f"You have passed a list of generators of length {len(generator)}, but requested an effective batch" + f" size of {batch_size}." + ) + + if latents is None: + latents = randn_tensor(shape, generator=generator, device=device, dtype=dtype) + else: + latents = latents.to(device) + + latents = latents * self.scheduler.init_noise_sigma + return latents + + def compute_flows(self, of_model, images, rescale_factor=1): + print('Computing forward flows...') + forward_flows = [] + for i in range(1, len(images)): + # RAFT optical flow model requires float32 input + prev_image = images[i - 1].float() + cur_image = images[i].float() + fflow = of.get_flow(of_model, cur_image, prev_image, rescale_factor=rescale_factor) + forward_flows.append(fflow) + return forward_flows + + def compute_single_flow(self, of_model, prev_image, cur_image, rescale_factor=1): + """Compute optical flow between two adjacent frames. + + To save VRAM, we compute flow at 1/4 resolution and upscale it back. + This is much more memory efficient for high-resolution inputs. + """ + # RAFT optical flow model requires float32 input + prev_image_f32 = prev_image.float() + cur_image_f32 = cur_image.float() + + # Downscale images for RAFT to save VRAM (RAFT is very memory hungry at high res) + # Use 1/2 resolution for flow computation (better quality than 1/4) + flow_scale = 2 + _, _, h, w = prev_image_f32.shape + small_h, small_w = h // flow_scale, w // flow_scale + + prev_small = F.interpolate(prev_image_f32, size=(small_h, small_w), mode='bilinear', align_corners=False) + cur_small = F.interpolate(cur_image_f32, size=(small_h, small_w), mode='bilinear', align_corners=False) + + # Compute flow at lower resolution + fflow_small = of.get_flow(of_model, cur_small, prev_small, rescale_factor=rescale_factor) + + # Upscale flow back to original resolution and scale the flow values + # Flow is in [B, H, W, 2] format after get_flow + fflow_small_permuted = fflow_small.permute(0, 3, 1, 2) # [B, 2, H, W] + fflow_upscaled = F.interpolate(fflow_small_permuted, size=(h, w), mode='bilinear', align_corners=False) + fflow = fflow_upscaled.permute(0, 2, 3, 1) # [B, H, W, 2] + + # Scale flow values to match the resolution change + fflow = fflow * flow_scale + + return fflow + + @torch.no_grad() + def __call__( + self, + prompt: Union[str, List[str]] = None, + images: PipelineImageInput = None, + height: Optional[int] = None, + width: Optional[int] = None, + num_inference_steps: int = 50, + guidance_scale: float = 7.5, + negative_prompt: Optional[Union[str, List[str]]] = None, + num_images_per_prompt: Optional[int] = 1, + eta: float = 0.0, + generator: Optional[Union[torch.Generator, List[torch.Generator]]] = None, + latents: Optional[torch.FloatTensor] = None, + prompt_embeds: Optional[torch.FloatTensor] = None, + negative_prompt_embeds: Optional[torch.FloatTensor] = None, + output_type: Optional[str] = "pil", + return_dict: bool = True, + callback: Optional[Callable[[int, int, torch.FloatTensor], None]] = None, + callback_steps: int = 1, + cross_attention_kwargs: Optional[Dict[str, Any]] = None, + controlnet_conditioning_scale: Union[float, List[float]] = 1.0, + guess_mode: bool = False, + control_guidance_start: Union[float, List[float]] = 0.0, + control_guidance_end: Union[float, List[float]] = 1.0, + of_model=None, + of_rescale_factor: int = 1, + timesteps_to_be_used: Optional[List[float]] = None, + # New parameters for chunked processing + prev_frame_rgb: Optional[torch.FloatTensor] = None, + prev_upscaled_for_flow: Optional[torch.FloatTensor] = None, + frame_offset: int = 0, + ): + """ + Run the Stream-DiffVSR pipeline. + """ + controlnet = self.controlnet._orig_mod if is_compiled_module(self.controlnet) else self.controlnet + + # align format for control guidance + if not isinstance(control_guidance_start, list) and isinstance(control_guidance_end, list): + control_guidance_start = len(control_guidance_end) * [control_guidance_start] + elif not isinstance(control_guidance_end, list) and isinstance(control_guidance_start, list): + control_guidance_end = len(control_guidance_start) * [control_guidance_end] + elif not isinstance(control_guidance_start, list) and not isinstance(control_guidance_end, list): + mult = len(controlnet.nets) if isinstance(controlnet, MultiControlNetModel) else 1 + control_guidance_start, control_guidance_end = mult * [control_guidance_start], mult * [control_guidance_end] + + # Define call parameters + if prompt is not None and isinstance(prompt, str): + batch_size = 1 + elif prompt is not None and isinstance(prompt, list): + batch_size = len(prompt) + else: + batch_size = prompt_embeds.shape[0] + + device = self._execution_device + do_classifier_free_guidance = guidance_scale > 1.0 + + if isinstance(controlnet, MultiControlNetModel) and isinstance(controlnet_conditioning_scale, float): + controlnet_conditioning_scale = [controlnet_conditioning_scale] * len(controlnet.nets) + + global_pool_conditions = ( + controlnet.config.global_pool_conditions + if isinstance(controlnet, ControlNetModel) + else controlnet.nets[0].config.global_pool_conditions + ) + guess_mode = guess_mode or global_pool_conditions + + # Encode input prompt + text_encoder_lora_scale = ( + cross_attention_kwargs.get("scale", None) if cross_attention_kwargs is not None else None + ) + prompt_embeds, negative_prompt_embeds = self.encode_prompt( + prompt, + device, + num_images_per_prompt, + do_classifier_free_guidance, + negative_prompt, + prompt_embeds=prompt_embeds, + negative_prompt_embeds=negative_prompt_embeds, + lora_scale=text_encoder_lora_scale, + ) + # Get model dtype early for consistency + model_dtype = self.unet.dtype + + if do_classifier_free_guidance: + prompt_embeds = torch.cat([negative_prompt_embeds, prompt_embeds]) + + # Ensure prompt embeds are in model dtype + prompt_embeds = prompt_embeds.to(dtype=model_dtype) + + # Prepare timesteps + if timesteps_to_be_used is None: + self.scheduler.set_timesteps(num_inference_steps, device=device) + else: + self.scheduler.set_timesteps(timesteps=timesteps_to_be_used, device=device) + timesteps = self.scheduler.timesteps + + extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta) + + # Create tensor stating which controlnets to keep + controlnet_keep = [] + for i in range(len(timesteps)): + keeps = [ + 1.0 - float(i / len(timesteps) < s or (i + 1) / len(timesteps) > e) + for s, e in zip(control_guidance_start, control_guidance_end) + ] + controlnet_keep.append(keeps[0] if isinstance(controlnet, ControlNetModel) else keeps) + + interp_mode = 'bilinear' if of_rescale_factor == 1 else 'nearest' + + # Initialize state from previous chunk if provided + rgb_for_warpping_to_next_frame = prev_frame_rgb + prev_upscaled = prev_upscaled_for_flow + + + # Store raw images for per-frame processing + raw_images = images + output_images = [] + num_channels_latents = self.vae.config.latent_channels + + num_warmup_steps = len(timesteps) - num_inference_steps * self.scheduler.order + total_frames = len(raw_images) + + with self.progress_bar(total=len(timesteps)*total_frames) as progress_bar: + for num_image, raw_image in enumerate(raw_images): + # === PROCESS ONE FRAME AT A TIME (VRAM efficient) === + + # Preprocess current frame only - DO NOT pass height/width to avoid resizing + # The preprocessor should just normalize, not resize the input + image = self.control_image_processor.preprocess(raw_image).to(dtype=model_dtype, device=device) + + # Upscale current frame only (4x bicubic for flow/conditioning) + upscaled = F.interpolate(image, scale_factor=4, mode='bicubic').to(dtype=model_dtype) + + # Get dimensions from upscaled output (for latent preparation) + frame_height, frame_width = upscaled.shape[-2:] + + # Prepare latent for current frame only + latent = self.prepare_latents( + batch_size * num_images_per_prompt, + num_channels_latents, + frame_height, + frame_width, + model_dtype, + device, + generator + ) + + # Compute flow only between adjacent frames + flow = None + if prev_upscaled is not None: + flow = self.compute_single_flow(of_model, prev_upscaled, upscaled, rescale_factor=of_rescale_factor) + + dec_temporal_features = None + warped_prev_est = None + + # Compute Temporal Texture Guidance if we have previous frame + if rgb_for_warpping_to_next_frame is not None and flow is not None: + warped_prev_est = of.flow_warp(rgb_for_warpping_to_next_frame, flow, interp_mode=interp_mode) + warped_prev_est = warped_prev_est.to(dtype=model_dtype) + enc_layer_features = self.vae.encode(warped_prev_est, return_features_only=True) + dec_temporal_features = enc_layer_features[::-1] + + for i, t in enumerate(timesteps): + # Ensure timestep is on the correct device + t = t.to(device) + + latent_model_input = torch.cat([latent] * 2) if do_classifier_free_guidance else latent + latent_model_input = self.scheduler.scale_model_input(latent_model_input, t) + + # Double image for CFG (unconditional + conditional) + image_input = torch.cat([image] * 2) if do_classifier_free_guidance else image + latent_model_input = torch.cat([latent_model_input, image_input], dim=1) + + # controlnet(s) inference + if guess_mode and do_classifier_free_guidance: + control_model_input = latent + control_model_input = self.scheduler.scale_model_input(control_model_input, t) + controlnet_prompt_embeds = prompt_embeds.chunk(2)[1] + else: + control_model_input = latent_model_input + controlnet_prompt_embeds = prompt_embeds + + if isinstance(controlnet_keep[i], list): + cond_scale = [c * s for c, s in zip(controlnet_conditioning_scale, controlnet_keep[i])] + else: + controlnet_cond_scale = controlnet_conditioning_scale + if isinstance(controlnet_cond_scale, list): + controlnet_cond_scale = controlnet_cond_scale[0] + cond_scale = controlnet_cond_scale * controlnet_keep[i] + + # Use ControlNet only if we have warped previous estimate + if warped_prev_est is None: + down_block_res_samples = None + mid_block_res_sample = None + else: + # Double warped_prev_est for CFG + controlnet_cond_input = torch.cat([warped_prev_est] * 2) if do_classifier_free_guidance else warped_prev_est + down_block_res_samples, mid_block_res_sample = self.controlnet( + control_model_input, + t, + encoder_hidden_states=controlnet_prompt_embeds, + controlnet_cond=controlnet_cond_input, + conditioning_scale=cond_scale, + guess_mode=guess_mode, + return_dict=False, + timestep_cond=None + ) + if guess_mode and do_classifier_free_guidance: + down_block_res_samples = [torch.cat([torch.zeros_like(d), d]) for d in down_block_res_samples] + mid_block_res_sample = torch.cat([torch.zeros_like(mid_block_res_sample), mid_block_res_sample]) + + # predict the noise residual + noise_pred = self.unet( + latent_model_input, + t, + encoder_hidden_states=prompt_embeds, + cross_attention_kwargs=cross_attention_kwargs, + down_block_additional_residuals=down_block_res_samples, + mid_block_additional_residual=mid_block_res_sample, + return_dict=False, + )[0] + + # perform guidance + if do_classifier_free_guidance: + noise_pred_uncond, noise_pred_text = noise_pred.chunk(2) + noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond) + + # compute the previous noisy sample x_t -> x_t-1 + step_output = self.scheduler.step(noise_pred, t, latent, **extra_step_kwargs) + latent, x0_est = step_output.prev_sample, step_output.pred_original_sample + + if i == len(timesteps) - 1 or ((i + 1) > num_warmup_steps and (i + 1) % self.scheduler.order == 0): + progress_bar.update() + if callback is not None and i % callback_steps == 0: + # Pass frame index (with offset), step index, total frames, total steps + callback(num_image + frame_offset, i, total_frames, len(timesteps), latent) + + if not output_type == "latent": + decoded_image = self.vae.decode(latent / self.vae.config.scaling_factor, temporal_features=dec_temporal_features, return_dict=False)[0] + else: + decoded_image = latent + + # Update state for next frame + # Clone tensors to avoid reference issues between frames + rgb_for_warpping_to_next_frame = decoded_image.clone() + prev_upscaled = upscaled.clone() + + has_nsfw_concept = None + do_denormalize = [True] * decoded_image[0].shape[0] + final_image = self.image_processor.postprocess(decoded_image, output_type=output_type, do_denormalize=do_denormalize) + output_images.append(final_image) + + self.vae.reset_temporal_condition() + + # Free memory for this frame + del image, latent, upscaled, decoded_image + if flow is not None: + del flow + if warped_prev_est is not None: + del warped_prev_est + + if hasattr(self, "final_offload_hook") and self.final_offload_hook is not None: + self.unet.to("cpu") + self.controlnet.to("cpu") + torch.cuda.empty_cache() + + if hasattr(self, "final_offload_hook") and self.final_offload_hook is not None: + self.final_offload_hook.offload() + + # Return output along with state for next chunk + output = StableDiffusionPipelineOutput(images=output_images, nsfw_content_detected=None) + return output, rgb_for_warpping_to_next_frame, prev_upscaled diff --git a/stream_diffvsr/scheduler/__init__.py b/stream_diffvsr/scheduler/__init__.py new file mode 100644 index 0000000..60b3d30 --- /dev/null +++ b/stream_diffvsr/scheduler/__init__.py @@ -0,0 +1,3 @@ +from .ddim_scheduler import DDIMScheduler + +__all__ = ["DDIMScheduler"] diff --git a/stream_diffvsr/scheduler/ddim_scheduler.py b/stream_diffvsr/scheduler/ddim_scheduler.py new file mode 100644 index 0000000..5c86944 --- /dev/null +++ b/stream_diffvsr/scheduler/ddim_scheduler.py @@ -0,0 +1,298 @@ +# Copyright 2024 Stanford University Team and The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +from dataclasses import dataclass +from typing import List, Optional, Tuple, Union + +import numpy as np +import torch + +from diffusers.configuration_utils import ConfigMixin, register_to_config +from diffusers.utils import BaseOutput +from diffusers.utils.torch_utils import randn_tensor +from diffusers.schedulers import KarrasDiffusionSchedulers, SchedulerMixin + + +@dataclass +class DDIMSchedulerOutput(BaseOutput): + """ + Output class for the scheduler's `step` function output. + + Args: + prev_sample (`torch.Tensor` of shape `(batch_size, num_channels, height, width)` for images): + Computed sample `(x_{t-1})` of previous timestep. `prev_sample` should be used as next model input in the + denoising loop. + pred_original_sample (`torch.Tensor` of shape `(batch_size, num_channels, height, width)` for images): + The predicted denoised sample `(x_{0})` based on the model output from the current timestep. + `pred_original_sample` can be used to preview progress or for guidance. + """ + + prev_sample: torch.Tensor + pred_original_sample: Optional[torch.Tensor] = None + + +def betas_for_alpha_bar( + num_diffusion_timesteps, + max_beta=0.999, + alpha_transform_type="cosine", +): + """ + Create a beta schedule that discretizes the given alpha_t_bar function. + """ + if alpha_transform_type == "cosine": + def alpha_bar_fn(t): + return math.cos((t + 0.008) / 1.008 * math.pi / 2) ** 2 + elif alpha_transform_type == "exp": + def alpha_bar_fn(t): + return math.exp(t * -12.0) + else: + raise ValueError(f"Unsupported alpha_transform_type: {alpha_transform_type}") + + betas = [] + for i in range(num_diffusion_timesteps): + t1 = i / num_diffusion_timesteps + t2 = (i + 1) / num_diffusion_timesteps + betas.append(min(1 - alpha_bar_fn(t2) / alpha_bar_fn(t1), max_beta)) + return torch.tensor(betas, dtype=torch.float32) + + +def rescale_zero_terminal_snr(betas): + """Rescales betas to have zero terminal SNR.""" + alphas = 1.0 - betas + alphas_cumprod = torch.cumprod(alphas, dim=0) + alphas_bar_sqrt = alphas_cumprod.sqrt() + + alphas_bar_sqrt_0 = alphas_bar_sqrt[0].clone() + alphas_bar_sqrt_T = alphas_bar_sqrt[-1].clone() + + alphas_bar_sqrt -= alphas_bar_sqrt_T + alphas_bar_sqrt *= alphas_bar_sqrt_0 / (alphas_bar_sqrt_0 - alphas_bar_sqrt_T) + + alphas_bar = alphas_bar_sqrt**2 + alphas = alphas_bar[1:] / alphas_bar[:-1] + alphas = torch.cat([alphas_bar[0:1], alphas]) + betas = 1 - alphas + + return betas + + +class DDIMScheduler(SchedulerMixin, ConfigMixin): + """ + DDIMScheduler extends the denoising procedure introduced in DDPMs with non-Markovian guidance. + """ + + _compatibles = [e.name for e in KarrasDiffusionSchedulers] + order = 1 + + @register_to_config + def __init__( + self, + num_train_timesteps: int = 1000, + beta_start: float = 0.0001, + beta_end: float = 0.02, + beta_schedule: str = "linear", + trained_betas: Optional[Union[np.ndarray, List[float]]] = None, + clip_sample: bool = True, + set_alpha_to_one: bool = True, + steps_offset: int = 0, + prediction_type: str = "epsilon", + thresholding: bool = False, + dynamic_thresholding_ratio: float = 0.995, + clip_sample_range: float = 1.0, + sample_max_value: float = 1.0, + timestep_spacing: str = "leading", + rescale_betas_zero_snr: bool = False, + ): + if trained_betas is not None: + self.betas = torch.tensor(trained_betas, dtype=torch.float32) + elif beta_schedule == "linear": + self.betas = torch.linspace(beta_start, beta_end, num_train_timesteps, dtype=torch.float32) + elif beta_schedule == "scaled_linear": + self.betas = torch.linspace(beta_start**0.5, beta_end**0.5, num_train_timesteps, dtype=torch.float32) ** 2 + elif beta_schedule == "squaredcos_cap_v2": + self.betas = betas_for_alpha_bar(num_train_timesteps) + else: + raise NotImplementedError(f"{beta_schedule} is not implemented for {self.__class__}") + + if rescale_betas_zero_snr: + self.betas = rescale_zero_terminal_snr(self.betas) + + self.alphas = 1.0 - self.betas + self.alphas_cumprod = torch.cumprod(self.alphas, dim=0) + self.final_alpha_cumprod = torch.tensor(1.0) if set_alpha_to_one else self.alphas_cumprod[0] + self.init_noise_sigma = 1.0 + self.num_inference_steps = None + self.timesteps = torch.from_numpy(np.arange(0, 1000)[::-1].copy().astype(np.int64)) + self.timestep_spacing = timestep_spacing + + def scale_model_input(self, sample: torch.Tensor, timestep: Optional[int] = None) -> torch.Tensor: + return sample + + def _get_variance(self, timestep, prev_timestep): + alpha_prod_t = self.alphas_cumprod[timestep] + alpha_prod_t_prev = self.alphas_cumprod[prev_timestep] if prev_timestep >= 0 else self.final_alpha_cumprod + beta_prod_t = 1 - alpha_prod_t + beta_prod_t_prev = 1 - alpha_prod_t_prev + variance = (beta_prod_t_prev / beta_prod_t) * (1 - alpha_prod_t / alpha_prod_t_prev) + return variance + + def _threshold_sample(self, sample: torch.Tensor) -> torch.Tensor: + dtype = sample.dtype + batch_size, channels, *remaining_dims = sample.shape + + if dtype not in (torch.float32, torch.float64): + sample = sample.float() + + sample = sample.reshape(batch_size, channels * np.prod(remaining_dims)) + abs_sample = sample.abs() + s = torch.quantile(abs_sample, self.config.dynamic_thresholding_ratio, dim=1) + s = torch.clamp(s, min=1, max=self.config.sample_max_value) + s = s.unsqueeze(1) + sample = torch.clamp(sample, -s, s) / s + sample = sample.reshape(batch_size, channels, *remaining_dims) + sample = sample.to(dtype) + return sample + + def set_timesteps(self, num_inference_steps: int = None, device: Union[str, torch.device] = None, timesteps: List[float] = None): + if timesteps is not None: + self.timesteps = torch.tensor(timesteps, device=device) + self.num_inference_steps = len(timesteps) + return + + if num_inference_steps > self.config.num_train_timesteps: + raise ValueError( + f"`num_inference_steps`: {num_inference_steps} cannot be larger than `self.config.train_timesteps`:" + f" {self.config.num_train_timesteps}" + ) + + self.num_inference_steps = num_inference_steps + + if self.timestep_spacing == "linspace": + timesteps = ( + np.linspace(0, self.config.num_train_timesteps - 1, num_inference_steps) + .round()[::-1] + .copy() + .astype(np.int64) + ) + elif self.timestep_spacing == "leading": + step_ratio = self.config.num_train_timesteps // self.num_inference_steps + timesteps = (np.arange(0, num_inference_steps) * step_ratio).round()[::-1].copy().astype(np.int64) + timesteps += self.config.steps_offset + elif self.timestep_spacing == "trailing": + step_ratio = self.config.num_train_timesteps / self.num_inference_steps + timesteps = np.round(np.arange(self.config.num_train_timesteps, 0, -step_ratio)).astype(np.int64) + timesteps -= 1 + else: + raise ValueError( + f"{self.timestep_spacing} is not supported. Please make sure to choose one of 'leading' or 'trailing'." + ) + + self.timesteps = torch.from_numpy(timesteps).to(device) + + def step( + self, + model_output: torch.Tensor, + timestep: int, + sample: torch.Tensor, + eta: float = 0.0, + use_clipped_model_output: bool = False, + generator=None, + variance_noise: Optional[torch.Tensor] = None, + return_dict: bool = True, + ) -> Union[DDIMSchedulerOutput, Tuple]: + if self.num_inference_steps is None: + raise ValueError( + "Number of inference steps is 'None', you need to run 'set_timesteps' after creating the scheduler" + ) + + prev_timestep = timestep - self.config.num_train_timesteps // self.num_inference_steps + alpha_prod_t = self.alphas_cumprod[timestep] + alpha_prod_t_prev = self.alphas_cumprod[prev_timestep] if prev_timestep >= 0 else self.final_alpha_cumprod + beta_prod_t = 1 - alpha_prod_t + + if self.config.prediction_type == "epsilon": + pred_original_sample = (sample - beta_prod_t ** (0.5) * model_output) / alpha_prod_t ** (0.5) + pred_epsilon = model_output + elif self.config.prediction_type == "sample": + pred_original_sample = model_output + pred_epsilon = (sample - alpha_prod_t ** (0.5) * pred_original_sample) / beta_prod_t ** (0.5) + elif self.config.prediction_type == "v_prediction": + pred_original_sample = (alpha_prod_t**0.5) * sample - (beta_prod_t**0.5) * model_output + pred_epsilon = (alpha_prod_t**0.5) * model_output + (beta_prod_t**0.5) * sample + else: + raise ValueError( + f"prediction_type given as {self.config.prediction_type} must be one of `epsilon`, `sample`, or" + " `v_prediction`" + ) + + if self.config.thresholding: + pred_original_sample = self._threshold_sample(pred_original_sample) + elif self.config.clip_sample: + pred_original_sample = pred_original_sample.clamp( + -self.config.clip_sample_range, self.config.clip_sample_range + ) + + variance = self._get_variance(timestep, prev_timestep) + std_dev_t = eta * variance ** (0.5) + + if use_clipped_model_output: + pred_epsilon = (sample - alpha_prod_t ** (0.5) * pred_original_sample) / beta_prod_t ** (0.5) + + pred_sample_direction = (1 - alpha_prod_t_prev - std_dev_t**2) ** (0.5) * pred_epsilon + prev_sample = alpha_prod_t_prev ** (0.5) * pred_original_sample + pred_sample_direction + + if eta > 0: + if variance_noise is not None and generator is not None: + raise ValueError( + "Cannot pass both generator and variance_noise." + ) + + if variance_noise is None: + variance_noise = randn_tensor( + model_output.shape, generator=generator, device=model_output.device, dtype=model_output.dtype + ) + variance = std_dev_t * variance_noise + prev_sample = prev_sample + variance + + if not return_dict: + return (prev_sample,) + + return DDIMSchedulerOutput(prev_sample=prev_sample, pred_original_sample=pred_original_sample) + + def add_noise( + self, + original_samples: torch.Tensor, + noise: torch.Tensor, + timesteps: torch.IntTensor, + ) -> torch.Tensor: + self.alphas_cumprod = self.alphas_cumprod.to(device=original_samples.device) + alphas_cumprod = self.alphas_cumprod.to(dtype=original_samples.dtype) + timesteps = timesteps.to(original_samples.device) + + sqrt_alpha_prod = alphas_cumprod[timesteps] ** 0.5 + sqrt_alpha_prod = sqrt_alpha_prod.flatten() + while len(sqrt_alpha_prod.shape) < len(original_samples.shape): + sqrt_alpha_prod = sqrt_alpha_prod.unsqueeze(-1) + + sqrt_one_minus_alpha_prod = (1 - alphas_cumprod[timesteps]) ** 0.5 + sqrt_one_minus_alpha_prod = sqrt_one_minus_alpha_prod.flatten() + while len(sqrt_one_minus_alpha_prod.shape) < len(original_samples.shape): + sqrt_one_minus_alpha_prod = sqrt_one_minus_alpha_prod.unsqueeze(-1) + + noisy_samples = sqrt_alpha_prod * original_samples + sqrt_one_minus_alpha_prod * noise + return noisy_samples + + def __len__(self): + return self.config.num_train_timesteps diff --git a/stream_diffvsr/temporal_autoencoder/__init__.py b/stream_diffvsr/temporal_autoencoder/__init__.py new file mode 100644 index 0000000..34d3bc8 --- /dev/null +++ b/stream_diffvsr/temporal_autoencoder/__init__.py @@ -0,0 +1,3 @@ +from .autoencoder_tiny import TemporalAutoencoderTiny + +__all__ = ["TemporalAutoencoderTiny"] diff --git a/stream_diffvsr/temporal_autoencoder/autoencoder_tiny.py b/stream_diffvsr/temporal_autoencoder/autoencoder_tiny.py new file mode 100644 index 0000000..926fdd5 --- /dev/null +++ b/stream_diffvsr/temporal_autoencoder/autoencoder_tiny.py @@ -0,0 +1,278 @@ +# Copyright 2024 Ollin Boer Bohan and The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from dataclasses import dataclass +from typing import Optional, Tuple, Union + +import torch + +from diffusers.configuration_utils import ConfigMixin, register_to_config +from diffusers.utils import BaseOutput +from diffusers.utils.accelerate_utils import apply_forward_hook +from diffusers.models.modeling_utils import ModelMixin +from .vae import DecoderOutput, TemporalDecoderTiny, EncoderTiny +from .models.unets.unet_2d_blocks import TemporalAutoencoderTinyBlock + + +@dataclass +class TemporalAutoencoderTinyOutput(BaseOutput): + """ + Output of TemporalAutoencoderTiny encoding method. + + Args: + latents (`torch.Tensor`): Encoded outputs of the `Encoder`. + """ + + latents: torch.Tensor + + +class TemporalAutoencoderTiny(ModelMixin, ConfigMixin): + """ + A tiny distilled VAE model for encoding images into latents and decoding latent representations into images. + """ + + _supports_gradient_checkpointing = True + + @register_to_config + def __init__( + self, + in_channels: int = 3, + out_channels: int = 3, + encoder_block_out_channels: Tuple[int, ...] = (64, 64, 64, 64), + decoder_block_out_channels: Tuple[int, ...] = (64, 64, 64, 64), + act_fn: str = "relu", + upsample_fn: str = "nearest", + latent_channels: int = 4, + upsampling_scaling_factor: int = 2, + num_encoder_blocks: Tuple[int, ...] = (1, 3, 3, 3), + num_decoder_blocks: Tuple[int, ...] = (3, 3, 3, 1), + latent_magnitude: int = 3, + latent_shift: float = 0.5, + force_upcast: bool = False, + scaling_factor: float = 1.0, + shift_factor: float = 0.0, + block_out_channels: Tuple[int, ...] = None, # For compatibility with saved configs + ): + super().__init__() + + if len(encoder_block_out_channels) != len(num_encoder_blocks): + raise ValueError("`encoder_block_out_channels` should have the same length as `num_encoder_blocks`.") + if len(decoder_block_out_channels) != len(num_decoder_blocks): + raise ValueError("`decoder_block_out_channels` should have the same length as `num_decoder_blocks`.") + + self.encoder = EncoderTiny( + in_channels=in_channels, + out_channels=latent_channels, + num_blocks=num_encoder_blocks, + block_out_channels=encoder_block_out_channels, + act_fn=act_fn, + ) + + self.encoder.requires_grad_(False) + + self.decoder = TemporalDecoderTiny( + in_channels=latent_channels, + out_channels=out_channels, + num_blocks=num_decoder_blocks, + block_out_channels=decoder_block_out_channels, + upsampling_scaling_factor=upsampling_scaling_factor, + act_fn=act_fn, + upsample_fn=upsample_fn, + ) + + self.decoder.requires_grad_(False) + + for name, param in self.decoder.named_parameters(): + if "alpha" in name or "temporal_processor" in name: + param.requires_grad_(True) + + self.latent_magnitude = latent_magnitude + self.latent_shift = latent_shift + self.scaling_factor = scaling_factor + + self.use_slicing = False + self.use_tiling = False + + self.spatial_scale_factor = 2**out_channels + self.tile_overlap_factor = 0.125 + self.tile_sample_min_size = 512 + self.tile_latent_min_size = self.tile_sample_min_size // self.spatial_scale_factor + + self.register_to_config(block_out_channels=decoder_block_out_channels) + self.register_to_config(force_upcast=False) + + def reset_temporal_condition(self): + """reset temporal memory""" + for module in self.encoder.layers: + if isinstance(module, TemporalAutoencoderTinyBlock): + module.reset_temporal() + for module in self.decoder.layers: + if isinstance(module, TemporalAutoencoderTinyBlock): + module.reset_temporal() + + def _set_gradient_checkpointing(self, module, value: bool = False) -> None: + if isinstance(module, (EncoderTiny, TemporalDecoderTiny)): + module.gradient_checkpointing = value + + def scale_latents(self, x: torch.Tensor) -> torch.Tensor: + """raw latents -> [0, 1]""" + return x.div(2 * self.latent_magnitude).add(self.latent_shift).clamp(0, 1) + + def unscale_latents(self, x: torch.Tensor) -> torch.Tensor: + """[0, 1] -> raw latents""" + return x.sub(self.latent_shift).mul(2 * self.latent_magnitude) + + def enable_slicing(self) -> None: + self.use_slicing = True + + def disable_slicing(self) -> None: + self.use_slicing = False + + def enable_tiling(self, use_tiling: bool = True) -> None: + self.use_tiling = use_tiling + + def disable_tiling(self) -> None: + self.enable_tiling(False) + + def _tiled_encode(self, x: torch.Tensor) -> torch.Tensor: + sf = self.spatial_scale_factor + tile_size = self.tile_sample_min_size + blend_size = int(tile_size * self.tile_overlap_factor) + traverse_size = tile_size - blend_size + + ti = range(0, x.shape[-2], traverse_size) + tj = range(0, x.shape[-1], traverse_size) + + blend_masks = torch.stack( + torch.meshgrid([torch.arange(tile_size / sf) / (blend_size / sf - 1)] * 2, indexing="ij") + ) + blend_masks = blend_masks.clamp(0, 1).to(x.device) + + out = torch.zeros(x.shape[0], 4, x.shape[-2] // sf, x.shape[-1] // sf, device=x.device) + for i in ti: + for j in tj: + tile_in = x[..., i : i + tile_size, j : j + tile_size] + tile_out = out[..., i // sf : (i + tile_size) // sf, j // sf : (j + tile_size) // sf] + tile = self.encoder(tile_in) + h, w = tile.shape[-2], tile.shape[-1] + blend_mask_i = torch.ones_like(blend_masks[0]) if i == 0 else blend_masks[0] + blend_mask_j = torch.ones_like(blend_masks[1]) if j == 0 else blend_masks[1] + blend_mask = blend_mask_i * blend_mask_j + tile, blend_mask = tile[..., :h, :w], blend_mask[..., :h, :w] + tile_out.copy_(blend_mask * tile + (1 - blend_mask) * tile_out) + return out + + def _tiled_decode(self, x: torch.Tensor) -> torch.Tensor: + sf = self.spatial_scale_factor + tile_size = self.tile_latent_min_size + blend_size = int(tile_size * self.tile_overlap_factor) + traverse_size = tile_size - blend_size + + ti = range(0, x.shape[-2], traverse_size) + tj = range(0, x.shape[-1], traverse_size) + + blend_masks = torch.stack( + torch.meshgrid([torch.arange(tile_size * sf) / (blend_size * sf - 1)] * 2, indexing="ij") + ) + blend_masks = blend_masks.clamp(0, 1).to(x.device) + + out = torch.zeros(x.shape[0], 3, x.shape[-2] * sf, x.shape[-1] * sf, device=x.device) + for i in ti: + for j in tj: + tile_in = x[..., i : i + tile_size, j : j + tile_size] + tile_out = out[..., i * sf : (i + tile_size) * sf, j * sf : (j + tile_size) * sf] + tile = self.decoder(tile_in) + h, w = tile.shape[-2], tile.shape[-1] + blend_mask_i = torch.ones_like(blend_masks[0]) if i == 0 else blend_masks[0] + blend_mask_j = torch.ones_like(blend_masks[1]) if j == 0 else blend_masks[1] + blend_mask = (blend_mask_i * blend_mask_j)[..., :h, :w] + tile_out.copy_(blend_mask * tile + (1 - blend_mask) * tile_out) + return out + + @apply_forward_hook + def encode(self, x: torch.Tensor, return_dict: bool = True, return_layers_features: bool = True, return_features_only: bool = False) -> Union[TemporalAutoencoderTinyOutput, Tuple[torch.Tensor]]: + layer_features = [] if return_layers_features else None + + if self.use_slicing and x.shape[0] > 1: + output = [ + self._tiled_encode(x_slice) if self.use_tiling else self.encoder(x_slice) + for x_slice in x.split(1) + ] + output = torch.cat(output) + else: + if self.use_tiling: + output = self._tiled_encode(x) + elif return_layers_features: + current_features = x + for module in self.encoder.layers: + current_features = module(current_features) + + if isinstance(module, TemporalAutoencoderTinyBlock): + layer_features.append(current_features) + + if return_features_only: + return layer_features + + output = self.encoder(x) + + if not return_dict: + return (output,), layer_features + + return TemporalAutoencoderTinyOutput(latents=output) + + @apply_forward_hook + def decode( + self, x: torch.Tensor, temporal_features=None, generator: Optional[torch.Generator] = None, return_dict: bool = True + ) -> Union[DecoderOutput, Tuple[torch.Tensor]]: + if self.use_slicing and x.shape[0] > 1: + output = [ + self._tiled_decode(x_slice) if self.use_tiling else self.decoder(x_slice) for x_slice in x.split(1) + ] + output = torch.cat(output) + elif temporal_features is not None: + block_idx = 0 + for module in self.decoder.layers: + if isinstance(module, TemporalAutoencoderTinyBlock): + module.prev_features = temporal_features[block_idx] + block_idx += 1 + output = self.decoder(x) + else: + output = self._tiled_decode(x) if self.use_tiling else self.decoder(x) + + if not return_dict: + return (output,) + + return DecoderOutput(sample=output) + + def forward( + self, + sample: torch.Tensor, + previous_sample: Optional[torch.Tensor] = None, + return_dict: bool = False, + ) -> Union[DecoderOutput, Tuple[torch.Tensor]]: + layer_features = None + + if previous_sample is not None: + prev_enc, layer_features = self.encode(previous_sample, return_dict=return_dict) + + if layer_features is not None: + temporal_features = layer_features[::-1] + else: + temporal_features = None + + dec = self.decode(sample, temporal_features=temporal_features, return_dict=return_dict)[0] + + if not return_dict: + return (dec,) + return DecoderOutput(sample=dec) diff --git a/stream_diffvsr/temporal_autoencoder/models/__init__.py b/stream_diffvsr/temporal_autoencoder/models/__init__.py new file mode 100644 index 0000000..319cb4f --- /dev/null +++ b/stream_diffvsr/temporal_autoencoder/models/__init__.py @@ -0,0 +1 @@ +# Temporal autoencoder models diff --git a/stream_diffvsr/temporal_autoencoder/models/unets/__init__.py b/stream_diffvsr/temporal_autoencoder/models/unets/__init__.py new file mode 100644 index 0000000..24c6c96 --- /dev/null +++ b/stream_diffvsr/temporal_autoencoder/models/unets/__init__.py @@ -0,0 +1,3 @@ +from .unet_2d_blocks import TemporalAutoencoderTinyBlock + +__all__ = ["TemporalAutoencoderTinyBlock"] diff --git a/stream_diffvsr/temporal_autoencoder/models/unets/unet_2d_blocks.py b/stream_diffvsr/temporal_autoencoder/models/unets/unet_2d_blocks.py new file mode 100644 index 0000000..2317fef --- /dev/null +++ b/stream_diffvsr/temporal_autoencoder/models/unets/unet_2d_blocks.py @@ -0,0 +1,98 @@ +# Copyright 2024 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch +import torch.nn as nn +from diffusers.models.activations import get_activation + + +class TemporalAutoencoderTinyBlock(nn.Module): + """ + Tiny Autoencoder block used in [`AutoencoderTiny`]. It is a mini residual module consisting of plain conv + ReLU + blocks. + + Args: + in_channels (`int`): The number of input channels. + out_channels (`int`): The number of output channels. + act_fn (`str`): + ` The activation function to use. Supported values are `"swish"`, `"mish"`, `"gelu"`, and `"relu"`. + + Returns: + `torch.Tensor`: A tensor with the same shape as the input tensor, but with the number of channels equal to + `out_channels`. + """ + + def __init__(self, in_channels: int, out_channels: int, act_fn: str): + super().__init__() + act_fn = get_activation(act_fn) + self.conv = nn.Sequential( + nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1), + act_fn, + nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1), + act_fn, + nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1), + ) + self.skip = ( + nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False) + if in_channels != out_channels + else nn.Identity() + ) + self.fuse = nn.ReLU() + + # temporal layers + self.prev_features = None + + self.alpha = nn.Parameter(torch.tensor(0.5)) + self.temporal_processor = nn.Sequential( + nn.Conv1d(out_channels, out_channels, 3, padding=1), + act_fn, + nn.Conv1d(out_channels, out_channels, 3, padding=1) + ) + + def forward(self, x): + current_features = self.conv(x) + + if self.prev_features is not None: + B, C, H, W = current_features.shape + + pool_kernel = (4, 4) + + avg_pool = nn.AvgPool2d(kernel_size=pool_kernel, stride=pool_kernel) + current_pooled = avg_pool(current_features) + prev_pooled = avg_pool(self.prev_features) + + temporal_input = torch.cat([ + current_pooled.view(B, C, -1), + prev_pooled.view(B, C, -1) + ], dim=2) + + temporal_out = self.temporal_processor(temporal_input) + + pool_h, pool_w = current_pooled.shape[2], current_pooled.shape[3] + temporal_out_fuse = self.alpha * temporal_out[:, :, :pool_h * pool_w].view(B, C, pool_h, pool_w) + \ + (1 - self.alpha) * temporal_out[:, :, -pool_h * pool_w:].view(B, C, pool_h, pool_w) + + temporal_out_fuse = nn.functional.interpolate( + temporal_out_fuse, + size=(H, W), + mode='bilinear', + align_corners=False + ) + + current_features = current_features + 0.1 * temporal_out_fuse + + return self.fuse(current_features + self.skip(x)) + + def reset_temporal(self): + self.prev_features = None diff --git a/stream_diffvsr/temporal_autoencoder/vae.py b/stream_diffvsr/temporal_autoencoder/vae.py new file mode 100644 index 0000000..dd5c11a --- /dev/null +++ b/stream_diffvsr/temporal_autoencoder/vae.py @@ -0,0 +1,138 @@ +# Copyright 2024 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from dataclasses import dataclass +from typing import Optional, Tuple + +import torch +import torch.nn as nn + +from diffusers.utils import BaseOutput +from diffusers.models.activations import get_activation +from .models.unets.unet_2d_blocks import TemporalAutoencoderTinyBlock + + +@dataclass +class DecoderOutput(BaseOutput): + """ + Output of decoding method. + + Args: + sample (`torch.Tensor` of shape `(batch_size, num_channels, height, width)`): + The decoded output sample from the last layer of the model. + """ + + sample: torch.Tensor + commit_loss: Optional[torch.FloatTensor] = None + + +class EncoderTiny(nn.Module): + """ + The `EncoderTiny` layer is a simpler version of the `Encoder` layer. + """ + + def __init__( + self, + in_channels: int, + out_channels: int, + num_blocks: Tuple[int, ...], + block_out_channels: Tuple[int, ...], + act_fn: str, + ): + super().__init__() + + layers = [] + for i, num_block in enumerate(num_blocks): + num_channels = block_out_channels[i] + + if i == 0: + layers.append(nn.Conv2d(in_channels, num_channels, kernel_size=3, padding=1)) + else: + layers.append( + nn.Conv2d( + num_channels, + num_channels, + kernel_size=3, + padding=1, + stride=2, + bias=False, + ) + ) + + for _ in range(num_block): + layers.append(TemporalAutoencoderTinyBlock(num_channels, num_channels, act_fn)) + + layers.append(nn.Conv2d(block_out_channels[-1], out_channels, kernel_size=3, padding=1)) + + self.layers = nn.Sequential(*layers) + self.gradient_checkpointing = False + + def forward(self, x: torch.Tensor) -> torch.Tensor: + x = self.layers(x.add(1).div(2)) + return x + + +class TemporalDecoderTiny(nn.Module): + """ + The `TemporalDecoderTiny` layer is a simpler version of the `Decoder` layer with temporal processing. + """ + + def __init__( + self, + in_channels: int, + out_channels: int, + num_blocks: Tuple[int, ...], + block_out_channels: Tuple[int, ...], + upsampling_scaling_factor: int, + act_fn: str, + upsample_fn: str, + ): + super().__init__() + + layers = [ + nn.Conv2d(in_channels, block_out_channels[0], kernel_size=3, padding=1), + get_activation(act_fn), + ] + + for i, num_block in enumerate(num_blocks): + is_final_block = i == (len(num_blocks) - 1) + num_channels = block_out_channels[i] + + for _ in range(num_block): + block = TemporalAutoencoderTinyBlock(num_channels, num_channels, act_fn) + layers.append(block) + + if not is_final_block: + layers.append(nn.Upsample(scale_factor=upsampling_scaling_factor, mode=upsample_fn)) + + conv_out_channel = num_channels if not is_final_block else out_channels + layers.append( + nn.Conv2d( + num_channels, + conv_out_channel, + kernel_size=3, + padding=1, + bias=is_final_block, + ) + ) + + self.layers = nn.Sequential(*layers) + self.gradient_checkpointing = False + + def forward(self, x: torch.Tensor) -> torch.Tensor: + # Clamp + x = torch.tanh(x / 3) * 3 + x = self.layers(x) + # scale image from [0, 1] to [-1, 1] to match diffusers convention + return x.mul(2).sub(1) diff --git a/stream_diffvsr/util/__init__.py b/stream_diffvsr/util/__init__.py new file mode 100644 index 0000000..c9a76e3 --- /dev/null +++ b/stream_diffvsr/util/__init__.py @@ -0,0 +1,3 @@ +from . import flow_utils + +__all__ = ["flow_utils"] diff --git a/stream_diffvsr/util/flow_utils.py b/stream_diffvsr/util/flow_utils.py new file mode 100644 index 0000000..5ef471e --- /dev/null +++ b/stream_diffvsr/util/flow_utils.py @@ -0,0 +1,100 @@ +import torch +import torch.nn.functional as F + +def flow_warp(x, flow, interp_mode='bilinear', padding_mode='zeros'): + """Warp an image or feature map with optical flow + Args: + x (Tensor): size (N, C, H, W) + flow (Tensor): size (N, H, W, 2), normal value + interp_mode (str): 'nearest' or 'bilinear' + padding_mode (str): 'zeros' or 'border' or 'reflection' + + Returns: + Tensor: warped image or feature map + """ + if flow.dim() == 4 and flow.shape[1] == 2: + flow = flow.permute(0, 2, 3, 1) # [N, 2, H, W] -> [N, H, W, 2] + + assert x.size()[-2:] == flow.size()[1:3] + _, _, H, W = x.size() + + # Ensure flow matches input dtype and device + flow = flow.to(dtype=x.dtype, device=x.device) + + # mesh grid + grid_y, grid_x = torch.meshgrid(torch.arange(0, H), torch.arange(0, W), indexing='ij') + grid = torch.stack((grid_x, grid_y), 2).float() # W(x), H(y), 2 + grid.requires_grad = False + grid = grid.type_as(x) + vgrid = grid + flow + # scale grid to [-1,1] + vgrid_x = 2.0 * vgrid[:, :, :, 0] / max(W - 1, 1) - 1.0 + vgrid_y = 2.0 * vgrid[:, :, :, 1] / max(H - 1, 1) - 1.0 + vgrid_scaled = torch.stack((vgrid_x, vgrid_y), dim=3) + output = F.grid_sample(x, vgrid_scaled, mode=interp_mode, padding_mode=padding_mode, align_corners=False) + return output + +def get_flow(of_model, target, source, rescale_factor=1): + flows = of_model(target, source) + flow = flows[-1] + flow = F.interpolate(flow//rescale_factor, scale_factor=1/rescale_factor, mode='bilinear') if rescale_factor != 1 else flow + flow = flow.permute(0, 2, 3, 1) # permute to B, H, W, 2 + return flow + +def compute_flow_magnitude(flow): + flow_mag = flow[:, :, :, 0] ** 2 + flow[:, :, :, 1] ** 2 + return flow_mag + +def compute_flow_gradients(flow): + B = flow.shape[0] + H = flow.shape[1] + W = flow.shape[2] + + device = flow.device + flow_x_du = torch.zeros((B, H, W), device=device) + flow_x_dv = torch.zeros((B, H, W), device=device) + flow_y_du = torch.zeros((B, H, W), device=device) + flow_y_dv = torch.zeros((B, H, W), device=device) + + flow_x = flow[:, :, :, 0] + flow_y = flow[:, :, :, 1] + + flow_x_du[:, :, :-1] = flow_x[:, :, :-1] - flow_x[:, :, 1:] + flow_x_dv[:, :-1, :] = flow_x[:, :-1, :] - flow_x[:, 1:, :] + flow_y_du[:, :, :-1] = flow_y[:, :, :-1] - flow_y[:, :, 1:] + flow_y_dv[:, :-1, :] = flow_y[:, :-1, :] - flow_y[:, 1:, :] + + return flow_x_du, flow_x_dv, flow_y_du, flow_y_dv + +def detect_occlusion(fw_flow, bw_flow): + # inputs: flow_forward, flow_backward + # return: occlusion mask + tmp = bw_flow + bw_flow = fw_flow + fw_flow = tmp + + fw_flow_w = flow_warp(fw_flow.permute(0,3,1,2), bw_flow).permute(0,2,3,1) + + fb_flow_sum = fw_flow_w + bw_flow + fb_flow_mag = compute_flow_magnitude(fb_flow_sum) + fw_flow_w_mag = compute_flow_magnitude(fw_flow_w) + bw_flow_mag = compute_flow_magnitude(bw_flow) + + mask1 = fb_flow_mag > 0.01 * (fw_flow_w_mag + bw_flow_mag) + 0.5 + + fx_du, fx_dv, fy_du, fy_dv = compute_flow_gradients(bw_flow) + fx_mag = fx_du ** 2 + fx_dv ** 2 + fy_mag = fy_du ** 2 + fy_dv ** 2 + + mask2 = (fx_mag + fy_mag) > 0.01 * bw_flow_mag + 0.002 + + mask = torch.logical_or(mask1, mask2) + occlusion = torch.ones((fw_flow.shape[0], fw_flow.shape[1], fw_flow.shape[2]), device=fw_flow.device) + occlusion[mask == 1] = 0 + + return occlusion + +def get_flow_forward_backward(net, current, prev, rescale_factor=1): + flow_forward = get_flow(net, current, prev, rescale_factor=rescale_factor) + flow_backward = get_flow(net, prev, current, rescale_factor=rescale_factor) + return flow_forward, flow_backward