aleph65's picture
Upload folder using huggingface_hub
f827b9d verified
Raw
History Blame Contribute Delete
3.48 kB
"""PLXR Deteriorate — apply the training-time synthetic degradation to an image.
Wraps the recipe families from the qwen-edit-restore project's deteriorate.py
(bundled as deteriorate_core.py) so a workflow can force-degrade an input
before restoration, for testing / guaranteeing visible deterioration.
"""
import io
import random
import numpy as np
import torch
from PIL import Image
from . import deteriorate_core as core
_REMBG_SESSION = None
def _person_mask_from_array(img01):
"""Soft subject mask via rembg, from a float [H,W,3] array. None on failure."""
global _REMBG_SESSION
try:
from rembg import remove, new_session
if _REMBG_SESSION is None:
_REMBG_SESSION = new_session("u2net")
buf = io.BytesIO()
Image.fromarray(core.to_uint8(img01)).save(buf, format="PNG")
out = remove(buf.getvalue(), session=_REMBG_SESSION, only_mask=True)
m = np.asarray(Image.open(io.BytesIO(out)).convert("L"),
dtype=np.float32) / 255.0
if m.shape != img01.shape[:2]:
import cv2
m = cv2.resize(m, (img01.shape[1], img01.shape[0]))
return m
except Exception as e:
print(f"[plxr_deteriorate] person mask failed ({e}); bg-blur ops degrade to global blur")
return None
class PLXRDeteriorate:
CATEGORY = "image/plxr"
RETURN_TYPES = ("IMAGE",)
FUNCTION = "run"
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"image": ("IMAGE",),
"family": (["random", "atmospheric", "digital"],),
"severity_min": ("FLOAT", {"default": 0.35, "min": 0.0, "max": 1.0, "step": 0.05}),
"severity_max": ("FLOAT", {"default": 0.85, "min": 0.0, "max": 1.0, "step": 0.05}),
"seed": ("INT", {"default": 0, "min": 0, "max": 2**32 - 1}),
"use_person_mask": ("BOOLEAN", {"default": True}),
}
}
def run(self, image, family, severity_min, severity_max, seed, use_person_mask):
out = []
for b in range(image.shape[0]):
x0 = image[b].cpu().numpy().astype(np.float32) # [H,W,C] 0..1
x0 = np.clip(x0[..., :3], 0.0, 1.0)
item_seed = seed + b
rng_np = np.random.default_rng(item_seed)
pyrng = random.Random(item_seed ^ 0xABCD)
class R:
uniform = staticmethod(pyrng.uniform)
choice = staticmethod(pyrng.choice)
random = staticmethod(pyrng.random)
normal = staticmethod(rng_np.normal)
lo, hi = sorted((severity_min, severity_max))
sev = pyrng.uniform(lo, hi)
fam = family
if fam == "random":
fam = pyrng.choice(["atmospheric", "digital"])
recipe = (core.recipe_atmospheric if fam == "atmospheric"
else core.recipe_digital)
mask = _person_mask_from_array(x0) if use_person_mask else None
y, label = recipe(x0.copy(), R, sev, mask)
print(f"[plxr_deteriorate] applied {label} sev={sev:.2f} seed={item_seed}")
y = np.clip(y, 0.0, 1.0)
out.append(torch.from_numpy(y.astype(np.float32)))
return (torch.stack(out).to(image.device),)
NODE_CLASS_MAPPINGS = {"PLXRDeteriorate": PLXRDeteriorate}
NODE_DISPLAY_NAME_MAPPINGS = {"PLXRDeteriorate": "PLXR Deteriorate (restore-lora test)"}