Files
yuvraj108c-ComfyUI_InvSR/node.py
T

162 lines
5.2 KiB
Python

from .comfyui_invsr_trimmed import get_configs, InvSamplerSR, BaseSampler
import torch
from comfy.utils import ProgressBar
from folder_paths import get_full_path, get_folder_paths
import os
def split_tensor_into_batches(tensor, batch_size):
"""
Split a tensor into smaller batches of specified size
Args:
tensor (torch.Tensor): Input tensor of shape (N, C, H, W)
batch_size (int): Desired batch size for splitting
Returns:
list: List of tensors, each with batch_size (except possibly the last one)
"""
# Get original batch size
original_batch_size = tensor.size(0)
# Calculate number of full batches and remaining samples
num_full_batches = original_batch_size // batch_size
remaining_samples = original_batch_size % batch_size
# Split tensor into chunks
batches = []
# Handle full batches
for i in range(num_full_batches):
start_idx = i * batch_size
end_idx = start_idx + batch_size
batch = tensor[start_idx:end_idx]
batches.append(batch)
# Handle remaining samples if any
if remaining_samples > 0:
last_batch = tensor[-remaining_samples:]
batches.append(last_batch)
return batches
class Namespace:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
def __repr__(self):
items = [f"{key}={repr(value)}" for key, value in vars(self).items()]
return f"Namespace({', '.join(items)})"
class LoadInvSRModels:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"sd_model": (['stabilityai/sd-turbo'],),
"invsr_model": (['noise_predictor_sd_turbo_v5.pth'],),
"dtype": (['fp16', 'fp32', 'bf16'], {"default": "fp16"}),
"tiled_vae": ("BOOLEAN", {"default": True}),
},
}
RETURN_TYPES = ("INVSR_PIPE",)
RETURN_NAMES = ("invsr_pipe",)
FUNCTION = "loadmodel"
CATEGORY = "INVSR"
def loadmodel(self, sd_model, invsr_model, dtype, tiled_vae):
match dtype:
case "fp16":
dtype = "torch.float16"
case "fp32":
dtype = "torch.float32"
case "bf16":
dtype = "torch.bfloat16"
cfg_path = os.path.join(
os.path.dirname(__file__), "configs", "sample-sd-turbo.yaml"
)
sd_path = get_folder_paths("diffusers")[0]
ckpt_path = get_full_path("invsr", "noise_predictor_sd_turbo_v5.pth")
args = Namespace(
bs=1,
chopping_bs=8,
timesteps=None,
num_steps=1,
cfg_path=cfg_path,
sd_path=sd_path,
started_ckpt_path=ckpt_path,
tiled_vae=tiled_vae,
color_fix="",
chopping_size=128,
)
configs = get_configs(args)
configs["sd_pipe"]["params"]["torch_dtype"] = dtype
base_sampler = BaseSampler(configs)
return (base_sampler,)
class InvSRSampler:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"invsr_pipe": ("INVSR_PIPE",),
"images": ("IMAGE",),
"num_steps": ("INT",{"default": 1, "min": 1, "max": 5}),
"batch_size": ("INT",{"default": 1}),
"chopping_batch_size": ("INT",{"default": 8}),
"chopping_size": ([128, 256, 512],{"default": 128}),
"color_fix": (['none', 'wavelet', 'ycbcr'], {"default": "none"}),
"seed": ("INT", {"default": 123, "min": 0, "max": 2**32 - 1, "step": 1}),
},
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("image",)
FUNCTION = "process"
CATEGORY = "INVSR"
def process(self, invsr_pipe, images, num_steps, batch_size, chopping_batch_size, chopping_size, color_fix, seed):
base_sampler = invsr_pipe
if color_fix == "none":
color_fix = ""
cfg_path = os.path.join(
os.path.dirname(__file__), "configs", "sample-sd-turbo.yaml"
)
sd_path = get_folder_paths("diffusers")[0]
ckpt_path = get_full_path("invsr", "noise_predictor_sd_turbo_v5.pth")
args = Namespace(
bs=batch_size,
chopping_bs=chopping_batch_size,
timesteps=None,
num_steps=num_steps,
cfg_path=cfg_path,
sd_path=sd_path,
started_ckpt_path=ckpt_path,
tiled_vae=base_sampler.configs.tiled_vae,
color_fix=color_fix,
chopping_size=chopping_size,
)
configs = get_configs(args)
base_sampler.configs = get_configs(args, log=True)
base_sampler.setup_seed(seed)
sampler = InvSamplerSR(base_sampler)
images_bchw = images.permute(0,3,1,2)
batches = split_tensor_into_batches(images_bchw, batch_size)
results = []
pbar = ProgressBar(len(batches))
for batch in batches:
result = sampler.inference(image_bchw=batch)
results.append(torch.from_numpy(result))
pbar.update(1)
return (torch.cat(results, dim=0),)