Разработка AI для замены фона в видео
Замена фона в видео — задача сложнее, чем в статичных изображениях: нужна временная согласованность между кадрами (temporal coherence), иначе фон будет мерцать. Мы реализуем системы для видеоконференций (Zoom, Teams), спортивных трансляций и новостных студий без хромакея. Realtime-требования для конференций — 15–30 FPS при задержке <50 мс на CPU/GPU с низким энергопотреблением.
Почему temporal coherence критична для видео?
Каждый кадр обрабатывается независимо, но без учёта предыдущих кадров маска фона может резко меняться, создавая артефакты. Temporal coherence устраняет мерцание, используя рекуррентные нейронные сети. RVM (Robust Video Matting) — одна из лучших моделей, явно хранящая скрытое состояние между кадрами. Подробнее о RVM можно прочитать в официальной документации.
Как мы добиваемся temporal coherence?
Ключевое решение — RVM с рекуррентным состоянием. Модель хранит скрытые векторы между кадрами, что устраняет мерцание. Наш опыт показывает, что этот подход даёт плавную маску даже на сложных сценах с движением камеры. Например, в одном из проектов для стриминговой платформы мы внедрили RVM MobileNetV3 — замена фона работала на 30 FPS на ноутбуке без GPU.
import torch
import torchvision.transforms as T
from PIL import Image
import numpy as np
import cv2
class VideoBackgroundReplacer:
def __init__(self, model_path: str, device: str = 'cuda'):
self.device = device
# RVM с recurrent state — ключ к temporal coherence
self.model = torch.jit.load(model_path).to(device)
self.model.eval()
self.transform = T.ToTensor()
# Recurrent state сохраняется между кадрами
self.rec = [None] * 4
def reset_state(self):
"""Сбросить состояние при смене сцены/источника"""
self.rec = [None] * 4
@torch.no_grad()
def process_frame(self, frame_bgr: np.ndarray,
background_bgr: np.ndarray) -> np.ndarray:
"""
Обработка одного кадра видео.
Состояние (rec) сохраняется между вызовами для плавности.
"""
frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
bg_rgb = cv2.cvtColor(background_bgr, cv2.COLOR_BGR2RGB)
# Изменяем размер до кратного 64 для модели
h, w = frame_rgb.shape[:2]
src = self.transform(Image.fromarray(frame_rgb)).unsqueeze(0).to(self.device)
bgr_tensor = self.transform(
Image.fromarray(bg_rgb).resize((w, h))
).unsqueeze(0).to(self.device)
# Основной вывод с передачей recurrent state
fgr, pha, *self.rec = self.model(src, *self.rec, downsample_ratio=0.25)
# Compositing
composite = fgr * pha + bgr_tensor * (1 - pha)
result = (composite.squeeze().permute(1, 2, 0).cpu().numpy() * 255).astype(np.uint8)
return cv2.cvtColor(result, cv2.COLOR_RGB2BGR)
def replace_in_video(self, input_path: str,
background_path: str,
output_path: str) -> dict:
cap = cv2.VideoCapture(input_path)
fps = cap.get(cv2.CAP_PROP_FPS)
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# Загружаем фон (может быть изображение или видео)
if background_path.endswith(('.jpg', '.png')):
bg = cv2.imread(background_path)
bg = cv2.resize(bg, (w, h))
bg_is_video = False
else:
bg_cap = cv2.VideoCapture(background_path)
bg_is_video = True
out = cv2.VideoWriter(output_path,
cv2.VideoWriter_fourcc(*'mp4v'),
fps, (w, h))
self.reset_state()
frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
if bg_is_video:
ret_bg, bg = bg_cap.read()
if not ret_bg:
bg_cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
_, bg = bg_cap.read()
bg = cv2.resize(bg, (w, h))
result = self.process_frame(frame, bg)
out.write(result)
frame_count += 1
cap.release()
out.release()
return {'frames': frame_count, 'fps': fps, 'output': output_path}
Какие модели обеспечивают realtime на CPU?
Для CPU без GPU мы используем ONNX Runtime с оптимизациями. В проекте для видеоконференций мы добились 30 FPS на ноутбуке Intel i5, применив квантизацию INT8 и уменьшение разрешения до 256x144. ONNX Runtime позволяет запускать модели на различных устройствах с минимальными изменениями.
import onnxruntime as ort
class RealtimeBackgroundProcessor:
"""
ONNX Runtime для CPU-оптимизации на машинах без GPU.
Target: 30 FPS на ноутбуке, задержка <33 мс/кадр.
"""
def __init__(self, onnx_model_path: str):
# Настройки для максимальной производительности на CPU
opts = ort.SessionOptions()
opts.intra_op_num_threads = 4
opts.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL
opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
self.session = ort.InferenceSession(
onnx_model_path,
sess_options=opts,
providers=['TensorrtExecutionProvider',
'CUDAExecutionProvider',
'CPUExecutionProvider']
)
# Recurrent state как numpy массивы
self.rec_states = [
np.zeros((1, 1, 1, 1), dtype=np.float32) for _ in range(4)
]
def process_frame_fast(self, frame_rgb: np.ndarray,
target_size: tuple = (256, 144)) -> np.ndarray:
"""
Уменьшаем до 256x144 для CPU realtime.
Upscale маски обратно через билинейную интерполяцию.
"""
orig_h, orig_w = frame_rgb.shape[:2]
small = cv2.resize(frame_rgb, target_size)
small_f = small.astype(np.float32) / 255.0
src = small_f.transpose(2, 0, 1)[np.newaxis] # [1, 3, H, W]
outputs = self.session.run(
None,
{'src': src, 'r1i': self.rec_states[0], 'r2i': self.rec_states[1],
'r3i': self.rec_states[2], 'r4i': self.rec_states[3],
'downsample_ratio': np.array([0.25])}
)
fgr, pha = outputs[0], outputs[1]
self.rec_states = list(outputs[2:6])
# Апскейл маски обратно до исходного размера
alpha_small = pha[0, 0]
alpha_full = cv2.resize(alpha_small, (orig_w, orig_h),
interpolation=cv2.INTER_LINEAR)
return alpha_full
Виртуальный размытый фон (Bokeh effect)
def apply_background_blur(frame: np.ndarray,
alpha: np.ndarray,
blur_radius: int = 25) -> np.ndarray:
"""
Альтернатива замене — размытие фона (как в Google Meet/Teams).
Не требует загрузки изображения, работает быстрее.
"""
# Размываем весь кадр
blurred = cv2.GaussianBlur(frame, (blur_radius * 2 + 1, blur_radius * 2 + 1), 0)
# Compositing с мягкими краями
alpha_3ch = np.stack([alpha, alpha, alpha], axis=2)
result = (frame * alpha_3ch + blurred * (1 - alpha_3ch)).astype(np.uint8)
return result
Сравнение моделей: какая лучше?
RVM лучше MediaPipe в 2–3 раза по качеству маски, но требует GPU для realtime. Background Matting V2 даёт лучшее качество, но медленнее. Выбор зависит от вашего сценария: для стримов подойдёт RVM MobileNetV3, для офлайн-продакшена — ResNet50.
| Метод | FPS (CPU) | FPS (GPU) | Качество |
|---|---|---|---|
| RVM MobileNetV3 | 28–35 | 100–140 | Высокое |
| MediaPipe Selfie Segmentation | 60+ | — | Среднее |
| RVM ResNet50 | 8–12 | 45–60 | Лучшее |
| Background Matting V2 | 5–8 | 30–40 | Высокое |
Типичные ошибки при интеграции AI-замены фона
| Ошибка | Последствие | Решение |
|---|---|---|
| Игнорирование temporal coherence | Мерцание фона, артефакты | Использовать RVM или другие рекуррентные модели |
| Неоптимальное разрешение | Низкий FPS или плохое качество маски | Подбирать размер так, чтобы сохранить баланс; для CPU использовать 256x144 |
| Отсутствие квантизации | Замедление инференса на CPU | Применить INT8 квантизацию в ONNX |
| Неправильный выбор модели | Несоответствие требованиям по скорости/качеству | Провести бенчмаркинг на целевом железе |
Что входит в работу?
Мы предоставляем:
- Анализ вашего сценария и выбор модели
- Интеграцию в вашу инфраструктуру (API, WebRTC, мобильное приложение)
- Оптимизацию под целевое железо (CPU/GPU/Edge)
- Документацию и обучение команды
- Поддержку после внедрения
Свяжитесь с нами для аудита вашего проекта — мы оценим требования и предложим оптимальное решение.
Как выбрать модель для замены фона?
При выборе модели учитывайте: целевое оборудование (CPU/GPU), требуемое разрешение и FPS, допустимую задержку. Для мобильных устройств лучше подходит MediaPipe, для продакшена — RVM с ONNX. Мы поможем подобрать конфигурацию и оптимизировать под ваш сценарий.
Процесс работы
- Аналитика: изучаем требования к FPS, задержкам, качеству маски.
- Проектирование: выбираем модель, стек (ONNX, PyTorch, TensorRT).
- Реализация: пишем код интеграции, добавляем рекуррентное состояние.
- Тестирование: замеряем latency p99, FLOPS, проверяем на разных сценах.
- Деплой: разворачиваем на ваших серверах или в облаке.
Сроки и стоимость
Ориентировочные сроки:
- Интеграция RVM для видеофайлов: 1–2 недели.
- Realtime плагин для видеоконференций: 4–8 недель.
- Мобильное приложение: 8–14 недель.
Стоимость рассчитывается индивидуально после аудита проекта. У нас более 5 лет опыта в AI/ML, мы реализовали свыше 30 проектов по компьютерному зрению. Гарантируем качество маски и соблюдение сроков. Закажите разработку под ключ — получите готовое решение с гарантией.







