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

от автора

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

Откуда вообще задача.

​ Мир ретуши не сводится к картинкам в 2048 пикселей по стороне. Профессиональные камеры до сих пор делают огромные файлы. Сорок мегапикселей, шестьдесят, сто, иногда сто пятьдесят. И весь этот объём всё так же требует ретуши, кожа, волосы, цвет, свет, чистка фона. Как было десять лет назад, так и сейчас. Никуда задача не ушла. ​ Подход к этим кадрам везде один и тот же. Режем картинку на тайлы, обрабатываем по кусочку, склеиваем обратно. Кто-то делает это аккуратнее, кто-то нет. Но проблема одна на всех, границы между тайлами и модель которая не понимает что она видит. ​ Перед моделью при генерации кусочек чего-то. Чего именно? Никто не знает. И вот это — настоящая проблема. ​ Хочется чтобы тайлы шли гладко, без видимых швов. И чтобы модель понимала, с чем она вообще имеет дело, что вот тут кожа, тут волосы, тут небо, тут металл с отражением. Не «обработай 512×512 пикселей». А «обработай вот эту часть портрета, рядом, щека, выше, волосы». ​ В этой статье я хочу выложить три идеи. Я сделала несколько ресерч-сессий и не нашла, чтобы кто-то системно смотрел в эту сторону. То ли я плохо искала. То ли действительно дыра в литературе. Возможно и то, и другое. Сейчас, теория, ресерч, предварительные тесты. Давайте приступим. ​

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

Сразу про термин. Дальше по тексту я буду называть «фото-моделью» обычную image-to-image диффузионку, SDXL, FLUX, Klein, SANA, что угодно из стандартного набора. Технически это reverse-diffusion с UNet’ом или DiT’ом. Договорились, “фото-модель”, поехали. ​ В видео-диффузии решают похожую задачу. Только там «соседние сущности», это кадры, у нас это тайлы рядом стоящие. Когда видео-модель генерирует, скажем, восемнадцатый кадр, она видит не только восемнадцатый. Она помнит про семнадцатый, шестнадцатый, какие-то ключевые ранние, иногда самый первый. Эта память живёт внутри архитектуры, в форме self-attention поверх временной оси, в форме accumulated state, в форме KV-cache между чанками. И благодаря ей у нас на видео не дёргается фон, не плывёт цвет, не меняется освещение между кадрами. ​ У нашей фото-модели в момент обработки тайла (3, 5) этой памяти нет. Она получает свой кусок пикселей и текстовый prompt. Всё. Ни соседнего тайла слева, ни тайла сверху, ни общего понимания, что это вообще одна картинка. ​ Если перенести механизм памяти из видео-генерации на пространственный тайлинг, теоретически можно решить и швы (тайлы помнят цвет соседей и не уходят в свою сторону), и часть семантики (тайл с волосами знает, что под ним началась шея, а не шерсть). Звучит как простая ассоциация. Но если зайти внутрь, там восемь архитектурных классов памяти, и не все они переносимы на плоскость изображения. ​

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

​ Прежде чем нырять в таблицу классов, что мы вообще ищем. Архитектура памяти должна делать несколько вещей сразу.

Дёшево по числу тайлов. Сразу прикинем масштаб. Размер тайла мы берём в диапазоне 1024-2048 пикселей, это нативное разрешение современных моделей. SDXL и SANA нативно сидят на 1024 (SANA в дополнение тренировали и до 4K). FLUX и Klein приемлемо работают на 2048. Опускаться ниже 1024 нет смысла — качество просаживается а количество тайлов растет.

Профессиональная съёмка сегодня, это файлы от 8K до 15K пикселей по длинной стороне. Phase One IQ4, 14200×10600. Hasselblad H6D-100c, 11600×8700. Полнокадровая Canon R5, 8192×5464. Sony A7R V легко за 12K. На этих файлах при 1024 с небольшим перекрытием получается: 60 MP → ~75-80 тайлов 100 MP → ~130 тайлов 150 MP → ~190 тайлов

