Работа с пикселями и imageData

TensorFlow.js предоставляет мощный инструментарий для работы с изображениями и пикселями непосредственно в браузере или в Node.js. Основой для обработки изображений служат тензоры, которые могут представлять пиксели как многомерные массивы чисел.

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

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

const imgElement = document.getElementById('myImage');
const tensor = tf.browser.fromPixels(imgElement);

Ключевые моменты:

  • tf.browser.fromPixels автоматически создает тензор размерности [height, width, 3] для RGB или [height, width, 4] для RGBA.
  • Тип тензора по умолчанию — int32.
  • Значения пикселей находятся в диапазоне [0, 255].

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

const normalizedTensor = tensor.toFloat().div(tf.scalar(255));

Это переводит значения пикселей в диапазон [0, 1], что улучшает сходимость моделей.

Работа с ImageData из Canvas

Canvas API предоставляет ImageData, содержащий массив пикселей в формате [R, G, B, A, R, G, B, A, ...]. Для преобразования в тензор:

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

const tensorFromImageData = tf.browser.fromPixels(imageData);

Особенности:

  • ImageData.data — это Uint8ClampedArray.
  • TensorFlow.js корректно обрабатывает этот формат, сохраняя структуру [height, width, channels].
  • Для нейросетей также рекомендуется нормализовать значения:
const floatTensor = tensorFromImageData.toFloat().div(tf.scalar(255));

Манипуляции с пикселями

Тензоры позволяют выполнять операции с пикселями напрямую, без обращения к Canvas API. Например, инверсия цветов:

const invertedTensor = tf.tidy(() => {
  return tf.sub(tf.scalar(1), normalizedTensor);
});

Здесь используется tf.sub для вычитания каждого значения пикселя из 1.

Другой пример — конвертация изображения в оттенки серого:

const grayscaleTensor = tf.tidy(() => {
  const [r, g, b] = tf.split(normalizedTensor, 3, 2);
  return r.mul(0.299).add(g.mul(0.587)).add(b.mul(0.114));
});
  • tf.split разделяет тензор по каналу.
  • Веса 0.299, 0.587 и 0.114 соответствуют восприятию яркости человеческим глазом.

Применение фильтров и свёрток

TensorFlow.js поддерживает 2D свёртки, что позволяет создавать фильтры для обработки изображений, например размытие или выявление границ:

const kernel = tf.tensor2d([
  [0, -1, 0],
  [-1, 5, -1],
  [0, -1, 0]
], [3, 3]);

const kernel4D = kernel.expandDims(2).expandDims(3);
const batchedTensor = normalizedTensor.expandDims(0); // [1, height, width, channels]

const filtered = tf.conv2d(batchedTensor, kernel4D, 1, 'same').squeeze();

Важно:

  • Свёртка требует 4D тензор [batch, height, width, channels].
  • Kernel нужно расширять до 4D [filterHeight, filterWidth, inChannels, outChannels].
  • squeeze() возвращает тензор к исходной размерности.

Обратное преобразование в Canvas

После обработки тензора его можно отобразить на Canvas:

const outputTensor = filtered.mul(255).toInt();
await tf.browser.toPixels(outputTensor, canvas);
  • tf.browser.toPixels автоматически преобразует тензор [height, width, channels] в формат ImageData.
  • Если тензор был нормализован, необходимо умножить на 255 и привести к целым значениям.

Эффективное управление памятью

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

  • tf.tidy — автоматически удаляет промежуточные тензоры.
  • Явное вызовы tensor.dispose() для больших объектов.
  • Минимизация дублирования тензоров при преобразовании форматов.

Примеры практического применения

  1. Предобработка данных для модели классификации изображений:

    • Нормализация.
    • Изменение размера через tf.image.resizeBilinear.
    • Разделение на батчи.
  2. Реализация фильтров изображений на клиентской стороне:

    • Инверсия цветов.
    • Размытие и резкость.
    • Переход в оттенки серого.
  3. Обработка потокового видео:

    • Использование <video> и tf.browser.fromPixels для анализа каждого кадра.
    • Реальное время распознавания объектов.

Работа с пикселями через тензоры позволяет объединять мощь GPU с удобством JavaScript и Canvas API, создавая высокопроизводительные веб-приложения для обработки изображений и машинного обучения.