Удаление жёлтых ореолов при композитинге: Lab пространство и трёхуровневая стратегия | AiManual
AiManual Logo Ai / Manual.
16 Янв 2026 Гайд

Убиваем цветовые артефакты: Lab-пространство и трёхуровневая стратегия для чистого композитинга

Пошаговое руководство по устранению цветовых артефактов при наложении изображений. Переход из RGB в Lab, работа с масками BiRefNet и трёхуровневая стратегия бле

Почему ваш композит выглядит так, будто его делал дизайнер с дальтонизмом

Вы скачали крутую нейросеть для сегментации фона, нагенерировали десяток изображений, наложили одно на другое - и получили мерзкий жёлтый ореол по краям. Знакомо? Эта желтизна - не баг вашей модели, а закономерный результат работы в RGB-пространстве.

RGB - это пространство для мониторов, а не для человеческого восприятия. Когда вы смешиваете пиксели переднего плана и фона, математика RGB делает это грубо: усредняет цвета, игнорируя то, как мы видим светлоту и цветность раздельно. Результат - артефакты, которые выглядят как грязь по контуру.

💡
Жёлтый ореол - это не недостаток маски, а побочный эффект блендинга в RGB. Ваша маска может быть идеальной, но если вы смешиваете цвета в неправильном пространстве, результат всё равно будет отвратительным.

Lab: пространство, где цвет и светлота живут отдельно

Представьте, что у вас есть два сотрудника: один отвечает за яркость (L), другой - за цвет (a и b каналы). В Lab они не мешают друг другу. Это меняет всё.

Когда вы переходите из RGB в Lab, происходит магия:

  • Канал L хранит информацию о светимости - от чёрного к белому
  • Канал a - от зелёного к красному
  • Канал b - от синего к жёлтому

Секрет в том, что человеческий глаз гораздо чувствительнее к изменениям светлоты (L), чем к изменениям цвета (a,b). И когда вы делаете блендинг только в канале L, оставляя цветовые каналы нетронутыми, артефакты исчезают. Просто потому, что вы не трогаете то, что создаёт цветовые искажения.

Не путайте Lab с HSL/HSV! HSL - это просто преобразование RGB, где H, S, L вычисляются из тех же R,G,B. Lab основан на человеческом восприятии и соответствует тому, как на самом деле работает наш глаз. Разница принципиальная.

Трёхуровневая стратегия: от грубой маски до финального блендинга

Одна только смена цветового пространства не спасёт, если ваша маска похожа на швейцарский сыр. Нужен системный подход.

1 Грубая сегментация: BiRefNet против U²-Net

Начинаем с выбора оружия. U²-Net был королём года три назад, но сегодня BiRefNet делает более чистые маски с меньшим количеством дырок. Особенно на сложных волосах и полупрозрачных объектах.

Почему BiRefNet? У него двунаправленная архитектура, которая смотрит на изображение и сверху вниз, и снизу вверх. Это как иметь двух редакторов: один проверяет общую структуру, другой - детали.

# Пример загрузки BiRefNet через HuggingFace
from transformers import pipeline

segmenter = pipeline("image-segmentation", model="briaai/RMBG-1.4")
result = segmenter("input_image.jpg")
mask = result["mask"]  # Готовая маска 0-1

Не забудьте пороговать маску! BiRefNet выдаёт мягкие границы (0-1), но для следующего этапа нужны чёткие 0 или 1. Порог 0.5 обычно работает, но для полупрозрачных тканей можно снизить до 0.3.

2 Уточнение границ: маттинг против эрозии/дилатации

Вот где большинство обламывается. Берут грубую маску и сразу применяют Gaussian blur для размытия краёв. Результат? Тот самый жёлтый ореол, только теперь ещё и размытый.

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

Метод Плюсы Минусы Когда использовать
Эрозия+Дилатация Быстро, просто Создаёт ступенчатые края Только для грубых масок без деталей
Gaussian Blur Плавные переходы Усиливает цветовые артефакты Никогда для композитинга
Маттинг (KNN) Учитывает цвета изображения Медленнее, сложнее Волосы, мех, полупрозрачные объекты

Если маттинг для вашего пайплайна слишком тяжёлый, есть компромисс: делайте эрозию/дилатацию с маленьким ядром (3x3), затем применяйте guided filter. Он размывает маску, но ориентируется на градиенты исходного изображения.

3 Финальный блендинг: Lab + правильная формула

Теперь самое важное. У вас есть уточнённая маска (alpha channel), передний план (foreground) и фон (background).

Как НЕ надо делать:

# Плохо: блендинг в RGB
result_rgb = foreground * alpha + background * (1 - alpha)

Эта формула в RGB создаёт цветовые артефакты, потому что смешивает R, G, B независимо, без учёта восприятия.

Правильный способ:

import cv2
import numpy as np

# 1. Конвертируем всё в Lab
fg_lab = cv2.cvtColor(foreground, cv2.COLOR_RGB2LAB)
bg_lab = cv2.cvtColor(background, cv2.COLOR_RGB2LAB)

# 2. Разделяем каналы
fg_L, fg_a, fg_b = cv2.split(fg_lab)
bg_L, bg_a, bg_b = cv2.split(bg_lab)