И тут вылазит ещё один параметр, overlap, перекрытие между соседними тайлами. Без него швы видно крайне сильно. Обычно швы прячутся блендингом, но число тайлов растёт. На том же 150-мегапиксельном файле при tile=1024: overlap 25%, это уже ~270 тайлов, overlap 50%, около 540. И тут ещё один минус блендинга, который сразу видно. Он по-разному работает на разных частотах картинки. На гладком (низкие частоты неба, тон кожи, плавный градиент в отражении металла) стык можно скрыть неплохо, цветовой переход замаскируется. А вот на высоких частотах (текстура волос, фактура камня, шум, мелкие царапины) либо вылезает драматический перепад на границе тайлов, либо, наоборот, верхняя частота размазывается из-за блюра смешивания соседей. Одной ручкой обе оси не починишь: чем агрессивнее блендим, тем мягче цветовой шов на гладком, но тем хуже текстура.

При tile=2048 (если работаешь на FLUX или Klein) количество тайлов меньше в 4 раза, но всё равно набегают десятки даже на средних файлах. То есть 150+ тайлов на одну картинку — это нормальный рабочий случай. Любая архитектурная стоимость, квадратичная по числу тайлов, на таких сетках просто не запустится, ни в 80 ГБ VRAM, ни в 192 ГБ. Full 3D attention отсюда выпадает сразу.

Если механизм хотя бы частично работает inference-only, это огромный плюс для нашей затеи.

Pixel-precise output. Мы ретушируем текстуру, не генерируем эстетику. Discrete-token модели типа Cosmos с FSQ-словарём на 64K квантизируют HF и съедают тонкие детали. Не подойдет.

Мне в принципе хотелось бы вот что. Apache 2.0 (чтобы можно было в продукт без переговоров), простую архитектуру и без лишнего груза. Современные топовые видео-модели, Wan 2.1 на 14 миллиардов параметров, HunyuanVideo на 13, CogVideoX, Open-Sora 2.0, слишком много в себе несут. Длинное видео, motion control, audio sync, multi-shot композиция. Половина функциональности, решение задач, которых у нас вообще нет. А VRAM и время загрузки весов платим за неё в полном объёме. Спасибо, не надо.

Нужен рабочий примитив, механизм памяти между соседями, отделимый от родительской модели и переносимый на свою фото-модель. SANA-Video, AnimateDiff, SVD, FramePack, каждая из этих работ изолирует такой примитив, он живёт отдельно от своей обвески. Wan и Hunyuan — нет, у них всё интегрировано в один стек, ничего не отделишь.

Естественный вопрос с места. А нельзя ли по ходу обработки выкидывать из памяти то, что уже сделали? Чтобы 200 тайлов не лежали все одновременно в VRAM, со всеми своими K/V-тензорами и attention-картами.

Можно. И это, по сути, главная ось по которой я выбираю архитектуру. Есть три способа разной степени радикальности:

Естественный вопрос с места. А нельзя ли по ходу обработки выкидывать из памяти то, что уже сделали? Чтобы 200 тайлов не лежали все одновременно в VRAM, со всеми своими K/V-тензорами и attention-картами.

Можно. И это, по сути, главная ось по которой я выбираю архитектуру. Есть три способа разной степени радикальности:

Слайдинг. Держим в памяти только последние W тайлов (скажем, 8), всё что дальше, забываем. Просто. Минус, не работает для далёких связей: если в правом верхнем углу зеркальное отражение того, что было в левом нижнем, мы это уже не увидим. Это тип C в таблице ниже. Геометрическая компрессия. Соседей держим в полном разрешении, диагональных, downsample’им в 2 раза, далёких, в 4 раза, и так далее. Total memory сходится к константе, не зависит от размера фото. Это тип F (FramePack). Аккумуляция в state. Самое радикальное. Тайлы вообще не храним. Держим только два маленьких тензора-сумматора S и Z, которые «помнят» всё что прошло, без хранения деталей. Это тип B (BCLA из SANA-Video).

Все три, primary-кандидаты в таблице ниже.

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

Тип

Механизм

Где встретить

На тайлы

Что переносим

A. Full 3D attention

