• Задача февраля 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/>прозрачной линзой]
Воркфлоу ComfyUI для примерки очков
Воркфлоу ComfyUI для примерки очков

Что получилось: оправа с прозрачной линзой действительно генерировалась, посадка на лице выглядела естественно, LoRA стабильно держала тип оправы, контуры лица ControlNet сохранял. На удачных прогонах результат трудно отличить от фотографии.

Нейро Примерка Очков - Изображение 1
Нейро Примерка Очков - Изображение 2

Где ломается

  • Цвет и направление взгляда. 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