Посмотреть как Markdown

Восстановление изображений

Восстановление изображений принимает искажённое изображение и возвращает чистое. LibreYOLO предоставляет его как задачу restore, которая охватывает шумоподавление, устранение размытия и суперразрешение за единым контрактом вывода: на входе одно RGB-изображение, на выходе одно RGB-изображение.

Определение

Задача restore отображает одно изображение в другое. Шумоподавление, устранение размытия и суперразрешение — здесь одна и та же задача, потому что у них общий контракт: модель принимает RGB-изображение и возвращает RGB-изображение, а деградация, которую модель учили устранять, — свойство чекпойнта, а не API.

Предсказание заполняет result.restored — полезную нагрузку RestoredImage с массивом RGB (H, W, 3) типа uint8. .array возвращает его как NumPy, а .save(path) записывает его на диск. result.restore_scale хранит коэффициент увеличения, который несёт выходной холст; для чекпойнта, сохраняющего разрешение, он равен 1. result.boxes остаётся пустым, поэтому conf, iou и max_det принимаются ради совместимости сигнатуры, но ни на что не влияют, а save=True записывает восстановленное изображение напрямую, а не аннотированное фото.

Модели

Задачу restore обслуживают три семейства, разделённые по деградации, которую они устраняют.

NAFNet отвечает за шумоподавление и остаётся единственным семейством restore, которое LibreYOLO умеет обучать. Его архитектура заменяет нелинейные активации в блоке UNet поэлементным умножением, а опубликованный чекпойнт обучен на реальном шуме SIDD. Разрешение выхода совпадает со входным.

Real-ESRGAN — практичный вариант для увеличения разрешения: три чекпойнта, обученные на синтетических деградациях, а не только на бикубическом уменьшении, с масштабами 4x, 2x и меньшим, более быстрым генератором 4x, рассчитанным на меньшую задержку.

SwinIR увеличивает разрешение в 4 раза с бэкбоном Swin Transformer, в трёх размерах, охватывающих официальный облегчённый генератор и два генератора для реальных изображений.

Предсказание

Веса скачиваются с Hugging Face при первом запуске и кэшируются локально.

Увеличение изображения
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Компактный генератор 4x; tile ограничивает пик памяти на большом источнике.model = LibreYOLO("LibreRealESRGANx4t-restore.pt")result = model(SAMPLE_IMAGE, tile=512, tile_pad=10) result.restored.save("upscaled.png")print(result.restored.array.shape)   # в 4 раза больше входа по каждой оси
Шумоподавление изображения
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Обучена на реальном шуме SIDD; размер выхода совпадает со входным.model = LibreYOLO("LibreNAFNetl-restore-sidd.pt")result = model(SAMPLE_IMAGE) result.restored.save("denoised.png")print(result.restore_scale)   # 1: этот чекпойнт не увеличивает разрешение

Восстановление работает в собственном разрешении исходного изображения, а не на фиксированном холсте сети, и дополняет его только до кратности коэффициенту понижения разрешения сети, поэтому и время, и память растут вместе с числом пикселей входа. tile разбивает прямой проход на перекрывающиеся тайлы и сглаживает стыки между ними, а tile_pad — это поля вокруг каждого тайла, которые потом обрезаются обратно; оба — именованные аргументы Python. Про источники, стриминг и обработку результата смотрите предсказание.

Формат датасета

Восстановление сопоставляет каждому искажённому входному изображению чистое целевое изображение ровно того же разрешения; пара определяется по имени файла без расширения.

dataset/
  data.yaml
  inputs/
    train/photo.jpg
    val/photo.jpg
  targets/
    train/photo.jpg
    val/photo.jpg
yaml
path: dataset
train: inputs/train
val: inputs/val
input_dir: inputs
target_dir: targets
degradation: denoise
dataset: MyDataset
nc: 1
names: {0: image}

