- Задача февраля 2025 года: дорисовать очки с прозрачной линзой, не тронув глаза человека
- Flux Fill + LoRA + ControlNet canny: оправа получалась, глаза плыли по цвету и взгляду
- Из этого выросла идея lock-слоя: сохранение как отдельный слой, а не строка в промпте
Задача
Виртуальных примерок одежды, обуви, макияжа и причёсок на генеративных моделях тысячи. Очков среди них почти нет, а AR-примерки оправ на тот момент выглядели как наклейка поверх лица. Причина в самой задаче: очки сидят на самой узнаваемой части лица. Нужно дорисовать оправу с прозрачной линзой, сквозь которую видны те же глаза, того же цвета, с тем же направлением взгляда. Малейшее изменение глаз делает человека непохожим на себя, и примерка теряет смысл.
Обычный инпейнтинг с этим не справляется: маска покрывает область глаз, и модель заново генерирует всё, что под маской, включая сами глаза.
Метод
Пайплайн февраля 2025 года в ComfyUI на трёх компонентах:
- Flux Fill как база латентного инпейнтинга. Хорошо дорисовывает оправу в контексте лица и освещения.
- LoRA на очках, обученная на конкретном типе оправ. Подключается к базовой модели и отвечает за форму, материал и посадку.
- ControlNet с предобработкой canny. Контуры исходного лица подаются как условие, чтобы структура глаз и черты не перестраивались под маской.
Отдельно маскировались брови: их исключали из основной маски, чтобы они не перерисовывались.
flowchart LR
P[Исходное фото] --> C[ControlNet canny:<br/>контуры лица]
P --> M[Маска глаз,<br/>брови исключены]
C --> F[Flux Fill<br/>+ LoRA очков]
M --> F
F --> R[Оправа с<br/>прозрачной линзой]
Что получилось: оправа с прозрачной линзой действительно генерировалась, посадка на лице выглядела естественно, LoRA стабильно держала тип оправы, контуры лица ControlNet сохранял. На удачных прогонах результат трудно отличить от фотографии.


Где ломается
- Цвет и направление взгляда. Canny сохраняет контур глаза, но не его содержимое. Радужка меняла оттенок, взгляд уходил чуть в сторону. IP-Adapter в тестах влиял на мелкие детали, но заметно не помогал.
- Маска бровей сдвигала очки. Генерация подстраивала оправу под маску без бровей и сажала очки ниже, ближе к глазам. Это смещало и ControlNet, ломая исходную структуру глаз.
- Нет универсальных параметров. Входные фото не стандартизированы по размеру и ракурсу; веса ControlNet и настройки сэмплера приходилось подбирать под каждое изображение. На непортретных кадрах и при выраженной мимике результат разваливался.
flowchart LR
M[Маска над<br/>областью глаз] --> O[Оправа и линза:<br/>получаются]
M --> C[Canny держит контур,<br/>не содержимое]
C --> X[Радужка и взгляд<br/>плывут]
classDef key stroke:#FF3600,stroke-width:2px
class X keyОстановились, когда стало ясно, что следующий шаг — не ещё сотня прогонов, а отдельный «адаптер глаз», который регенерирует их из исходника в латентном пространстве, плюс автоматическая маскировка и нормализация входа. Это уже исследовательская программа, а не воркфлоу, и в феврале 2025 года её было не на чем оправдать.
Итог
- Оправа и линза решаются связкой Flux Fill + LoRA + ControlNet; глаза этой связкой не решаются.
- Причина не в моделях, а в архитектуре: сохранение глаз и генерация очков жили в одной маске и одном промпте и конкурировали.
- Из этого выросло правило «сохранение как отдельный слой», позже оформленное в Lock Layer: то, что должно выжить, описывается отдельно и проигрывается дословно, а генеративная часть никогда не описывает идентичность.
- Воркфлоу остался бета-версией: полезен как отправная точка, не как продукт.
© Александр Никулин. Цитирование — с указанием автора и ссылкой · Версия для LLM