Нормализация и денормализация значений пикселей

В работе с моделями машинного обучения на изображениях одной из ключевых операций является преобразование значений пикселей в диапазон, удобный для сети. В ONNX Runtime Web для JavaScript нормализация и денормализация выполняются на этапе подготовки входных данных и обработки выходных значений модели.


Зачем нужна нормализация

Модели глубокого обучения чувствительны к масштабу входных данных. Изображения обычно представлены в формате Uint8Array или ImageData с пикселями в диапазоне 0–255. Перед подачей в сеть необходимо привести эти значения к диапазону, на котором обучалась модель, например:

  • [0, 1] — простое масштабирование на 255.
  • [-1, 1] — используется в моделях, обученных с центрированными значениями.

Нормализация ускоряет сходимость и уменьшает вероятность ошибок из-за переполнения или недостаточной точности.


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

Для работы с ONNX Runtime Web используется тип ort.Tensor. Пример создания тензора из изображения с нормализацией:

import * as ort from 'onnxruntime-web';

// Предположим, imageData — объект ImageData с width, height и data
const { width, height, data } = imageData;

// Преобразуем Uint8Array в Float32Array и нормализуем
const floatData = new Float32Array(width * height * 3);
for (let i = 0; i < width * height; i++) {
    floatData[i * 3]     = data[i * 4] / 255;       // R
    floatData[i * 3 + 1] = data[i * 4 + 1] / 255;   // G
    floatData[i * 3 + 2] = data[i * 4 + 2] / 255;   // B
}

// Создание тензора в формате [1, 3, height, width]
const inputTensor = new ort.Tensor('float32', floatData, [1, 3, height, width]);

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

  • Индекс i * 4 используется, так как ImageData.data содержит альфа-канал (RGBA).
  • Тензор формируется в порядке [batch, channel, height, width], как ожидают большинство ONNX-моделей для CV.
  • Деление на 255 обеспечивает нормализацию в диапазон [0,1].

Центрирование и стандартизация

Некоторые модели требуют центрации относительно среднего значения и масштабирования на стандартное отклонение:

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

for (let i = 0; i < width * height; i++) {
    floatData[i * 3]     = (data[i * 4] / 255 - mean[0]) / std[0];
    floatData[i * 3 + 1] = (data[i * 4 + 1] / 255 - mean[1]) / std[1];
    floatData[i * 3 + 2] = (data[i * 4 + 2] / 255 - mean[2]) / std[2];
}

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


Денормализация выходных данных

После обработки моделью результат часто возвращается в том же диапазоне, что и вход (например, [0,1] или центрированный). Для визуализации или сохранения изображения необходимо обратное преобразование:

const outputData = modelOutput.data; // Float32Array из тензора [1, 3, height, width]
const denormalized = new Uint8ClampedArray(width * height * 4);

for (let i = 0; i < width * height; i++) {
    denormalized[i * 4]     = Math.min(255, Math.max(0, outputData[i * 3] * 255));
    denormalized[i * 4 + 1] = Math.min(255, Math.max(0, outputData[i * 3 + 1] * 255));
    denormalized[i * 4 + 2] = Math.min(255, Math.max(0, outputData[i * 3 + 2] * 255));
    denormalized[i * 4 + 3] = 255; // альфа-канал
}

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

  • Использование Math.min и Math.max предотвращает выход за границы [0,255].
  • Для корректного отображения в Canvas или сохранения в PNG необходим полный альфа-канал.

Оптимизация для Web

ONNX Runtime Web поддерживает несколько вариантов исполнения (webgl, wasm). При больших изображениях нормализация и денормализация могут стать узким местом. Оптимизации:

  • Использовать тип Float32Array сразу при чтении пикселей.
  • Применять WebGL-шейдеры для пакетной нормализации при обработке большого объема изображений.
  • Параллелизация через Worker или OffscreenCanvas для ускорения подготовки данных.

Поддержка разных форматов входных данных

ONNX Runtime Web позволяет использовать:

  • ImageData — стандарт для Canvas.
  • HTMLImageElement — с предварительным копированием в Canvas.
  • TypedArrayFloat32Array или Uint8Array для прямой передачи.

Для каждого типа требуется корректная нормализация. Наиболее универсальный подход — всегда конвертировать в Float32Array и формировать тензор [1, 3, height, width].


Вывод

Нормализация и денормализация пикселей — базовые операции, определяющие корректность работы моделей компьютерного зрения в ONNX Runtime Web. Правильное масштабирование, центрирование и формирование тензоров позволяют получить точные прогнозы и корректно визуализировать результаты.