ONNX Runtime Web (ORT Web) представляет собой высокопроизводительную
JavaScript-библиотеку для запуска моделей в формате ONNX прямо в
браузере или на Node.js. Она обеспечивает переносимость моделей, высокую
скорость выполнения и совместимость с различными аппаратными
ускорителями, такими как WebAssembly (WASM) и WebGPU. Основной объект
для работы — Ort.InferenceSession, который управляет
загрузкой модели, подготовкой входных данных и выполнением
инференса.
import * as ort from 'onnxruntime-web';
const session = await ort.InferenceSession.create('model.onnx', {
executionProviders: ['wasm', 'webgl']
});
Ключевые моменты:
executionProviders определяет, на каком движке будет
выполняться модель: wasm для универсальной поддержки или
webgl/webgpu для ускорения на GPU.Модели семантической и инстанс-сегментации требуют специфической предобработки. Основные шаги включают:
[0,1] или нормализуются по среднему и стандартному
отклонению.Float32Array с размерностью [1, C, H, W],
где C — число каналов, H и W —
высота и ширина.Пример подготовки входного тензора:
function preprocessImage(imageData, width, height) {
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(imageData, 0, 0, width, height);
const imageArray = ctx.getImageData(0, 0, width, height).data;
const floatArray = new Float32Array(width * height * 3);
for (let i = 0; i < width * height; i++) {
floatArray[i] = imageArray[i * 4] / 255; // R
floatArray[i + width * height] = imageArray[i * 4 + 1] / 255; // G
floatArray[i + 2 * width * height] = imageArray[i * 4 + 2] / 255; // B
}
return new ort.Tensor('float32', floatArray, [1, 3, height, width]);
}
После подготовки тензора создается объект с ключами входных данных, где ключ совпадает с именем входного узла модели. Выполнение инференса возвращает объект с выходными тензорами, которые необходимо интерпретировать в зависимости от типа сегментации.
const inputTensor = preprocessImage(imgElement, 512, 512);
const feeds = { input: inputTensor };
const results = await session.run(feeds);
const outputTensor = results['output'];
Особенности:
[1, num_classes, H, W], где каждый канал соответствует
вероятностям для класса.boxes, masks, labels и
scores.Для визуализации семантической карты необходимо преобразовать вероятности в метки классов:
function getSegmentationMap(outputTensor) {
const [batch, numClasses, height, width] = outputTensor.dims;
const data = outputTensor.data;
const segmentationMap = new Uint8ClampedArray(height * width);
for (let h = 0; h < height; h++) {
for (let w = 0; w < width; w++) {
let maxProb = -Infinity;
let classIdx = -1;
for (let c = 0; c < numClasses; c++) {
const idx = c * height * width + h * width + w;
if (data[idx] > maxProb) {
maxProb = data[idx];
classIdx = c;
}
}
segmentationMap[h * width + w] = classIdx;
}
}
return segmentationMap;
}
Для визуализации можно сопоставить каждому классу цвет и отрисовать
на canvas.
Инстанс-сегментация требует дополнительной постобработки:
score_threshold).Пример обработки одного объекта:
function applyMask(ctx, maskTensor, box, color) {
const [height, width] = maskTensor.dims;
const data = maskTensor.data;
ctx.fillStyle = color;
ctx.globalAlpha = 0.5;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
if (data[y * width + x] > 0.5) {
ctx.fillRect(box[0] + x, box[1] + y, 1, 1);
}
}
}
ctx.globalAlpha = 1.0;
}
Особенности работы с инстанс-сегментацией:
box.webgpu
обеспечивает максимальную скорость на поддерживаемых устройствах.
wasm универсален, но медленнее.ImageData напрямую, избегать лишнего копирования в
массивы.ORT Web поддерживает работу:
script тег или
ES-модули, поддерживает WebAssembly и WebGPU.onnxruntime-web или
onnxruntime-node с идентичным API, но с использованием
нативного ускорения CPU/GPU.Особое внимание требуется при работе с WebGPU в браузере: проверяется
доступность через navigator.gpu и конфигурируются
соответствующие execution providers.