Все токены space+time видят всех, 3D RoPE

Wan 2.1, HunyuanVideo, CogVideoX

Drop

O((T·H·W)²), для 64+ тайлов не запустится

B. Block Causal Linear (BCLA) ★★★

S = Σ KᵀV, Z = Σ Kᵀ. Константная state O(D²)

SANA-Video, MiraMo

Primary

~380 МБ суммарного state на 1.6B модель (по всем слоям, fp16), не зависит от числа тайлов

C. Sliding window

Attend к последним W кадрам

CausVid, Self-Forcing

Backup

Хорошо для local consistency, плохо для далёких тайлов

D. Factored S+T ★★

Temporal attn после каждого spatial. Reshape (B·T, C, H, W) → (B·H·W, T, C)

SVD, AnimateDiff, Latte

Direct map

«Для каждой пиксельной позиции attend через все кадры» = «через все тайлы»

E. Anchor frame

Все кадры обязательно attend к frame 0

Rolling Forcing

Augment

Анкор-тайл (угловой/центральный) выравнивает цвет

F. Geometric compression ★★★

Близкие = full, далёкие = compressed. Total CONVERGES

FramePack, MAG

Primary

Соседи = full, диагональ = 2×, далёкие = 4×

G. Cache sharing

KV-cache при t=0 переиспользуется на всех denoising steps

Ca2-VDM, TempCache

Augment

Compute neighbor features once, reuse N_steps ×

H. Discrete tokens

FSQ vocab=64K, Llama-style next-token

Cosmos

Drop

Несовместимо с continuous pixel editing

Ключевые в нашем переносе, B, D, F. Дальше про каждый по абзацу.

Type B, BCLA из SANA-Video. Linear attention с causal mask: каждый блок (каждый кадр = тайл) аккумулирует state в виде двух тензоров, S = Σ KᵀV размером D×D и Z = Σ Kᵀ размером D. Когда новый блок приходит, он cross-attend’ит не ко всем предыдущим токенам, а к этим двум аккумуляторам. Стоимость: O(D²) на блок, не растёт с числом блоков. Для нас это значит что 100 тайлов стоят столько же, сколько 10. На SANA 1.6B при D ≈ 2304 и ~28 слоях суммарный state по всем слоям выходит около 380 МБ в fp16. Очень привлекательно.

Type D, Factored S+T (SVD). Stable Video Diffusion добавил поверх SDXL UNet temporal-блок после каждого spatial, 656M доп. параметров, 43% всей модели. Архитектурно делается через reshape: тензор формы (B·T, C, H, W) после spatial блока перевзят как (B·H·W, T, C), прогоняется через temporal attention, возвращается обратно. На тайлы переводится дословно: B·T → B·N_tiles, T → N_tiles. Temporal attention становится cross-tile attention для каждой пиксельной позиции. Самый прямой 1:1 перенос. Но кажется что самый хрупкий в реализации.

Type F, FramePack. Lvmin Zhang (тот же автор, что ControlNet) сделал гениальную штуку. Близкие кадры пакуются в context на максимальной плотности, далёкие, на сжатой, ещё более далёкие, ещё сжатее. Total context CONVERGES, то есть он не растёт с числом кадров, а сходится к фиксированному пределу. Для нас идеально: тайл (3, 5) видит соседей (2, 5), (3, 4), (3, 6), (4, 5) на полной плотности, диагональных (2, 4), (4, 6) на 2×-сжатии, дальних (1, 1), на 4×. Total context = const, не зависит от размера фото. Можно работать на сетках 16×16 и больше без квадратичного взрыва.

Что выкидываем явно. Type A (full 3D attention), у Wan 2.1 это 14 миллиардов параметров и квадратичная стоимость по числу тайлов; для сетки 10×10 просто не запустится. Type H (discrete), Cosmos на FSQ-токенах с vocab=64K, для editing нужен continuous pixel-level выход. Большие модели вроде LTX-2 22B и HunyuanVideo 13B, слишком тяжёлые для нашего бюджета.