# 3. Смешиваем ТОЛЬКО канал L (светлоту)
blended_L = fg_L * alpha + bg_L * (1 - alpha)

# 4. Для цветовых каналов используем более умную стратегию:
# Если alpha близок к 1, берём цвет переднего плана
# Если alpha близок к 0, берём цвет фона
# В промежуточной зоне - линейная интерполяция
blended_a = fg_a * alpha + bg_a * (1 - alpha)
blended_b = fg_b * alpha + bg_b * (1 - alpha)

# 5. Собираем обратно и конвертируем в RGB
blended_lab = cv2.merge([blended_L, blended_a, blended_b])
result = cv2.cvtColor(blended_lab, cv2.COLOR_LAB2RGB)
💡
Ключевой момент: мы смешиваем L канал всегда, но для a и b каналов можно использовать нелинейную интерполяцию. Например, пороговую: если alpha > 0.7, берём полностью цвет переднего плана. Это уменьшает цветовое загрязнение на границах.

Распространённые ошибки и как их избежать

Даже с правильной теорией можно наступить на грабли. Вот самые частые:

1. Гамма-коррекция забыта

Lab работает с линейной светлотой, а большинство изображений хранятся в sRGB с гамма-коррекцией. Если конвертировать sRGB→Lab напрямую, цвета исказятся.

Решение: Сначала преобразуйте sRGB в линейный RGB, потом в Lab. Или используйте cv2.COLOR_RGB2LAB - OpenCV делает это автоматически.

2. Плохая маска на сложных участках

BiRefNet хорошо справляется с волосами, но может провалиться на полупрозрачных объектах вроде вуали или дыма. Здесь поможет техника итеративного уточнения: сегментируете несколько раз с разными порогами, комбинируете результаты.

3. Цветовой сдвиг после конвертации

Иногда после RGB→Lab→RGB цвета слегка меняются. Это происходит из-за округления и ограниченной точности. Для критичных проектов используйте 16-битные изображения вместо 8-битных.

Деплой на HuggingFace Spaces: production-ready пайплайн

Теперь, когда у вас работает локально, давайте упакуем это в сервис. HuggingFace Spaces идеально подходит для демонстрации композитинга.

# app.py для HuggingFace Spaces
import gradio as gr
import cv2
import numpy as np
from PIL import Image

# Загрузка модели (кешируем для скорости)
from transformers import pipeline
segmenter = pipeline("image-segmentation", model="briaai/RMBG-1.4")

def composite_images(foreground, background):
    # Сегментация
    result = segmenter(foreground)
    mask = result["mask"]
    
    # Конвертация в Lab
    fg_lab = cv2.cvtColor(np.array(foreground), cv2.COLOR_RGB2LAB)
    bg_lab = cv2.cvtColor(np.array(background), cv2.COLOR_RGB2LAB)
    
    # Блендинг в Lab (как в коде выше)
    # ...
    
    return Image.fromarray(result_rgb)

# Интерфейс Gradio
iface = gr.Interface(
    fn=composite_images,
    inputs=[
        gr.Image(label="Передний план"),
        gr.Image(label="Фон")
    ],
    outputs=gr.Image(label="Результат"),
    title="Чистый композитинг в Lab-пространстве"
)

iface.launch()

На Spaces можно добавить слайдеры для регулировки порога маски, силы блендинга и других параметров. Пользователи смогут экспериментировать без написания кода.

Внимание на память! BiRefNet не маленькая модель. На Spaces с бесплатным CPU она может тормозить. Либо кэшируйте результаты для одинаковых изображений, либо предлагайте пользователям загружать предварительно вырезанные объекты с маской.

А что насчет реального времени?

Всё это работает для офлайн-обработки. Но что если нужно в реальном времени, например, для виртуальных примерочных?

Тогда Lab может быть слишком медленным. Альтернатива - YCbCr. Это не перцептивное пространство, но оно тоже разделяет яркость (Y) и цветность (Cb, Cr). Конвертация быстрее, и для многих случаев результат приемлемый.

Ещё один трюк - предварительно вычислять маски для каталога товаров и хранить их вместе с изображениями. Как в статье про стейджей стабильной генерации контента, где каждый этап оптимизирован для продакшена.

Неочевидный совет: когда НЕ использовать эту технику

Да, бывает и такое. Lab-блендинг не панацея:

  • Стилизованная графика: Если вы накладывайте мультяшного персонажа на фэнтези-фон, цветовые артефакты могут быть частью стиля
  • Ночные сцены: Lab плохо работает с очень тёмными изображениями, где шум доминирует над сигналом
  • HDR-изображения: Lab рассчитан на стандартный динамический диапазон. Для HDR нужны специальные пространства вроде ICtCp

И последнее: если вы делаете композитинг для печати, а не для экрана, вам нужен не Lab, а CMYK. Но это уже совсем другая история с другими граблями.

Главное - понимать, почему появляются артефакты, а не просто применять рецепты. Теперь вы знаете и «почему», и «как». Осталось попробовать и перестать ненавидеть жёлтые ореолы.