Применение масок к видеопотоку

Библиотека ml5.js предоставляет удобный интерфейс для работы с моделями машинного обучения в браузере, включая обработку изображений и видео. Применение масок к видеопотоку позволяет создавать эффекты дополненной реальности, сегментацию объектов и художественные фильтры. Основой таких операций является использование моделей для сегментации и отслеживания объектов, а также взаимодействие с HTML <video> и <canvas>.


Инициализация видеопотока

Для начала необходимо подключить видеопоток с веб-камеры. Используется стандартный объект MediaDevices:

const video = document.createElement('video');

navigator.mediaDevices.getUserMedia({ video: true })
  .then(stream => {
    video.srcObject = stream;
    video.play();
  })
  .catch(err => console.error('Ошибка доступа к камере:', err));

Ключевой момент — убедиться, что видеопоток полностью загружен перед применением модели. Это проверяется через событие loadedmetadata или при использовании video.readyState.


Использование модели BodyPix для сегментации

Для наложения маски на человека в кадре удобнее всего использовать модель BodyPix. Она позволяет получить маску сегментации, определяющую пиксели, относящиеся к телу человека, и фон.

Создание и загрузка модели:

let bodypixModel;

ml5.bodyPix(video, { architecture: 'MobileNetV1', outputStride: 16, multiplier: 0.75 }, modelLoaded);

function modelLoaded() {
  console.log('BodyPix модель загружена');
}

Параметры модели:

  • architecture — выбор структуры нейронной сети, влияет на точность и скорость.
  • outputStride — шаг, с которым сеть обрабатывает изображение, меньший шаг дает более точную маску.
  • multiplier — уменьшение размера модели для ускорения обработки на слабых устройствах.

Генерация маски и её отрисовка

После загрузки модели можно получать маску сегментации и отображать её на <canvas>:

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

function drawMask() {
  bodypixModel.segment(video, { flipHorizontal: true }, (err, result) => {
    if (err) {
      console.error(err);
      return;
    }

    const mask = ml5.bodyPix.toMask(result);
    ctx.putImageData(mask, 0, 0);
    requestAnimationFrame(drawMask);
  });
}

video.addEventListener('loadeddata', () => {
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
  drawMask();
});

Особенности работы с маской:

  • Функция ml5.bodyPix.toMask(result) возвращает объект ImageData с прозрачными пикселями для фона.
  • Параметр flipHorizontal удобен для зеркального отображения, привычного для фронтальных камер.
  • Использование requestAnimationFrame обеспечивает плавное обновление маски на каждом кадре.

Наложение пользовательских эффектов

На основе маски можно создавать разнообразные эффекты:

  1. Размытие фона:
ctx.drawImage(video, 0, 0);
ctx.globalCompositeOperation = 'destination-in';
ctx.putImageData(mask, 0, 0);
ctx.globalCompositeOperation = 'source-over';
ctx.filter = 'blur(10px)';
ctx.drawImage(video, 0, 0);
ctx.filter = 'none';
  1. Замена фона:
const background = new Image();
background.src = 'background.jpg';
background.onl oad = () => {
  ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
  ctx.globalCompositeOperation = 'destination-in';
  ctx.putImageData(mask, 0, 0);
  ctx.globalCompositeOperation = 'source-over';
  ctx.drawImage(video, 0, 0);
};
  1. Цветовые фильтры на теле:
const maskedData = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (let i = 0; i < maskedData.data.length; i += 4) {
  if (maskedData.data[i + 3] > 0) { // проверка прозрачности
    maskedData.data[i] = 255 - maskedData.data[i]; // инверсия красного канала
  }
}
ctx.putImageData(maskedData, 0, 0);

Оптимизация производительности

При работе с видео в реальном времени важно учитывать нагрузку на процессор и GPU:

  • Снижение разрешения видео: уменьшение videoWidth и videoHeight ускоряет сегментацию.
  • Меньший outputStride и multiplier: уменьшение этих параметров ускоряет обработку, но снижает точность маски.
  • Использование requestAnimationFrame вместо setInterval для синхронизации с частотой кадров экрана.
  • Кэширование маски при слабом изменении кадра: повторное использование маски для нескольких кадров снижает нагрузку.

Совмещение с другими библиотеками

Маски от ml5.js можно интегрировать с графическими библиотеками типа p5.js или Three.js:

  • p5.js: удобен для быстрого рисования на canvas и обработки интерактивных эффектов.
  • Three.js: позволяет наложить маску на 3D-объекты, создавая эффекты смешанной реальности.

Пример интеграции с p5.js:

function setup() {
  createCanvas(640, 480);
  video.hide();
  bodypixModel.segment(video, drawSegment);
}

function drawSegment(err, result) {
  const mask = ml5.bodyPix.toMask(result);
  image(video, 0, 0);
  tint(255, 127); // полупрозрачная маска
  image(mask, 0, 0);
  requestAnimationFrame(() => bodypixModel.segment(video, drawSegment));
}

Такой подход позволяет динамически комбинировать видеопоток с интерактивными визуальными эффектами.


Расширенные возможности

  • Сегментация нескольких объектов: BodyPix поддерживает выделение разных частей тела, что позволяет накладывать эффекты на отдельные сегменты (например, лицо, руки, ноги).
  • Использование масок для обучения ИИ: маски можно сохранять и использовать для подготовки датасетов для своих моделей.
  • Смешение с аудиореактивными эффектами: пиксели маски можно использовать для генерации визуализации, реагирующей на звук в реальном времени.

Эти инструменты открывают широкие возможности для создания интерактивных приложений с обработкой видео и реализацией эффектов дополненной реальности прямо в браузере.