Какие модели уже на сцене, и кто что забрал В видео-диффузии 2024-2026 годов опубликовано около тридцати моделей с разными типами памяти. Не буду гнать через все, главное:

  • SANA-Video (arxiv 2509.24695), primary кандидат на BCLA. Linear attention, NVFP4 quantization из коробки. Это видео-расширение базовой SANA, и именно оттуда мы забираем механизм BCLA.

  • AnimateDiff (arxiv 2307.04725), primary кандидат на factored S+T при условии 32 тайлов или меньше. Главное, motion modules уже обучены, можно использовать инференсом.

  • SVD (arxiv 2311.15127), наследие, но reshape pattern хорошо документирован.

  • FramePack (arxiv 2504.12626), для больших сеток, реализация на DiT-моделях.

  • StreamingT2V (arxiv 2403.14773), CAM (cross-attn skip-connection от соседей) и APM (CLIP-anchor для всех кадров). Оба механизма устроены так, что их можно прикрутить к pretrained backbone’у без ретренинга основной модели, обучается только сам адаптер. Для нашего случая это значит, что часть механизмов можно пробовать без полного обучения с нуля.

Прецедент в обратную сторону, но всё-таки не наша идея. PatchVSR (CVPR 2025) уже взял видео-модель и приделал к ней dual-stream адаптер для патчей. Но они сохранили временное внимание внутри патча (по кадрам этого патча), не между патчами. То есть переносили видео в патчи, но память между патчами не пробовали. STA, Sliding Tile Attention (ICML 2025) применил sliding-tile внимание к видео-генерации на HunyuanVideo и получил ускорение 2.8-17× over FlashAttention2 на end-to-end inference. Это про скорость в видео, не про seam coherence в фото, но идея sliding-tile внимания пришла оттуда. FrescoDiffusion (Mar 2026), самый близкий кузен моей идеи, делает tiled denoising для 4K I2V с prior-regularized fusion, но генерирует видео а не редактирует фото.

Системного эксперимента «temporal attention из видео-моделей как cross-tile attention для статичной картинки на разных backbones», я не нашла. Если кто-то знает, дайте ссылку, порадуюсь.

Карта переноса видео → горизонталь Если коротко, каждому из ключевых видео-механизмов есть прямой пространственный аналог:

  • BCLA (SANA-Video) → S/Z аккумуляция между соседями, O(D²) const, тип B

  • FramePack compression → близкие тайлы full, диагональ 2×, далёкие 4×, тип F

  • SVD factored reshape(B·N_tiles, C, H, W) → (B·H·W, N_tiles, C), тип D

  • AnimateDiff motion modules → те же modules как cross-tile attention, тип D

  • StreamingT2V CAM → cross-attn от уже обработанных соседей, тип E

  • Ca2-VDM cache reuse → compute neighbor KV at t=0, reuse 28 denoising steps, тип G

Что должно быть в датасете под идею первую

Про датасет почти никто не пишет. А это половина задачи. Если мы хотим обучать модель помнить соседние тайлы, это значит датасет должен подавать ей не одиночные тайлы, а последовательности соседей. Несколько разрешений и несколько overlap-режимов. Иначе модель ничему не научится, у неё в train data просто нет «вот тайл и его сосед слева».

В моём рабочем сетапе:

На радость у меня завалялся небольшой датасет на 53 000 картинок ювелирных украшений. Собственно про объём датасета. На одну ювелирную фотку при tile=1024 и стандартном overlap’е выходит порядка 30-50 пересекающихся тайлов. Strip-последовательность, это одна прямая (горизонтальная или вертикальная) сквозь эти тайлы; их ~10-15 на фотку на одной scale. С тремя scale’ами (512, 768, 1024) и двумя хранимыми направлениями (LtR + TtB, остальные генерируются на лету через np.flip()) на одну картинку выходит ≈70 strip-последовательностей. На 53 000 картинок, порядка 3-4 миллионов сэмплов.

Планируется четыре направления обхода, слева-направо, справа-налево, сверху-вниз, снизу-вверх. На диске хранятся только LtR + TtB, остальные генерируются на лету через np.flip().

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

