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.Модели для обработки изображений обычно требуют тензоров фиксированного размера и типа данных. Перед подачей изображения в модель необходимо выполнить несколько шагов:
Нормализация — важный этап предобработки. Она включает приведение значений пикселей к диапазону, удобному для модели, и корректировку распределения по каналам.
Для каждого канала (R, G, B) выполняется стандартная операция:
[ = ]
где mean и std — среднее и стандартное
отклонение по каналу. Например, для моделей, обученных на ImageNet:
const mean = [0.485, 0.456, 0.406];
const std = [0.229, 0.224, 0.225];
Изображения в браузере обычно представлены в формате HWC (Height × Width × Channels). Многие модели ONNX требуют формат CHW (Channels × Height × Width).
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;
}
Особенности:
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 формате, поэтому
альфа-канал игнорируется.После предобработки создаётся объект 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] для
большинства моделей классификации.ImageData и масштабирование пикселей.ort.Tensor.Эта последовательность обеспечивает корректное соответствие входных данных требованиям модели, предотвращает ошибки в предсказаниях и позволяет максимально использовать возможности ORT Web для обработки изображений.