Работа с HTMLImageElement, HTMLCanvasElement, HTMLVideoElement

TensorFlow.js предоставляет мощный набор инструментов для обработки и анализа данных прямо в браузере. Одним из ключевых аспектов является возможность использовать стандартные веб-элементы — изображения, канвасы и видео — в качестве источников данных для нейронных сетей. Это позволяет интегрировать машинное обучение непосредственно в веб-приложения без необходимости сервера для предобработки данных.


Поддерживаемые источники данных

TensorFlow.js может принимать следующие типы элементов HTML в качестве входных данных:

  • HTMLImageElement<img> элементы, представляющие статические изображения.
  • HTMLCanvasElement<canvas> элементы, содержащие динамическую графику или результаты рисования.
  • HTMLVideoElement<video> элементы, которые позволяют обрабатывать поток видео в реальном времени.

Все эти элементы могут быть преобразованы в тензоры (tf.Tensor) с помощью функций tf.browser.fromPixels() и далее использованы для построения, обучения и инференса моделей.


Преобразование HTML-элементов в тензоры

Ключевая функция для работы с визуальными HTML-элементами:

const tensor = tf.browser.fromPixels(element);
  • element может быть <img>, <canvas> или <video>.
  • Возвращаемое значение — тензор формы [height, width, channels]. Для цветного изображения channels = 3 (RGB).
  • Тип данных по умолчанию — int32. Для большинства моделей требуется преобразование в float32 и нормализация значений.

Пример для изображения:

const img = document.getElementById('input-image');
let tensor = tf.browser.fromPixels(img);
tensor = tensor.toFloat().div(tf.scalar(255)); // Нормализация значений от 0 до 1
tensor = tensor.expandDims(0); // Добавление батча для модели

Пример для видео:

const video = document.getElementById('input-video');
function processFrame() {
    const frameTensor = tf.browser.fromPixels(video)
        .toFloat()
        .div(tf.scalar(255))
        .expandDims(0);
    // Инференс или обработка frameTensor
    requestAnimationFrame(processFrame);
}
requestAnimationFrame(processFrame);

Использование Canvas для предобработки

HTMLCanvasElement особенно полезен для манипуляций с изображениями перед передачей в модель. С его помощью можно:

  • изменять размер изображения (drawImage с указанием новых размеров);
  • преобразовывать цветовую гамму (через фильтры Canvas API);
  • объединять несколько изображений в один тензор.

Пример ресайза изображения через Canvas:

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 224;
canvas.height = 224;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
const resizedTensor = tf.browser.fromPixels(canvas)
    .toFloat()
    .div(tf.scalar(255))
    .expandDims(0);

Нормализация и типы данных

Модели TensorFlow.js часто ожидают входные данные в формате float32 с диапазоном [0, 1] или [-1, 1]. Для этого используется преобразование:

const normalized = tensor.toFloat().div(tf.scalar(255)); // 0..1

Для некоторых предобученных моделей, таких как MobileNet, используется смещение и масштабирование:

const mobilenetInput = tensor.toFloat()
    .div(tf.scalar(127.5))
    .sub(tf.scalar(1.0)); // Диапазон [-1, 1]

Работа с видео в реальном времени

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

  1. Создается тензор из текущего кадра с помощью tf.browser.fromPixels(video).
  2. Тензор нормализуется и передается в модель.
  3. После обработки тензор освобождается с помощью tensor.dispose() для предотвращения утечек памяти.
  4. Повторение происходит с использованием requestAnimationFrame для синхронизации с рендерингом браузера.

Пример цикла инференса для видео:

async function runInference(video, model) {
    const frame = tf.browser.fromPixels(video)
        .toFloat()
        .div(tf.scalar(255))
        .expandDims(0);
    
    const prediction = await model.predict(frame);
    frame.dispose();
    prediction.dispose();
    requestAnimationFrame(() => runInference(video, model));
}

Освобождение памяти

При работе с HTML-элементами необходимо помнить о ручном управлении памятью. TensorFlow.js не отслеживает автоматически тензоры, созданные из HTML-элементов. Для предотвращения утечек памяти:

  • Использовать tensor.dispose() после завершения обработки кадра.
  • Оборачивать вычисления в tf.tidy(), чтобы автоматически освобождать промежуточные тензоры.

Пример с tf.tidy:

tf.tidy(() => {
    const tensor = tf.browser.fromPixels(img).toFloat().div(tf.scalar(255));
    const prediction = model.predict(tensor.expandDims(0));
    prediction.print();
});

Поддержка асинхронных операций

Некоторые модели требуют асинхронной загрузки данных (await model.predictAsync(tensor)), особенно при работе с большими изображениями или потоковым видео. Использование async/await обеспечивает корректную обработку кадров и предотвращает блокировку интерфейса.


Особенности использования разных элементов

Элемент Особенности обработки
HTMLImageElement Статическое изображение, можно загружать с сервера или локально.
HTMLCanvasElement Динамическое изображение, поддерживает трансформации, рисование и ресайз.
HTMLVideoElement Потоковое видео, требует циклической обработки кадров и управления памятью.

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

  • Ресайз перед конверсией: уменьшает нагрузку на GPU/CPU.
  • Использование WebGL backend: tf.setBackend('webgl') ускоряет вычисления на видеокарте.
  • Минимизация промежуточных тензоров: использовать tf.tidy() и избегать лишних копий.
  • Обработка кадров через requestAnimationFrame: синхронизирует с рендерингом и снижает нагрузку на основной поток.

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