Идея механики BCLA-аккумуляции в одном предложении: два внешних аккумулятора S (D×D) и Z (D), переживают между тайлами; каждый новый тайл cross-attend’ит к этим двум тензорам и в конце дописывает в них свой KᵀV и K.

Идея SVD-style reshape так же в одном предложении: после spatial-блока тензор (B·N_tiles, C, H, W) перевзят как (B·H·W, N_tiles, C), прогоняется через cross-tile attention (для каждой пиксельной позиции attend через все тайлы), потом reshape обратно.

Главное в обоих случаях, что cross-tile attention видит для каждой пиксельной позиции (h, w) все её копии в N_tiles тайлах. То есть «как этот же угол выглядит в соседнем тайле». Это и есть тот самый перенос с видео, там было «как этот пиксель выглядит во всех кадрах», стало «во всех тайлах».

Что я уже попробовала по этой стороне

Только на SANA. Большое нативное разрешение радует меня как ни что другое. SANA тренировали на 512 → 1024 → 2K → 4K. То есть тайл размером 4096пикселей для нее как родной.

Плюс ещё одно архитектурное совпадение, внутри SANA уже стоит linear attention. Тип B из таблицы выше. Примитив для cross-tile памяти у неё встроен прямо в backbone, отдельно прикручивать не надо.

Что сделала. Запустила небольшое обучение на тестовом датасете strip-последовательностей с tile=1024. Цель простая: проверить две вещи: сходится ли loss и переносится ли вообще механизм с временной оси видео на пространственную плоскость фото.

Что вышло. Loss сходится. Перенос temporal → spatial на SANA реально работает, модель учится согласовывать соседние тайлы так же, как раньше училась согласовывать соседние кадры в видео. Цифры пока не публикую (это всё-таки тестовый прогон), но направление подтверждается.

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

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

Если у тебя есть фото 6000×4000, и ты его режешь на тайлы 512×512, у тебя на руках вся картинка целиком. Не использовать её, это, ну, странно. Можно сделать downscaled-версию в латентном пространстве. И эту downscaled-версию подать модели дополнительно к каждому тайлу. Channel concat в первый conv-слой, самый прямой способ.

Плюс позиция тайла. Координаты. Два дополнительных канала, (x, y) ∈ [-1, 1]. Тайл (3, 5) знает, что он именно (3, 5) из сетки, а не «какой-то 512×512 пикселей в воздухе».

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

PaDIS (NeurIPS 2024) сделал простую штуку и получил совсем не простой результат. Идея такая: к входным RGB-каналам модели добавляются ещё два, координатные. В каждом пикселе записано его положение в большой картинке, нормализованное от -1 до 1. Модель в момент обработки конкретного патча видит не только сами пиксели, но и «где я нахожусь в полной фотке: левый верхний угол, центр, низ».

Дальше та же модель, датасет, гиперпараметры. В одной версии координатные каналы есть, в другой нет. Без координат PSNR падает с 33.57 до 23.25 дБ. Минус 10.3 децибел. Цитата авторов: «все восстановленные результаты были очень низкого качества». То есть это не разница между «хорошо» и «нормально», а между «работает» и «вообще ничего не работает».

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

Стоит это дёшево. Два числа на пиксель добавить к трём RGB-каналам. Копейки в общей стоимости. При этом в современных тайловых пайплайнах координат почти никто не подаёт. Я не очень понимаю почему. Возможно потому, что у pretrained-моделей вход фиксированной размерности, и любое расширение требует ретренинга.

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

Если разложить «что должна знать модель про тайл», выходит три ортогональных оси.

Уровень

Что значит

Где это уже умеют

Геометрический

«Я тайл (3, 5) из сетки 8×8»

PaDIS, два канала (x, y)

Визуальный

«Вся картинка целиком выглядит так»

DemoFusion, FreeScale, DC-VSR, ResMaster

Семантический

«Я обрабатываю кожу, рядом, волосы, не выдумай ухо»

AccDiffusion v2, per-tile prompt через VLM

Tiled VAE из коробки даёт только нулевой уровень: пиксели и общий prompt. Все три оси, на стороне «что добавить».

