Почему диффузия рисует швы на 40-мегапиксельных фото и как сделать тайлы с памятью

Почему диффузия рисует швы на 40-мегапиксельных фото и как сделать тайлы с памятью

Я более двадцати лет работала ретушёром и последние четыре года пытаюсь адаптировать диффузионные модели для обработки профессиональных снимков с разрешением 40+ мегапикселей. Основная проблема — швы между тайлами и отсутствие у модели контекста. Это первая статья из цикла, в которой я делюсь тремя идеями, результатами исследований и предварительными тестами.

Откуда задача

Профессиональные камеры по-прежнему снимают на 40, 60, 100 и даже 150 мегапикселей. Эти файлы требуют качественной ретуши: кожи, волос, фона, цвета, света. Стандартный подход — разрезать изображение на тайлы, обработать и склеить. Но при этом возникают швы, а модель не понимает, что именно она обрабатывает: кожу, волосы, небо или металл.

Хочется, чтобы тайлы обрабатывались плавно, без видимых границ, и чтобы модель понимала контекст: «это щека, рядом волосы, выше — небо». Вместо «обработай 512×512 пикселей» — «обработай эту часть портрета».

Я провела исследование и не нашла системных работ по этой теме. Возможно, я плохо искала. Возможно, это реальная дыра в литературе. Сейчас — теория, ресерч, предварительные тесты.

Идея первая: видео-модели помнят кадры, наша фото-модель — нет

Под «фото-моделью» я имею в виду стандартные диффузионные модели: SDXL, FLUX, Klein, SANA — любые image-to-image архитектуры на базе UNet или DiT.

В видео-диффузии модель при генерации кадра видит не только его, но и предыдущие — за счёт механизма памяти: self-attention по временной оси, accumulated state, KV-cache. Благодаря этому фон не дёргается, цвет и освещение стабильны.

Фото-модель при обработке тайла (3, 5) не видит соседей. У неё нет памяти о предыдущих тайлах, нет понимания, что это часть одной сцены.

Если перенести механизм памяти из видео-моделей на пространственный тайлинг, можно решить две проблемы: швы (тайлы будут согласовывать цвет с соседями) и семантику (тайл с волосами узнает, что под ним — шея, а не шерсть).

Что мы ищем: критерии для тайлов

Размер тайла — 1024–2048 пикселей, чтобы сохранить качество и не усугублять количество тайлов. Профессиональные файлы — от 8K до 15K пикселей. На 150 МП при тайле 1024 получается до 190 тайлов. С перекрытием 50% — уже 540.

Проблема блендинга: на гладких участках (небо, кожа) шов можно скрыть, но на высоких частотах (волосы, текстуры) либо виден резкий переход, либо детали размазываются.

Любая архитектура с квадратичной сложностью по числу тайлов (например, full 3D attention) не запустится даже на 80 ГБ VRAM. Нужны эффективные решения.

Требования к архитектуре:

  • Дешёвая по числу тайлов
  • Работает inference-only
  • Pixel-precise output (не дискретные токены)
  • Простая, без лишнего функционала (без motion control, audio sync и т.п.)
  • Переносимый примитив памяти (не интегрированный в тяжёлую модель)

Можно ли выкидывать из памяти уже обработанные тайлы? Да. Есть три подхода:

  • Слайдинг: держим последние W тайлов (например, 8), остальные забываем. Просто, но не работает с далёкими связями.
  • Геометрическая компрессия: соседи — полное разрешение, диагональные — в 2×, далёкие — в 4×. Общий объём памяти сходится к константе.
  • Аккумуляция в state: не храним тайлы, только два маленьких тензора S и Z, которые «помнят» всё пройденное.

Восемь архитектурных классов памяти

Ключевые кандидаты: B (BCLA), D (Factored S+T), F (FramePack).

  • Тип B, BCLA (SANA-Video): линейное внимание с causal mask. Каждый тайл аккумулирует state в тензорах S (D×D) и Z (D). Стоимость — O(D²) на блок, не растёт с числом тайлов. Для SANA 1.6B — ~380 МБ state на всех слоях. Очень эффективно.
  • Тип D, Factored S+T (SVD): после spatial-блока тензор (B·T, C, H, W) преобразуется в (B·H·W, T, C), проходит temporal attention, возвращается обратно. Прямой перенос: T → N_tiles. Самый прямой, но хрупкий в реализации.
  • Тип F, FramePack: близкие тайлы — полное разрешение, далёкие — сжатые. Общий контекст сходится к константе. Можно работать с сетками 16×16 и больше.

Что отбрасываем:

  • Тип A (Full 3D attention): квадратичная сложность, не масштабируется.
  • Тип H (Discrete tokens): теряет пиксельную точность, не подходит для ретуши.
  • Большие модели (Wan 2.1, HunyuanVideo) — слишком тяжёлые.

