Привет, Хабр! Меня зовут Павел Кузнецов, и я ML-разработчик в лаборатории компьютерного зрения Центра ИИ Контура. Мы занимаемся созданием AI-фич для продуктов компании. Один из наших ключевых заказчиков — сервис видео-конференц-связи Контур.Толк. Для него мы разрабатываем такие фичи, как бьютификация, улучшение освещённости, детекция дипфейков и, конечно же, сегментация фона.
В статье я расскажу, как мы создавали виртуальный фон. Наш путь был полон вызовов: мы долго выбирали архитектуру, продумывали стратегию обучения и искали способ запустить модель в вебе. Каждая из этих задач достойна отдельной истории. Но эта статья — рассказ о данных, «новой нефти», и о том, как мы их добывали на разных этапах разработки.
С чего всё начиналось?
Сегментация фона — одна из ключевых фич любого сервиса ВКС. Во времена пандемии Covid-19 удалённый формат работы стал нормой по всему миру, и виртуальный фон превратился в незаменимый инструмент. Он помогает скрыть от собеседников личное пространство, будь то члены семьи дома или коллеги в коворкинге.
Изначально в Толке была внедрена готовая модель из библиотеки Mediapipe от Google. Однако клиенты часто жаловались на качество: модель плохо справлялась с причёсками и руками. Границы между человеком и фоном были нестабильными и заметно дрожали.

Тогда команда Толка обратилась в нашу лабораторию с задачей улучшить качество виртуального фона. Дополнительную мотивацию придало внутреннее исследование Контура, которое показало, что 65% пользователей считают встречи с включенной камерой более эффективными. Так родилась наша гипотеза: качественный виртуальный фон повышает уверенность пользователя в своём внешнем виде → он чаще включает камеру → больше встреч оцениваются субъективно как эффективные.
Этап 1. Открытые данные: ожидания и реальность
Задача виртуального фона — это бинарная сегментация: «человек» и «всё остальное». Как и многие, мы начали с поиска готовых открытых датасетов для обучения и оценки моделей. Но их недостатки быстро стали очевидны:
Низкое качество разметки. В одних датасетах границы объектов были грубыми и ломаными, в других — лица людей были размыты.
Малое разнообразие. Некоторые наборы данных содержали всего несколько десятков уникальных людей.

Более того, большинство изображений и видео не соответствовали нашему домену видеозвонков: люди находились далеко от камеры, освещение было студийным, а сложные позы и жесты практически отсутствовали. Всё это приводило к главному — модели, обученные на таких данных, плохо справлялись с сегментацией в пограничных областях. Стало ясно: нужно собирать и размечать собственный датасет.
Этап 2. Свой датасет: сила комьюнити
Самый быстрый способ получить релевантные данные — попросить о помощи коллег. Мы сформулировали требования, бросили клич в рабочем чате и уже через пару недель получили ценный набор видеозаписей, снятых в разных условиях и на разные камеры. Коллеги помогли охватить множество сложных сценариев: с головными уборами, гарнитурами, офисными креслами, сложным фоном и предметами в руках.


Важный момент: мы сразу решили размечать именно видео, а не отдельные изображения. Мы предполагали, что на одном из этапов экспериментов сможем использовать архитектуру, учитывающую временну́ю связь между кадрами. При этом мы понимали, что, имея большой объём кадров от одного человека, мы рисковали потерять в разнообразии людей в обучающей выборке.
За разметкой мы обратились в Асессорскую службу Контура и в итоге получили отличный бенчмарк. Но для обучения качественных данных всё ещё не хватало.
Этап 3. YouTube и псевдоразметка: масштабирование и новые грабли
Крупнейший источник видеоконтента — это YouTube. Именно туда мы отправились на поиски роликов, похожих на сценарий видеозвонка. Чтобы ускорить путь от идеи до результата, мы решили собрать и разметить новый сет данных силами нашей лаборатории. Мы продумали поисковые запросы и погрузились в просмотр видео. Собрав внушительный список ссылок, мы скачали короткие фрагменты (5–10 секунд) контента с лицензией Creative Commons Attribution.
Для создания псевдоразметки мы использовали комбинацию из энкодера DINOv2 и сегментационной головы Mask2Former. Такой сетап отлично справлялся с простыми сценариями, но довольно грубо размечал сложные случаи. Поэтому нам приходилось вручную отсматривать разметку, чтобы исключить ошибки в масках.

Получив солидный датасет, мы продолжили эксперименты и заметно улучшили метрики нашей модели. Но тут проявилась неприятная особенность: на некоторых кадрах фон начал «протекать» в маску человека — например, части диванов или стен.
Проанализировав проблему, мы пришли к гипотезе: мы зря включали в маску стулья и кресла. Эти объекты часто сливаются с фоном, и модель начинает путаться. Изначально мы ориентировались на NVIDIA Broadcast, где кресла остаются частью маски, но у нас было серьёзное ограничение: наша модель должна работать на обычных пользовательских ноутбуках, а не на мощных видеокартах, как у стримеров. Размер нашей модели должен быть на порядок меньше.
Этап 4. SAM 2 и удаление кресел: работа над ошибками
Проверку гипотезы мы снова решили провести своими силами. На этот раз, чтобы сделать разметку точнее, мы отказались от DINOv2. К тому моменту вышла модель Segment Anything 2 (SAM 2), способная сегментировать объекты на видео после разметки всего одного или нескольких кадров. С помощью SAM 2 мы довольно быстро исключили стулья и кресла из масок и подтвердили гипотезу — фон действительно перестал «протекать».

SAM 2 достаточно точно выделял мелкие детали: пальцы, волосы, гарнитуру, предметы в руках. Но и он иногда ошибался. Например, модель могла вырезать из маски рисунок на одежде или целый головной убор. К счастью, многие из этих косяков удалось исправить с выходом следующей версии, SAM 2.1.
Результаты
После первого релиза нашей модели в Толке мы собрали обратную связь. Пользователи отмечали нестабильную сегментацию рук в определённых положениях и моргание границ маски при плохом освещении. Эти ошибки удалось исправить с помощью дополнительных аугментаций, в том числе и кастомных.
На скриншотах ниже вы можете визуально сравнить нашу текущую сегментацию с моделью Mediapipe. В таблице приведено сравнение по ключевым метрикам. Для оценки качества маски мы использовали метрику Dice (она же F1), а для пограничной области — Boundary Dice. Временну́ю согласованность кадров измеряли кастомной метрикой Flickering: чем ниже её значение, тем меньше дрожит маска от кадра к кадру.


Модель/Метрика |
Dice |
Boundary Dice |
Flickering |
MediaPipe |
0.9627 |
0.6705 |
0.0098 |
Наша модель |
0.9801 |
0.8734 |
0.0059 |
В итоге мы достигли значительного прогресса:
Улучшилась сегментация рук, волос и головных уборов.
Фон перестал «протекать», и модель уверенно отделяет человека от окружения.
Модель стала стабильнее работать в условиях плохого освещения.
Всё это привело к росту использования виртуального фона и, как следствие, к увеличению числа пользователей, включающих камеру.

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