Геометрический уровень, выше уже разобран, PaDIS-каналы.

Визуальный уровень. Тут два рабочих варианта и один тупиковый. Рабочий №1, кинуть в первый conv-слой downscaled VAE-латент полной картинки. Сохраняет пространственную структуру, цвет, освещение. Рабочий №2, добавить компактный 64-мерный вектор глобальных свойств (mean color, exposure, white balance), модулировать им AdaLN-Zero на каждом блоке. Похожие приёмы global-context conditioning описаны в работах вроде Simple ISP with Global Context Guidance (ICIP 2024). Дешевле латента, но без пространственной информации.

Тупиковый, CLIP image embedding (IP-Adapter). Для style transfer, окей, для ретуши, теряет пиксельную точность. 768-мерный вектор без spatial axes не даёт сигнал «у этого тайла верхний край на тёмно-синем небе, нижний, на голубоватом». Это я отдельно проверила, ниже расскажу.

Кто эту ось уже умеет, кроме PaDIS: FreeScale (Alibaba, ICCV 2025) фьюзит low-frequency глобального self-attention с high-frequency локального, UltraGen формализует «локальные окна + LR-глобал», DC-VSR делает Spatial Attention Propagation, subsample всей картинки пропихивает в локальные тайлы через attention, ResMaster выравнивает low-frequency патчей с LR-референсом на каждом denoising step. Все они про визуальный уровень. Третий, нетронутый.

Семантический уровень. Тут либо текстовый prompt на тайл через VLM, либо segmentation mask conditioning. AccDiffusion v2 генерирует отдельный prompt на каждый тайл через VLM (Florence-2, Qwen2-VL и подобные), что-то вроде upper-left corner of glass with droplets. В моём случае это значит: тайл с плечом и волосами получает явный текстовый сигнал skin and hair, no fur. И галлюцинация «шерсть» становится физически невозможной, она противоречит prompt’у. Цена, один VLM-pass на полную картинку плюс короткий prompt-запрос на тайл (Florence-2 справляется за ~50 ms на тайл).

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

В одной фразе: на вход тайла идёт concat из его собственного латента + двух coord-каналов + downscaled-латента полной картинки + опциональной seg-маски. Первый conv-слой делает zero-init проекцию обратно в нужную размерность каналов. Дополнительно, 64-мерный вектор глобальных color/exposure/WB-статистик через AdaLN-Zero модуляцию на каждом блоке. И per-tile text prompt из одного VLM-pass’а на полную картинку.

Один важный нюанс. Zero-init у first_conv критичен. Иначе на t=0 модель видит свой обычный input + случайные веса, и pretrained функционал ломается с первого forward pass’а. Zero-init = на t=0 эффективная архитектура та же, что у backbone’а; обучение постепенно увеличивает влияние новых каналов. Этот трюк описан в ControlNet, AnimateDiff motion adapter, миллионе других работ, стандарт.

Что я уже попробовала по этой стороне

IP-Adapter global preview, слабый сигнал на SDXL. Гипотеза была: подадим в IP-Adapter downscaled-версию полной картинки, тайл получит «общую визуальную подсказку». Counterfactual probe: real preview vs random-noise preview. Diff_mean между двумя случаями, 0.0066 на пиксель. При threshold 0.02 (ниже которого мы считаем сигнал «декоративным»). То есть IP-Adapter технически работает (image_encoder вызывается, 120 cross-attention calls на тайл), но влияние на финальный output пренебрежимое. Гипотеза почему, IP-Adapter обучали на bigG-ViT image embedding, у нас стандартная SDXL пара CLIP-L + CLIP-G. Encoder mismatch съедает сигнал. Для production нужен либо bigG, либо native SDXL conditioning.

Идеи 1 и 2, это про то, как сделать тайлинг умнее. Третья идея в другую сторону, а что если тайлинг сократить в количестве? Не делать его на каждом denoising-шаге, а только там, где он реально нужен.

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

Эта идея пока чисто архитектурная. Не тестировала. Но логика следующая.

Что такое Detail Demon

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