Модели, которые уже на сцене

  • SANA-Video: кандидат на BCLA. Linear attention, NVFP4, видео-расширение SANA.
  • AnimateDiff: кандидат на factored S+T. Motion modules обучены, можно использовать inference.
  • SVD: наследие, но reshape хорошо задокументирован.
  • FramePack: для больших сеток, реализация на DiT.
  • StreamingT2V: CAM (cross-attn от соседей) и APM (CLIP-anchor). Можно прикрутить к pretrained backbone без ретренинга.

Прецеденты:

  • PatchVSR: видео-модель + dual-stream адаптер для патчей, но память между патчами не пробовали.
  • STA (Sliding Tile Attention): применили sliding-tile внимание к видео. Идея пришла оттуда.
  • FrescoDiffusion: ближайший аналог — tiled denoising для 4K I2V, но генерирует видео, не редактирует фото.

Системного эксперимента «temporal attention → cross-tile attention» я не нашла. Если знаете — дайте ссылку.

Карта переноса: видео → пространство

  • BCLA → S/Z аккумуляция между тайлами, тип B
  • FramePack → близкие full, диагональ 2×, далёкие 4×, тип F
  • SVD reshape → (B·N_tiles, C, H, W) → (B·H·W, N_tiles, C), тип D
  • AnimateDiff modules → cross-tile attention, тип D
  • StreamingT2V CAM → cross-attn от соседей, тип E
  • Ca2-VDM cache reuse → compute KV once, reuse, тип G

Что должно быть в датасете

Чтобы модель училась помнить соседние тайлы, датасет должен подавать не одиночные тайлы, а последовательности. Несколько разрешений, несколько режимов overlap.

У меня есть датасет из 53 000 фото ювелирных изделий. На одну фотку при tile=1024 и overlap — 30–50 тайлов. Strip-последовательность (прямая через тайлы) — 10–15 на фотку. С тремя scale’ами (512, 768, 1024) и двумя направлениями (LtR, TtB) — ~70 последовательностей на фотку. Всего — 3–4 млн сэмплов.

Как это может выглядеть

BCLA: два аккумулятора S и Z переживают между тайлами. Новый тайл cross-attend’ит к ним и обновляет.

SVD-style reshape: после spatial-блока тензор (B·N_tiles, C, H, W) → (B·H·W, N_tiles, C), проходит cross-tile attention, возвращается обратно.

Суть: для каждой пиксельной позиции (h, w) модель видит её копии во всех тайлах. Как в видео — «как пиксель выглядит во всех кадрах», стало — «во всех тайлах».

Что я уже попробовала

Только на SANA. У неё большое нативное разрешение (до 4K) и встроенный linear attention (тип B). Значит, примитив памяти уже есть в backbone.

Провела небольшое обучение на strip-последовательностях (tile=1024). Цель — проверить: сходится ли loss и работает ли перенос temporal → spatial.

Результат: loss сходится. Механизм работает — модель учится согласовывать тайлы, как раньше кадры. Цифры не публикую (тестовый прогон), но направление подтверждается.

Идея 1 решает горизонтальные связи. Но есть ещё одно упущение — модель не знает, где тайл находится в общей картинке.

Идея вторая: подадим модели всю картинку и положение тайла

Если у вас фото 6000×4000, и вы режете его на тайлы 512×512 — у вас есть вся картинка. Почему не использовать её?

Можно сделать downscaled-версию в латентном пространстве и подать её модели вместе с тайлом. И добавить координаты: два канала (x, y) ∈ [-1, 1]. Тайл (3, 5) будет знать, что он — (3, 5), а не «какой-то кусок».

Мотивация: PaDIS +10.3 dB

PaDIS (NeurIPS 2024) добавил два координатных канала. Без них PSNR падает с 33.57 до 23.25 дБ — минус 10.3 дБ. Авторы: «все результаты были очень низкого качества».

Без позиции модель пытается одной функцией восстановить все патчи. Без привязки к месту — выдаёт усреднённый шум. С координатами — появляется patch-prior: модель знает, что «в этом регионе обычно лицо, здесь небо».

Стоит копейки — два числа на пиксель. Но в современных пайплайнах почти никто этого не делает. Возможно, из-за фиксированного входа pretrained-моделей.

Три уровня сигнала

Что должна знать модель о тайле:

  • Геометрический: «я тайл (3, 5) из сетки 8×8» — PaDIS, два канала (x, y)
  • Визуальный: «вся картинка выглядит так» — DemoFusion, FreeScale, DC-VSR, ResMaster
  • Семантический: «я обрабатываю кожу, рядом волосы» — AccDiffusion v2, per-tile prompt через VLM