nc и names — заглушки схемы; модель restore возвращает Results.restored, а не детекции. degradation и dataset — необязательные метки происхождения. target_stem_suffix рассчитан на датасеты, где чистое изображение названо иначе, чем его искажённая пара. Валидация сохраняет исходное разрешение и дополняет ровно настолько, чтобы собрать батч, поэтому метрики считаются на исходном холсте. Полный контракт описан в форматах датасетов.

Обучение

NAFNet — единственное семейство restore с реализацией обучения. Real-ESRGAN.train() и SwinIR.train() оба выбрасывают NotImplementedError: эти чекпойнты получены GAN-обучением поверх синтетических пайплайнов деградации, и обучающий цикл restore для парных данных запустился бы, не воспроизводя этот рецепт.

Дообучение NAFNet на парных изображениях
from libreyolo import LibreYOLO model = LibreYOLO("LibreNAFNetl-restore-sidd.pt")model.train(data="my-dataset.yaml", epochs=100, imgsz=256, batch=16, lr0=1e-3)
Запись происхождения в чекпойнт
from libreyolo import LibreYOLO model = LibreYOLO("LibreNAFNetl-restore-sidd.pt") # degradation и dataset записываются в сохранённый чекпойнт для# отслеживания происхождения; в обучении они не участвуют.model.train(    data="my-dataset.yaml",    epochs=100,    degradation="denoise",    dataset="MyDataset",)

Обучающий цикл берёт из входного и целевого изображений согласованные кропы, поэтому обе стороны остаются выровненными. Про датасеты, обучение на нескольких GPU и логгеры смотрите обучение, а про умолчания этого семейства и пулинг, который оно применяет на инференсе и отключает во время обучения, — страницу NAFNet.

Валидация

val() сравнивает восстановленное изображение с чистой целью, в RGB, на исходном холсте, без обрезки границ и без изменения размера.

Валидация и чтение ключей метрик
from libreyolo import LibreYOLO model = LibreYOLO("LibreNAFNetl-restore-sidd.pt") # val() возвращает обычный dict, а не объект.metrics = model.val(data="my-dataset.yaml") print(metrics["metrics/PSNR"])   # fitnessprint(metrics["metrics/SSIM"])

metrics/PSNR — пиковое отношение сигнала к шуму в децибелах, и это же значение служит fitness, числом, по которому выбирается лучший чекпойнт. metrics/SSIM — структурное сходство в [0, 1], посчитанное с гауссовым окном 11x11 при сигме 1.5 и усреднённое по трём цветовым каналам. Для обеих метрик больше — лучше.

Экспорт

Экспортированная модель restore загружается обратно через LibreYOLO() по суффиксу файла, поэтому файл .onnx или .engine ведёт себя как чекпойнт и возвращает тот же Results, где restored несёт выходное изображение.

Экспорт
from libreyolo import LibreYOLO model = LibreYOLO("LibreNAFNetl-restore-sidd.pt") # imgsz фиксируется в графе, поэтому передавайте тот размер, который# ваше развёртывание действительно подаёт модели.model.export(format="onnx", imgsz=256)
Запуск экспортированного файла
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Фабрика выбирает загрузчик по суффиксу файла, поэтому экспортированный# артефакт грузится как обычный чекпойнт и возвращает тот же Results.model = LibreYOLO("LibreNAFNetl-restore-sidd.onnx")result = model(SAMPLE_IMAGE) result.restored.save("denoised.png")

Экспорт restore фиксирует пространственное разрешение в графе, поэтому передавайте тот imgsz, который ваше развёртывание действительно будет подавать модели. Для NAFNet этот размер должен делиться на коэффициент понижения разрешения сети, и при dynamic=True динамическим остаётся только измерение батча. Для Real-ESRGAN и SwinIR, если imgsz не указан, берётся небольшой внутренний размер патча, а не ваше рабочее разрешение. Поддержка по форматам описана на странице каждой модели и в полной матрице экспорта. В разделе экспорт перечислены аргументы, которые принимает каждый формат.

Проверено с LibreYOLO v1.5.0.