В практике StableDiffusion это значит: при том же числе шагов получаешь картинку с более чёткой текстурой, более тонкими переходами, без overshoot’а CFG. Для генерации: чуть больше резкости и много деталей. Для апскейла: намного больше детализации без видимого «AI-сглаживания».

Как работает обычный диффузионный апскейл

Стандартный диффузионный upscale (SDXL upscale, RealESRGAN+SD pipeline, X-to-1024, что угодно) сегодня делается так. Берёшь маленькую картинку, например 512×512. Поднимаешь её bicubic’ом до 1024×1024. Дальше прогоняешь это через диффузию с большим количеством шагов и существенным conditioning’ом на исходную картинку, чтобы она «дорисовала» детали.

Если картинка уже большая, например 2048 на сторону, этого делать в одном запуске нельзя. Не лезет в VRAM. Поэтому снова режем на тайлы, апскейлим каждый отдельно, склеиваем. Со всеми соответствующими швами, дублированиями, цветовыми сдвигами. То есть проблема та же самая, что в начале статьи, только теперь поверх ещё и upscale-логика.

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

Гипотеза: первая половина denoising-шагов работает с низкочастотной структурой. Грубое распределение цвета, общая композиция, крупные элементы. Это можно делать без тайлов, на downscaled версии, целиком в одном forward pass’е. Маленькая картинка лезет в VRAM.

Вторая половина шагов работает с высокочастотной детализацией, текстура, кромки, тонкие переходы. Здесь Detail Demon как раз и помогает: он делает HF-добавление через sampler-схему, не через рекурсивный re-denoise. И теоретически, это можно сделать на уже апскейленной картинке без re-tile, потому что Detail Demon не требует full denoising loop. Он работает локально по sigma-schedule, добавляет HF в малых sigma-зонах, не пересчитывая всю траекторию.

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

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

Detail Demon на больших фото, вопрос VRAM. Sample-шаги на полном разрешении 4096×4096 в attention map не лезут даже в 80 ГБ. Поэтому, скорее всего, чистый «без тайлов» получится только до какого-то предела разрешения, наверное, 2048 на сторону. Дальше всё равно нужна форма тайлинга в HF-фазе. А проблему стыковки тайлов тоже решит контекст.

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


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

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

  • Полная aбляция ещё не сделана. Я подтвердила сходимость и базовую переносимость механизма на тестовом прогоне SANA, но это не полное обучение и не полная aбляция против baseline’ов. До цифр seam_PSNR / deltaE_ratio / HF-SSIM мы дойдём только в будущем.

  • Не знаю, какая из трёх архитектур в итоге даст лучший seam_PSNR. SANA-BCLA должен быть лучшим по памяти (O(D²) const), Klein-cache, по качеству (DC-AE 32-канальный латент сохраняет цвет лучше SD 4-канального), SVD-factored, самый прямой архитектурный перенос. Какой выиграет на real ablation, не знаю и врать не буду.

  • Не знаю, как масштабируется на сетки 16×16 и больше. Все probe’ы гонялись на 3×3-7×7 тайлов. Для 100-тайловой сетки нужен FramePack или sliding window.

  • Семантический уровень (Florence-2 per-tile prompts), не тестировала. Отдельная вариация под этой темой, которую тоже хочется попробовать, описание делать один раз на всю картинку (один VLM-pass), а на каждом тайле просто понижать вес токенов, которых на этом тайле физически нет. То есть в тайле «небо» в cross-attention приглушаются токены про лицо, волосы, металл, а на тайле с украшением, наоборот, приглушаются токены про небо. Получается единый prompt + per-tile attention masking, без 200 отдельных VLM-генераций. Формально похожий приём делает AccDiffusion v2 через token attention masking по региональным маскам; в коммьюнити похожее знают по Regional Prompter / Latent Couple для sd1.5 в связке с ControlNet-Tile.

  • Detail Demon + апскейл, чисто гипотеза. Архитектурный sketch без единого прогона. Возможно сломается на VRAM, возможно даст другой набор артефактов.

ссылка на оригинал статьи https://habr.com/ru/articles/1028252/