Tiled VAE даёт только пиксели и общий prompt. Остальное — на стороне «что добавить».

Визуальный уровень:

  • Рабочий №1: downscaled VAE-латент полной картинки в первый conv-слой
  • Рабочий №2: 64-мерный вектор глобальных свойств (цвет, экспозиция, баланс белого) через AdaLN-Zero
  • Тупиковый: CLIP image embedding (IP-Adapter) — теряет пиксельную точность

Семантический уровень:

  • Per-tile prompt через VLM (Florence-2, Qwen2-VL)
  • Например: тайл с плечом и волосами получает prompt «skin and hair, no fur» — галлюцинация «шерсть» становится невозможной
  • Стоимость: один VLM-pass на картинку + короткий запрос на тайл (~50 мс)

Как это может выглядеть

На вход тайла: concat его латента + coord-каналов + downscaled-латента полной картинки + опциональной seg-маски. Первый conv-слой с zero-init проекцией. Плюс 64-мерный вектор глобальных статистик через AdaLN-Zero. И per-tile prompt из одного VLM-pass’а.

Zero-init критичен: иначе на t=0 модель видит случайные веса, и pretrained функционал ломается. Zero-init — архитектура сначала как у backbone, обучение постепенно включает новые каналы. Стандартный трюк (ControlNet, AnimateDiff).

Что я уже попробовала

IP-Adapter с downscaled-превью: гипотеза — тайл получит «общую визуальную подсказку». Проверила: real preview vs random noise. Разница — 0.0066 на пиксель (порог 0.02). Сигнал пренебрежимо мал.

Причина: IP-Adapter обучали на bigG-ViT, у нас — CLIP-L + CLIP-G. Mismatch энкодеров съедает сигнал. Нужен либо bigG, либо native SDXL conditioning.

Бонусная идея: Detail Demon + апскейл диффузией = тайлинг можно сократить вдвое

Это пока гипотеза. Не тестировала. Но логика ясна.

Что такое Detail Demon

Detail Demon (или Daemon) — патч для sampler’а, который изменяет sigma-schedule, чтобы поздние шаги денойза давали больше детализации. В зоне малых sigma добавляется «детальный» отрезок. Без переобучения модели.

Результат: при том же числе шагов — больше резкости, больше деталей, меньше AI-сглаживания.

Как работает обычный апскейл

Берём маленькую картинку (512×512), bicubic-апскейлим до 1024×1024, потом диффузией «дорисовываем» детали.

Если картинка большая (2048+), — не лезет в VRAM. Режем на тайлы, апскейлим отдельно, склеиваем. Швы, дублирования, цветовые сдвиги — те же проблемы.

Куда я хочу прийти

Гипотеза:

  • Первая половина шагов — низкочастотная структура (цвет, композиция). Можно делать на downscaled-версии, целиком, без тайлов.
  • Вторая половина — высокочастотная детализация. Здесь помогает Detail Demon: он добавляет HF через sampler, не через re-denoise. Работает локально, не пересчитывая всю траекторию.

Выигрыш: первая половина — быстро, без тайлов, без швов. Вторая — Detail Demon на полном разрешении. В идеале — пайплайн без тайлинга или с тайлингом только в HF-фазе.

Где это может сломаться

Detail Demon на 4096×4096 — attention map не лезет даже в 80 ГБ VRAM. Чистый «без тайлов» — только до ~2048. Дальше нужен тайлинг в HF-фазе. Но проблема швов решается контекстом из первых двух идей.

Это гипотеза для тестирования. Возможно, будет в Части 3. Если повезёт с H100 — попробую раньше.

Что это не доказывает

Антирезультаты честнее позитивных. Чего я не могу утверждать:

  • Полная абляция не сделана. Подтвердила сходимость и базовый перенос на SANA, но это не полное обучение и не сравнение с baseline’ами. До цифр seam_PSNR, deltaE_ratio, HF-SSIM — ещё далеко.
  • Не знаю, какая архитектура лучше. SANA-BCLA — лучший по памяти, Klein-cache — по цвету, SVD-factored — по прямому переносу. Кто выиграет — не знаю.
  • Не знаю, как масштабируется на 16×16+. Все тесты — на 3×3–7×7. Для 100+ тайлов нужны FramePack или sliding window.
  • Семантический уровень не тестировала. Есть идея: один VLM-pass на картинку, а на тайлах — маскирование токенов, которых там нет. Например, в тайле «небо» — приглушаем токены «лицо», «металл». Формально похоже на AccDiffusion v2 и Regional Prompter.
  • Detail Demon + апскейл — чисто гипотеза. Архитектурный набросок. Может сломаться на VRAM или дать новые артефакты.
Читать оригинал