Expose latent upscale sampler controls
This commit is contained in:
+58
-13
@@ -4,6 +4,7 @@ import math
|
||||
import os
|
||||
import re
|
||||
|
||||
import comfy.samplers
|
||||
import folder_paths
|
||||
import torch
|
||||
|
||||
@@ -33,6 +34,8 @@ LATENTS_STD = [
|
||||
]
|
||||
|
||||
_LATENT_UPSCALE_FOLDER = "latent_upscale_models"
|
||||
MP_UNIT = 1024 * 1024
|
||||
RES_MULTIPLE = 32
|
||||
|
||||
|
||||
def _models_dir():
|
||||
@@ -347,10 +350,29 @@ def _compute_upscale_target(width, height, h_in, w_in):
|
||||
return h_out, w_out, eff
|
||||
|
||||
|
||||
def _scale_to_megapixels(w, h, mp, multiple=RES_MULTIPLE):
|
||||
if not mp or mp <= 0 or w <= 0 or h <= 0:
|
||||
return int(h), int(w)
|
||||
multiple = max(1, int(multiple))
|
||||
scale = math.sqrt((float(mp) * MP_UNIT) / float(w * h))
|
||||
nw = max(multiple, int(round(w * scale / multiple)) * multiple)
|
||||
nh = max(multiple, int(round(h * scale / multiple)) * multiple)
|
||||
return nh, nw
|
||||
|
||||
|
||||
def _resolve_target_size(param, h_in, w_in):
|
||||
width = int(param.get("width", 0) or 0)
|
||||
height = int(param.get("height", 0) or 0)
|
||||
megapixels = float(param.get("megapixels", 0.0) or 0.0)
|
||||
if width > 0 and height > 0:
|
||||
return height, width
|
||||
if megapixels > 0:
|
||||
return _scale_to_megapixels(w_in, h_in, megapixels)
|
||||
return int(h_in), int(w_in)
|
||||
|
||||
|
||||
def upscale_video_model(video, param):
|
||||
model_name = param["model_name"]
|
||||
width = int(param["width"])
|
||||
height = int(param["height"])
|
||||
device = param.get("device", "cuda")
|
||||
precision = param.get("precision", "fp16")
|
||||
|
||||
@@ -359,7 +381,8 @@ def upscale_video_model(video, param):
|
||||
compute_dtype = {"fp32": torch.float32, "fp16": torch.float16, "bf16": torch.bfloat16}[precision]
|
||||
|
||||
_, c, t, h_in, w_in = video.shape
|
||||
h_out, w_out, eff = _compute_upscale_target(width, height, h_in, w_in)
|
||||
h_out, w_out = _resolve_target_size(param, h_in, w_in)
|
||||
eff = (w_out / float(w_in) + h_out / float(h_in)) / 2.0 if w_in and h_in else 1.0
|
||||
|
||||
if eff < 1.0 and (w_out < w_in or h_out < h_in):
|
||||
raise ValueError("This model only supports upscaling (effective scale >= 1.0).")
|
||||
@@ -386,10 +409,8 @@ def upscale_video_model(video, param):
|
||||
|
||||
def upscale_video_interp(video, param):
|
||||
method = str(param.get("method") or "bilinear")
|
||||
width = int(param.get("width", 0) or 0)
|
||||
height = int(param.get("height", 0) or 0)
|
||||
_, c, t, h_in, w_in = video.shape
|
||||
h_out, w_out, _ = _compute_upscale_target(width, height, h_in, w_in)
|
||||
h_out, w_out = _resolve_target_size(param, h_in, w_in)
|
||||
if h_out == h_in and w_out == w_in:
|
||||
return video, h_in, w_in
|
||||
video_bt = video.permute(0, 2, 1, 3, 4).reshape(-1, c, h_in, w_in)
|
||||
@@ -425,23 +446,42 @@ class H3LatentUpscaleParams:
|
||||
"method": (["nearest-exact", "bilinear", "area", "bicubic"], {"default": "bilinear",
|
||||
"tooltip": "Interpolation method used when mode = interp."}),
|
||||
"width": ("INT", {"default": 0, "min": 0, "max": 4096, "step": 32,
|
||||
"tooltip": "Target upscaled pixel width for the latent refinement stage. 0 keeps the original width and effectively disables the resize."}),
|
||||
"tooltip": "Explicit target width for the latent refinement stage. Leave at 0 to let megapixels choose the size instead."}),
|
||||
"height": ("INT", {"default": 0, "min": 0, "max": 4096, "step": 32,
|
||||
"tooltip": "Target upscaled pixel height for the latent refinement stage. 0 keeps the original height and effectively disables the resize."}),
|
||||
"tooltip": "Explicit target height for the latent refinement stage. Leave at 0 to let megapixels choose the size instead."}),
|
||||
"device": (["cuda", "cpu"], {"default": "cuda",
|
||||
"tooltip": "Device used by the H3 latent upscaler model when mode = model."}),
|
||||
"precision": (["fp16", "fp32", "bf16"], {"default": "fp16",
|
||||
"tooltip": "Computation precision used by the H3 latent upscaler model when mode = model."}),
|
||||
"refine_denoise": ("FLOAT", {"default": 0.25, "min": 0.0, "max": 1.0, "step": 0.01,
|
||||
"tooltip": "How much the 2-step refinement pass may rewrite the upscaled latent. Lower = safer, higher = freer."}),
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, {"default": "euler_ancestral",
|
||||
"tooltip": "Sampler used for the latent refinement pass. Default matches the current H3 preference."}),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"default": "simple",
|
||||
"tooltip": "Scheduler used for the latent refinement pass."}),
|
||||
"steps": ("INT", {"default": 2, "min": 1, "max": 50, "step": 1,
|
||||
"tooltip": "Number of refinement steps applied after the latent upscaler stage."}),
|
||||
"denoise": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0, "step": 0.01,
|
||||
"tooltip": "How much the refinement pass may rewrite the upscaled latent. Lower = safer, higher = freer."}),
|
||||
"megapixels": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 4.0, "step": 0.01,
|
||||
"tooltip": "Primary target size for the latent refinement stage. If width and height are both set, they win; otherwise the node scales the current shot to this pixel budget while preserving aspect ratio. 0 keeps the incoming latent size."}),
|
||||
}
|
||||
}
|
||||
|
||||
def build(self, mode, model_name, method, width, height, device, precision, refine_denoise):
|
||||
def build(self, mode, model_name, method, width, height, device, precision, sampler_name, scheduler, steps, denoise, megapixels):
|
||||
width = int(width)
|
||||
height = int(height)
|
||||
steps = int(steps)
|
||||
if mode == "off":
|
||||
return ({"mode": "off", "width": width, "height": height, "refine_denoise": float(refine_denoise)},)
|
||||
return ({
|
||||
"mode": "off",
|
||||
"width": width,
|
||||
"height": height,
|
||||
"sampler_name": sampler_name,
|
||||
"scheduler": scheduler,
|
||||
"steps": steps,
|
||||
"denoise": float(denoise),
|
||||
"refine_denoise": float(denoise),
|
||||
"megapixels": float(megapixels),
|
||||
},)
|
||||
if width > 0:
|
||||
width = int(round(width / 32.0)) * 32
|
||||
if height > 0:
|
||||
@@ -454,7 +494,12 @@ class H3LatentUpscaleParams:
|
||||
"height": height,
|
||||
"device": device,
|
||||
"precision": precision,
|
||||
"refine_denoise": float(refine_denoise),
|
||||
"sampler_name": sampler_name,
|
||||
"scheduler": scheduler,
|
||||
"steps": steps,
|
||||
"denoise": float(denoise),
|
||||
"refine_denoise": float(denoise),
|
||||
"megapixels": float(megapixels),
|
||||
},)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user