Нормализация изображений: mean, std, каналы, порядок HWC/CHW

ONNX Runtime Web (ORT Web) предоставляет возможность запускать модели в формате ONNX непосредственно в браузере или в среде Node.js с использованием JavaScript. Библиотека оптимизирована для выполнения инференса с поддержкой WebAssembly (WASM) и WebGL, что позволяет достигать высокой производительности даже на клиентских устройствах.


Инициализация сессии модели

Работа с ONNX Runtime Web начинается с создания сессии, которая загружает модель и управляет её выполнением:

import * as ort from 'onnxruntime-web';

const session = await ort.InferenceSession.create('model.onnx', {
  executionProviders: ['wasm'], // можно использовать 'webgl' для GPU
});

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

  • executionProviders определяет, каким способом будет выполняться модель: wasm — кроссплатформенный и безопасный способ через WebAssembly; webgl — использование GPU для ускорения обработки.
  • Создание сессии асинхронное, требуется использование await или Promise.

Подготовка входных данных

Модели для обработки изображений обычно требуют тензоров фиксированного размера и типа данных. Перед подачей изображения в модель необходимо выполнить несколько шагов:

  1. Изменение размера изображения до требуемой модели формы.
  2. Преобразование формата изображения в массив чисел.
  3. Нормализация значений пикселей.

Нормализация изображений

Нормализация — важный этап предобработки. Она включает приведение значений пикселей к диапазону, удобному для модели, и корректировку распределения по каналам.

Формулы нормализации

Для каждого канала (R, G, B) выполняется стандартная операция:

[ = ]

где mean и std — среднее и стандартное отклонение по каналу. Например, для моделей, обученных на ImageNet:

const mean = [0.485, 0.456, 0.406];
const std = [0.229, 0.224, 0.225];

Порядок каналов HWC и CHW

Изображения в браузере обычно представлены в формате HWC (Height × Width × Channels). Многие модели ONNX требуют формат CHW (Channels × Height × Width).

Преобразование HWC → CHW

function hwcToChw(imageData, height, width, channels) {
  const chwData = new Float32Array(height * width * channels);
  for (let c = 0; c < channels; c++) {
    for (let h = 0; h < height; h++) {
      for (let w = 0; w < width; w++) {
        chwData[c * height * width + h * width + w] =
          imageData[h * width * channels + w * channels + c];
      }
    }
  }
  return chwData;
}

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

  • В CHW порядок данных полностью меняется: сначала идут все значения первого канала, затем второго и третьего.
  • Правильное преобразование критично для корректного предсказания модели.

Пример полной предобработки изображения

function preprocessImage(image, height, width, mean, std) {
  const canvas = document.createElement('canvas');
  canvas.width = width;
  canvas.height = height;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(image, 0, 0, width, height);
  const imageData = ctx.getImageData(0, 0, width, height).data;

  const floatData = new Float32Array(width * height * 3);
  for (let i = 0; i < width * height; i++) {
    for (let c = 0; c < 3; c++) {
      const value = imageData[i * 4 + c] / 255; // масштабирование в [0,1]
      floatData[i * 3 + c] = (value - mean[c]) / std[c];
    }
  }

  return hwcToChw(floatData, height, width, 3);
}

Пояснения:

  • imageData содержит пиксели в RGBA формате, поэтому альфа-канал игнорируется.
  • Значения делятся на 255 для перевода в диапазон [0,1].
  • После нормализации применяется преобразование в CHW для модели.

Формирование входного тензора ONNX

После предобработки создаётся объект Tensor, который подаётся на вход сессии:

const inputTensor = new ort.Tensor('float32', preprocessedData, [1, 3, height, width]);

const feeds = { input: inputTensor };
const output = await session.run(feeds);

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

  • Тип данных должен совпадать с ожидаемым моделью (float32).
  • Форма тензора [batch, channels, height, width] для большинства моделей классификации.

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

  • Использование WebGL позволяет ускорить вычисления за счёт GPU, особенно на больших изображениях.
  • Предварительное изменение размера и нормализация на CPU позволяют снизить нагрузку на WebGL.
  • Можно объединять несколько изображений в один батч для одновременной обработки.

Итоговая структура предобработки

  1. Изображение → изменение размера.
  2. Получение ImageData и масштабирование пикселей.
  3. Нормализация с использованием mean/std для каждого канала.
  4. Преобразование из HWC в CHW.
  5. Формирование тензора ort.Tensor.
  6. Подача в сессию ONNX Runtime Web.

Эта последовательность обеспечивает корректное соответствие входных данных требованиям модели, предотвращает ошибки в предсказаниях и позволяет максимально использовать возможности ORT Web для обработки изображений.