Обработка видеопотока

ConvNetJS — это чисто JavaScript-библиотека для построения и обучения нейронных сетей, специализирующаяся на сверточных сетях (CNN). Она полностью работает в браузере и позволяет обрабатывать данные в реальном времени, включая изображения и видеопотоки. Библиотека поддерживает как классификацию, так и регрессию, а также обучение через стохастический градиентный спуск (SGD).

Основной объект — convnetjs.Net, который представляет нейронную сеть. Сеть создается путем последовательного добавления слоев через LayerDefs, где каждый слой имеет тип, размеры, функции активации и другие параметры.

Пример базовой сети:

var layer_defs = [];
layer_defs.push({type:'input', out_sx:64, out_sy:64, out_depth:3});
layer_defs.push({type:'conv', sx:5, filters:8, stride:1, pad:2, activation:'relu'});
layer_defs.push({type:'pool', sx:2, stride:2});
layer_defs.push({type:'fc', num_neurons:10, activation:'softmax'});

var net = new convnetjs.Net();
net.makeLayers(layer_defs);

Здесь создается сеть, которая принимает изображение 64x64 с тремя каналами (RGB), применяет сверточный слой с ReLU, слой подвыборки (pooling), а затем полностью связанный слой для классификации.


Подключение видеопотока

Обработка видеопотока начинается с получения кадров с камеры через WebRTC API:

navigator.mediaDevices.getUserMedia({ video: true })
  .then(stream => {
    var video = document.createElement('video');
    video.srcObject = stream;
    video.play();
  })
  .catch(err => console.error(err));

Для работы с ConvNetJS необходимо преобразовать кадры видео в матрицы чисел. Обычно используют Canvas API:

var canvas = document.createElement('canvas');
canvas.width = 64;
canvas.height = 64;
var ctx = canvas.getContext('2d');

function getFrame(video) {
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
    var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    var data = [];
    for (var i = 0; i < imgData.data.length; i += 4) {
        data.push(imgData.data[i]/255);     // R
        data.push(imgData.data[i+1]/255);   // G
        data.push(imgData.data[i+2]/255);   // B
    }
    return new convnetjs.Vol(canvas.width, canvas.height, 3, 0.0).setFromArray(data);
}

Ключевой момент: ConvNetJS работает с объектами типа Vol, которые представляют трехмерные объемы данных (width × height × depth). Каждый кадр должен быть преобразован в Vol, чтобы его можно было подать на вход сети.


Обучение сети на видеопотоке

Обучение сверточной сети на видеопотоке часто подразумевает онлайн-обучение. ConvNetJS поддерживает стохастический градиентный спуск через Trainer:

var trainer = new convnetjs.SGDTrainer(net, {
    learning_rate: 0.01,
    momentum: 0.9,
    batch_size: 1,
    l2_decay: 0.001
});

Для каждого кадра можно вычислить прогноз и обновить веса:

function processFrame(frameVol, label) {
    var predicted = net.forward(frameVol);
    trainer.train(frameVol, label);
    return predicted;
}

Если требуется классификация нескольких объектов на кадре, применяется оконный подход (sliding window), когда изображение делится на блоки, каждый из которых подается на сеть.


Оптимизация обработки

  1. Изменение размера кадра — уменьшение размеров перед подачей на сеть ускоряет обработку и снижает нагрузку на CPU.
  2. Буферизация кадров — хранение нескольких последних кадров может позволить использовать временные признаки.
  3. Параллельная обработка — кадры можно обрабатывать с использованием requestAnimationFrame, чтобы не блокировать интерфейс браузера.

Пример интеграции с циклом рендеринга:

function update() {
    var frameVol = getFrame(video);
    var output = net.forward(frameVol);
    requestAnimationFrame(update);
}
update();

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

  • Data Augmentation: ConvNetJS поддерживает вращение, отражение и масштабирование изображений, что улучшает обучение при малых данных.
  • Регрессия координат: для отслеживания объектов можно использовать полносвязные выходы, предсказывающие координаты центра объекта.
  • Хранение и загрузка сети: сеть можно сериализовать через JSON.stringify(net.toJSON()) и восстанавливать через net.fromJSON(json).
  • Кастомные функции потерь: поддерживаются стандартные потери (softmax, mse), но можно реализовать собственные.

Практические примеры

  1. Распознавание жестов руки: каждый кадр видеопотока преобразуется в Vol, сеть предсказывает класс жеста.
  2. Отслеживание лица: окно по лицу передается в сеть, которая регрессирует координаты.
  3. Интерактивные приложения: игра или визуальный фильтр, который реагирует на движения пользователя в реальном времени.

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