Классификация с веб-камеры

Для работы с ConvNetJS в браузере необходимо подключить библиотеку через <script> тег либо через пакетный менеджер. В случае веб-страницы подключение выглядит так:

<script src="https://cs.stanford.edu/people/karpathy/convnetjs/build/convnet-min.js"></script>

ConvNetJS работает на чистом JavaScript и не требует серверной части для обучения простых нейронных сетей. Основные компоненты библиотеки:

  • convnetjs.Net — объект нейронной сети.
  • convnetjs.Layer — описание слоев сети.
  • convnetjs.SGDTrainer — тренер для стохастического градиентного спуска.
  • convnetjs.Vol — многомерный массив данных (тензор).

Создание и конфигурация сети

Для классификации изображений с веб-камеры используется сверточная нейронная сеть (CNN). Пример конфигурации:

var layer_defs = [];
// Входной слой: 32x32x3 (цветное изображение)
layer_defs.push({type:'input', out_sx:32, out_sy:32, out_depth:3});
// Сверточный слой: 8 фильтров 5x5, stride 1, ReLU
layer_defs.push({type:'conv', sx:5, filters:8, stride:1, pad:2, activation:'relu'});
// Субдискретизация (пулинг) 2x2
layer_defs.push({type:'pool', sx:2, stride:2});
// Еще один сверточный слой
layer_defs.push({type:'conv', sx:5, filters:16, stride:1, pad:2, activation:'relu'});
layer_defs.push({type:'pool', sx:2, stride:2});
// Полносвязный слой с 64 нейронами
layer_defs.push({type:'fc', num_neurons:64, activation:'relu'});
// Выходной слой: число классов
layer_defs.push({type:'softmax', num_classes:10});

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

Эта конфигурация подходит для классификации небольших изображений (например, 32×32 пикселя), захватываемых с веб-камеры. Использование ReLU повышает эффективность обучения, а softmax на выходе позволяет получать вероятности принадлежности к каждому классу.

Настройка тренера

Для обучения сети используется стохастический градиентный спуск с моментумом и регуляризацией:

var trainer = new convnetjs.SGDTrainer(net, {
  learning_rate: 0.01,
  momentum: 0.9,
  batch_size: 20,
  l2_decay: 0.001
});
  • learning_rate регулирует скорость изменения весов.
  • momentum помогает избежать застревания в локальных минимумах.
  • l2_decay предотвращает переобучение.

Захват изображения с веб-камеры

Для захвата видеопотока используется API getUserMedia:

var video = document.createElement('video');
navigator.mediaDevices.getUserMedia({video:true}).then(function(stream){
  video.srcObject = stream;
  video.play();
});

Чтобы получить изображение для классификации, используется временный canvas:

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

function captureFrame() {
  ctx.drawImage(video, 0, 0, 32, 32);
  var imgData = ctx.getImageData(0, 0, 32, 32);
  return imgData;
}

Преобразование изображения в тензор

ConvNetJS работает с объектом Vol. Необходимое преобразование:

function imageDataToVol(imgData) {
  var vol = new convnetjs.Vol(32, 32, 3, 0.0);
  var p = 0;
  for(var y=0;y<32;y++) {
    for(var x=0;x<32;x++) {
      for(var c=0;c<3;c++) {
        vol.set(x, y, c, imgData.data[p]/255.0);
        p++;
      }
      p++; // пропуск alpha
    }
  }
  return vol;
}

Деление на 255 нормализует данные к диапазону [0,1].

Классификация и обновление сети

Если сеть уже обучена, можно напрямую получать предсказания:

function classifyFrame() {
  var imgData = captureFrame();
  var x = imageDataToVol(imgData);
  var prob = net.forward(x);
  var maxIdx = prob.w.indexOf(Math.max(...prob.w));
  return maxIdx; // индекс класса с наибольшей вероятностью
}

Для онлайн-обучения на данных с веб-камеры:

function trainFrame(label) {
  var imgData = captureFrame();
  var x = imageDataToVol(imgData);
  trainer.train(x, label);
}

Каждое изображение с веб-камеры может быть использовано как обучающий пример. Это позволяет создавать интерактивные классификаторы в браузере без серверной части.

Оптимизация и ускорение работы

  • Снижение разрешения: уменьшение размера входного изображения до 32×32 или 64×64 значительно ускоряет обучение и классификацию.
  • Выбор батчей: использование batch_size > 1 позволяет стабилизировать градиенты.
  • Кэширование данных: можно хранить предобработанные изображения в массиве Vol для повторного использования.

Визуализация результатов

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

function drawPrediction() {
  var ctxOverlay = canvas.getContext('2d');
  ctxOverlay.clearRect(0, 0, canvas.width, canvas.height);
  var predictedClass = classifyFrame();
  ctxOverlay.font = '16px Arial';
  ctxOverlay.fillStyle = 'red';
  ctxOverlay.fillText('Класс: ' + predictedClass, 5, 20);
}

Обновление визуализации производится через requestAnimationFrame для плавного отображения.

Расширение сети и добавление новых классов

Для классификации нескольких категорий рекомендуется:

  • Добавлять дополнительные сверточные и полносвязные слои.
  • Использовать dropout для предотвращения переобучения.
  • Собрать разнообразный набор изображений с веб-камеры для обучения.

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