Download clean.py from q6/N: direct link, hf CLI and curl.
- Browser
- Download file 2.32 kB
-
https://huggingface.co/spaces/q6/N/resolve/main/clean.py
- Command line
-
hf download hf://spaces/q6/N/clean.py
-
curl -L -o clean.py https://huggingface.co/spaces/q6/N/resolve/main/clean.py
2.32 kB
| import numpy as np | |
| import torch | |
| from pathlib import Path | |
| from huggingface_hub.constants import HF_HUB_CACHE | |
| from PIL import Image | |
| from spandrel import ImageModelDescriptor, ModelLoader | |
| CLEAN_BUCKET = "HyperHail/CB" | |
| CLEAN_FILE = "upscale_models/3_1x-Archivist_Soft.pth" | |
| TILE_SIZE = 256 | |
| TILE_PAD = 32 | |
| PIXEL_MAX = 255 | |
| def download_clean(): | |
| path = Path(HF_HUB_CACHE) / f"buckets--{CLEAN_BUCKET.replace('/', '--')}" / CLEAN_FILE | |
| if not path.is_file(): | |
| path.parent.mkdir(parents=True, exist_ok=True) | |
| url = f"https://huggingface.co/buckets/{CLEAN_BUCKET}/resolve/{CLEAN_FILE}" | |
| torch.hub.download_url_to_file(url, str(path), progress=False) | |
| return str(path) | |
| def load_clean(device): | |
| model = ModelLoader().load_from_file(download_clean()) | |
| if not isinstance(model, ImageModelDescriptor) or model.scale != 1: | |
| raise ValueError("Clean after requires a 1x image model") | |
| if model.input_channels != 3 or model.output_channels != 3: | |
| raise ValueError("Clean after requires an RGB model") | |
| return model.to(device).eval() | |
| def clean_image(model, input_path, output_path): | |
| device = next(model.model.parameters()).device | |
| with Image.open(input_path) as source: | |
| image = source.convert("RGB") | |
| alpha = source.convert("RGBA").getchannel("A") if "A" in source.getbands() or "transparency" in source.info else None | |
| width, height = image.size | |
| result = Image.new("RGB", image.size) | |
| for y in range(0, height, TILE_SIZE): | |
| for x in range(0, width, TILE_SIZE): | |
| right, bottom = min(x + TILE_SIZE, width), min(y + TILE_SIZE, height) | |
| left, top = max(0, x - TILE_PAD), max(0, y - TILE_PAD) | |
| box = (left, top, min(width, right + TILE_PAD), min(height, bottom + TILE_PAD)) | |
| pixels = np.array(image.crop(box), dtype=np.float32) / PIXEL_MAX | |
| tile = torch.from_numpy(pixels).permute(2, 0, 1).unsqueeze(0).to(device) | |
| output = model(tile)[0].clamp(0, 1).mul(PIXEL_MAX).round().byte() | |
| patch = Image.fromarray(output.permute(1, 2, 0).cpu().numpy()) | |
| result.paste(patch.crop((x - left, y - top, right - left, bottom - top)), (x, y)) | |
| if alpha is not None: | |
| result.putalpha(alpha) | |
| result.save(output_path, format="PNG") | |