ШІ Super-Resolution — апскейл зображень
Бікубічна інтерполяція дає 4x апскейл із розмиттям. ШІ super-resolution відновлює деталі: текстури шкіри, текст на вивісках, структуру тканини. Різниця видна при порівнянні PSNR: бікубік — 28–30 dB, Real-ESRGAN — 32–36 dB на фотографіях.
Real-ESRGAN — практичний стандарт
import torch
import numpy as np
from PIL import Image
from basicsr.archs.rrdbnet_arch import RRDBNet
from realesrgan import RealESRGANer
def upscale_image(
image_path: str,
scale: int = 4,
model_name: str = 'RealESRGAN_x4plus', # або 'RealESRGAN_x4plus_anime_6B'
tile_size: int = 512, # для великих зображень — обробка плитками
half_precision: bool = True
) -> np.ndarray:
"""
tile_size=512 при VRAM 6GB, tile_size=0 (все зображення) при VRAM 24GB.
half=True — FP16, економить ~50% VRAM.
"""
model = RRDBNet(
num_in_ch=3, num_out_ch=3,
num_feat=64, num_block=23, num_grow_ch=32,
scale=scale
)
upsampler = RealESRGANer(
scale=scale,
model_path=f'weights/{model_name}.pth',
model=model,
tile=tile_size,
tile_pad=10, # перекриття плиток для гладких швів
pre_pad=0,
half=half_precision,
device='cuda'
)
img = np.array(Image.open(image_path).convert('RGB'))
output, _ = upsampler.enhance(img, outscale=scale)
return output
GFPGAN для відновлення облич
Real-ESRGAN на портретах іноді створює артефакти на обличчі. GFPGAN додає face restoration поверх SR:
from gfpgan import GFPGANer
def restore_face_photo(
degraded_image: np.ndarray,
upscale: int = 2,
arch: str = 'clean', # 'clean' | 'RestoreFormer'
channel_multiplier: int = 2,
weight: float = 0.5 # 0=чистий GFPGAN, 1=без face enhancement
) -> np.ndarray:
"""
weight=0.5 — компроміс між відновленням та збереженням
індивідуальних рис. При weight=0 обличчя виглядають «глянцево».
"""
restorer = GFPGANer(
model_path='weights/GFPGANv1.4.pth',
upscale=upscale,
arch=arch,
channel_multiplier=channel_multiplier,
bg_upsampler=None # можна передати RealESRGANer для фону
)
_, _, restored = restorer.enhance(
degraded_image,
has_aligned=False,
only_center_face=False,
paste_back=True,
weight=weight
)
return restored
Метрики та порівняння моделей
| Модель | PSNR (Set5 4x) | SSIM | Швидкість 1080p→4K | Застосування |
|---|---|---|---|---|
| Bicubic | 28.42 | 0.810 | Миттєво | Baseline |
| SRCNN | 30.48 | 0.862 | Швидко | Застаріла |
| ESRGAN | 32.73 | 0.901 | ~2s RTX3080 | Фото |
| Real-ESRGAN x4+ | 33.98 | 0.918 | ~3s RTX3080 | Фото, текст |
| SwinIR-L | 34.97 | 0.932 | ~8s RTX3080 | Максимальна якість |
| GFPGAN v1.4 | — | — | ~4s RTX3080 | Портрети |
PSNR — не єдиний критерій: людське сприйняття корелює з LPIPS (perceptual loss). Real-ESRGAN при меншому PSNR ніж SwinIR часто виглядає краще суб'єктивно через вищочастотні деталі.
Пакетна обробка великих обсягів
from pathlib import Path
import torch
from torch.utils.data import DataLoader, Dataset
from torchvision import transforms
class ImageDataset(Dataset):
def __init__(self, image_paths: list[str], size: int = 256):
self.paths = image_paths
self.transform = transforms.Compose([
transforms.Resize((size, size)),
transforms.ToTensor()
])
def __len__(self): return len(self.paths)
def __getitem__(self, idx):
img = Image.open(self.paths[idx]).convert('RGB')
return self.transform(img), self.paths[idx]
def batch_upscale_pipeline(
input_dir: str,
output_dir: str,
batch_size: int = 4, # при VRAM 12GB та tile_size=0
scale: int = 4
):
paths = list(Path(input_dir).glob('*.{jpg,jpeg,png}'))
Path(output_dir).mkdir(exist_ok=True)
# Для пакетного інференсу використовуємо прямий forward pass
# (RealESRGANer не підтримує пакети, потрібен прямий виклик моделі)
model = RRDBNet(
num_in_ch=3, num_out_ch=3,
num_feat=64, num_block=23, num_grow_ch=32, scale=scale
)
model.load_state_dict(
torch.load(f'weights/RealESRGAN_x4plus.pth')['params_ema']
)
model.eval().cuda().half()
for path in paths:
with torch.no_grad(), torch.cuda.amp.autocast():
img_t = transforms.ToTensor()(
Image.open(path).convert('RGB')
).unsqueeze(0).half().cuda()
out = model(img_t).squeeze(0).float().cpu()
out_img = transforms.ToPILImage()(out.clamp(0, 1))
out_img.save(
Path(output_dir) / (Path(path).stem + '_4x.png')
)
Обмеження та типові проблеми
- Галюцинації текстур — Real-ESRGAN може додати неіснуючий текст на вивісках. На forensics-застосуваннях це неприйнятно
-
OOM на великих зображеннях — 12-мегапіксельне фото при 4x апскейл = 192Мп, не вміщується в пам'ять. Рішення:
tile_size=512зtile_pad=10 - JPEG-артефакти — блочність артефактів JPEG посилюється SR. Предобробка: JPEG-aware denoise (nf_denoise з BasicSR)
Часові рамки
| Завдання | Час |
|---|---|
| API-сервіс SR (Real-ESRGAN) | 1–2 тижні |
| Fine-tuning на специфічний домен | 4–6 тижнів |
| Кастомна SR-модель з нуля | 10–16 тижнів |







